b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] /proc vis rework
@ 2009-11-30 21:14 Andrew Lunn
  2009-12-11 22:58 ` Linus Lüssing
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Andrew Lunn @ 2009-11-30 21:14 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 503 bytes --]

Hi Folks

A while back i suggested we re-work the /proc/net/batman/vis format.
Attached are two patches to achieve this. One patch is for the kernel
model sources and the second extends batctl so that it can read from
the /proc file and output dot or json format as before. The patch
includes documentation for the new new batctl command in the man page.

I've tested the dot output using graphviz dot. However i don't have
any tools which use the json output. So that format is not tested.

    Andrew

[-- Attachment #2: batctl.diff --]
[-- Type: text/x-diff, Size: 14150 bytes --]

Index: batctl/vis.c
===================================================================
--- batctl/vis.c	(revision 0)
+++ batctl/vis.c	(revision 0)
@@ -0,0 +1,323 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "main.h"
+#include "vis.h"
+#include "functions.h"
+#include "bat-hosts.h"
+#include "proc.h"
+
+#define TQ_MAX_VALUE 255
+
+typedef void (*print_tq_t)(char * orig, char * from, const long tq);
+typedef void (*print_HNA_t)(char * orig, char * from);
+typedef void (*print_1st_t)(char * orig);
+typedef void (*print_2nd_t)(char * orig, char * from);
+typedef void (*print_header_t)(void);
+typedef void (*print_footer_t)(void);
+
+struct funcs 
+{
+  print_tq_t print_tq;
+  print_HNA_t print_HNA;
+  print_1st_t print_1st;
+  print_2nd_t print_2nd;
+  print_header_t print_header;
+  print_footer_t print_footer;
+};
+
+static bool with_HNA = true;
+static bool with_2nd = true;
+static bool with_names = true;
+
+static void 
+usage(void)
+{
+  printf("batctl vis dot {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+  printf("or\n");
+  printf("batctl vis json {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+}
+
+static void 
+dot_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t\"%s\" -> ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\"%s\" [label=\"%d.%d\"]\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+dot_print_HNA(char * orig, char * from)
+{
+        printf("\t\"%s\" -> ",
+               get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+        printf("\"%s\" [label=\"HNA\"]\n", 
+               get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+dot_print_1st(char * orig)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_2nd(char * orig, char * from)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\"\n",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_header(void) 
+{
+  printf("digraph {\n");
+}
+
+static void
+dot_print_footer(void) 
+{
+  printf("}\n");
+}
+
+const struct funcs dot_funcs = 
+  { dot_print_tq,
+    dot_print_HNA,
+    dot_print_1st,
+    dot_print_2nd,
+    dot_print_header,
+    dot_print_footer
+};
+
+static void 
+json_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("neighbor : \"%s\", label : \"%d.%d\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+json_print_HNA(char * orig, char * from)
+{
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("gateway : \"%s\", label : \"HNA\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_1st(char * orig)
+{
+  printf("\t{ primary : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_2nd(char * orig, char * from)
+{
+  printf("\t{ secondary : \"%s\", ",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+
+  printf("of : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+const struct funcs json_funcs = 
+  { json_print_tq,
+    json_print_HNA,
+    json_print_1st,
+    json_print_2nd,
+    NULL,
+    NULL
+};
+
+static FILE *
+open_vis(void) 
+{
+  char full_path[500];
+  
+  if (check_proc_dir("/proc") != EXIT_SUCCESS)
+    return NULL;
+
+  strncpy(full_path, PROC_ROOT_PATH, strlen(PROC_ROOT_PATH));
+  full_path[strlen(PROC_ROOT_PATH)] = '\0';
+  strncat(full_path, "vis", sizeof(full_path) - strlen(full_path));
+
+  return fopen(full_path, "r");
+}
+
+static int 
+format(const struct funcs *funcs)
+{
+  size_t len = 0;
+  ssize_t read;
+  char * line = NULL;
+  char * orig, * from;
+  char * duplet;
+  char * line_save_ptr;
+  char * duplet_save_ptr;
+  char * endptr;
+  char * value;
+  long tq;
+  char * flag;
+  
+  FILE * fp = open_vis(); 
+
+  if (!fp)
+    return EXIT_FAILURE;
+  
+  if (funcs->print_header)
+    funcs->print_header();
+  
+  while ((read = getline(&line, &len, fp)) != -1) {
+    /* First MAC address is the originator */
+    orig = strtok_r(line, " ", &line_save_ptr);
+
+    duplet_save_ptr = line_save_ptr;
+    while ((duplet = strtok_r(NULL, ",", &duplet_save_ptr)) != NULL) {
+      flag = strtok(duplet, " ");
+      if (!flag) 
+        continue;
+      if (!strcmp(flag, "TQ")) {
+        from = strtok(NULL, " ");
+        value = strtok(NULL, " ");
+        tq = strtoul(value, &endptr, 0);
+        funcs->print_tq(orig, from, tq);
+        continue;
+      }
+      if (!strcmp(flag, "HNA")) {
+        /* We have an HNA record */
+        if (!with_HNA) 
+          continue;
+        from = strtok(NULL, " ");
+        funcs->print_HNA(orig, from);
+        continue;
+      }
+      if (!strcmp(flag, "SEC") && with_2nd) {
+        /* We found a secondary interface MAC address.*/
+        from = strtok(NULL, " ");
+        funcs->print_2nd(orig, from);
+      }
+      if (!strcmp(flag, "PRIMARY") && with_2nd) {
+        /* We found a primary interface MAC address.*/
+        funcs->print_1st(orig);
+      }
+    }
+  }
+  
+  if (funcs->print_footer)
+    funcs->print_footer();
+  
+  if (line)
+    free(line);
+  return EXIT_SUCCESS;
+}
+
+int 
+vis(int argc, char *argv[])
+{
+  bool dot = false;
+  bool json = false;
+  int c;
+  
+  /* Do we know the requested format? */
+  if (strcmp(argv[1], "dot") == 0)
+    dot=true;
+  if (strcmp(argv[1], "json") == 0)
+    json=true;
+  
+  if (!dot && !json) {
+    usage();
+    return EXIT_FAILURE;
+  }
+  
+  /* Move over the output format */
+  argc--;
+  argv++;
+  
+  while (1) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      {"no-HNA", 0, 0, 'h'},
+      {"no-2nd", 0, 0, '2'},
+      {"numbers", 0, 0, 'n'},
+      {0, 0, 0, 0}
+    };
+    
+    c = getopt_long(argc, argv, "h2n", long_options, &option_index);
+    if (c == -1)
+      break;
+    
+    switch(c) {
+      case 'h':
+        with_HNA = false;
+        break;
+      case '2':
+        with_2nd = false;
+        break;
+      case 'n':
+        with_names = false;
+        break;
+      default:
+        usage();
+        return -1;
+    }
+  }
+  
+  if (with_names)
+	  bat_hosts_init();
+  
+  if (dot) 
+    return format(&dot_funcs);
+  
+  if (json)
+    return format(&json_funcs);
+
+  return EXIT_FAILURE;
+}
+  
+
Index: batctl/vis.h
===================================================================
--- batctl/vis.h	(revision 0)
+++ batctl/vis.h	(revision 0)
@@ -0,0 +1,21 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int vis(int argc, char * argv[]);
+
Index: batctl/functions.c
===================================================================
--- batctl/functions.c	(revision 1489)
+++ batctl/functions.c	(working copy)
@@ -99,7 +99,7 @@
 	return get_name_by_macaddr(mac_addr, read_opt);
 }
 
-static int check_proc_dir(char *dir)
+int check_proc_dir(char *dir)
 {
 	struct stat st;
 
Index: batctl/functions.h
===================================================================
--- batctl/functions.h	(revision 1489)
+++ batctl/functions.h	(working copy)
@@ -34,6 +34,7 @@
 char *get_name_by_macstr(char *mac_str, int read_opt);
 int read_file(char *dir, char *path, int read_opt);
 int write_file(char *dir, char *path, char *value);
+int check_proc_dir(char *dir);
 
 extern char read_buff[10];
 
Index: batctl/main.c
===================================================================
--- batctl/main.c	(revision 1489)
+++ batctl/main.c	(working copy)
@@ -35,6 +35,7 @@
 #include "traceroute.h"
 #include "tcpdump.h"
 #include "bisect.h"
+#include "vis.h"
 
 
 void print_usage(void) {
@@ -47,7 +48,7 @@
 	printf(" \tlog|l                           \tread the log produced by the kernel module\n");
 	printf(" \ttranslocal|tl                   \tdisplay the local translation table\n");
 	printf(" \ttransglobal|tg                  \tdisplay the global translation table\n");
-	printf(" \tvisformat|vf  [format]          \tdisplay or modify the vis output format\n");
+	printf(" \tvis [dot|JSON]                  \tdisplay the VIS data in dot or JSON format\n");
 	printf(" \taggregation|ag   [0|1]          \tdisplay or modify the packet aggregation setting\n");
 	printf("\n");
 	printf(" \tping|p        <destination>     \tping another batman adv host via layer 2\n");
@@ -74,7 +75,8 @@
 	}
 
 	/* check if user is root */
-	if ((strcmp(argv[1], "bisect") != 0) && ((getuid()) || (getgid()))) {
+	if (((strcmp(argv[1], "bisect") != 0) && (strcmp(argv[1], "vis") != 0))
+	    && ((getuid()) || (getgid()))) {
 		fprintf(stderr, "Error - you must be root to run '%s' !\n", argv[0]);
 		exit(EXIT_FAILURE);
 	}
@@ -119,9 +121,9 @@
 
 		ret = handle_proc_setting(argc - 1, argv + 1, PROC_ORIG_INTERVAL, orig_interval_usage);
 
-	} else if ((strcmp(argv[1], "visformat") == 0) || (strcmp(argv[1], "vf") == 0)) {
+	} if (strcmp(argv[1], "vis") == 0) {
 
-		ret = handle_proc_setting(argc - 1, argv + 1, PROC_VIS_FORMAT, vis_format_usage);
+		ret = vis(argc - 1, argv + 1);
 
 	} else if ((strcmp(argv[1], "aggregation") == 0) || (strcmp(argv[1], "ag") == 0)) {
 
Index: batctl/man/batctl.8
===================================================================
--- batctl/man/batctl.8	(revision 1489)
+++ batctl/man/batctl.8	(working copy)
@@ -63,9 +63,22 @@
 .IP "\fBtransglobal|tg\fP"
 Once started batctl will refresh the displayed global translation table every second. Use the "\-b" option to let batctl display the table only once (useful for scripts). If "\-n" was given batctl will not replace the mac addresses with bat\-host names in the output.
 .br
-.IP "\fBvisformat|vf	[format]\fP"
-If no parameter is given the current vis format settings are displayed otherwise the parameter is used to set the vis format.
+.IP "\fBvis dot\fP"
+Display the visualisation data in graphviz dot(1) format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
 .br
+.IP "\fBvis json\fP"
+Display the visualisation data in JSON format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
+.br
 .IP "\fBaggregation|ag	[0|1]\fP"
 If no parameter is given the current aggregation settings are displayed otherwise the parameter is used to enable or disable the packet aggregation.
 .br
Index: batctl/Makefile
===================================================================
--- batctl/Makefile	(revision 1489)
+++ batctl/Makefile	(working copy)
@@ -39,8 +39,8 @@
 EXTRA_MODULES_C := bisect.c
 EXTRA_MODULES_H := bisect.h
 
-SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c $(EXTRA_MODULES_C)
-SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h $(EXTRA_MODULES_H)
+SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C)
+SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H)
 SRC_O = $(SRC_C:.c=.o)
 
 PACKAGE_NAME = batctl

[-- Attachment #3: proc.diff --]
[-- Type: text/x-diff, Size: 7604 bytes --]

diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c
index ed4c734..e214936 100644
--- a/drivers/staging/batman-adv/proc.c
+++ b/drivers/staging/batman-adv/proc.c
@@ -322,91 +322,76 @@ static int proc_transt_global_open(struct inode *inode, struct file *file)
 	return single_open(file, proc_transt_global_read, NULL);
 }
 
-/* insert interface to the list of interfaces of one originator */
+/* 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 if_list_entry {
+	uint8_t addr[ETH_ALEN];
+	bool primary;
+	struct hlist_node list;
+};
+
+/* insert interface to the list of interfaces of one originator, if it
+ * does not already exist in the list */
 
 static void proc_vis_insert_interface(const uint8_t *interface,
-				      struct vis_if_list **if_entry,
+				      struct hlist_head *if_list,
 				      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)
+	struct if_list_entry *entry;
+	struct hlist_node *pos;
+
+
+	hlist_for_each_entry(entry, pos, if_list, list) {
+		if (compare_orig(entry->addr, (void *)interface))
 			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;
+	/* its a new address, add it to the list */
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return;
+	memcpy(entry->addr, interface, ETH_ALEN);
+	entry->primary = primary;
+	hlist_add_head(&entry->list, if_list);
+}
+
+static void proc_vis_read_prim_sec(struct seq_file *seq,
+				   struct hlist_head *if_list)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
+	char tmp_addr_str[ETH_STR_LEN];
+
+	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
+		if (entry->primary)
+			seq_printf(seq, "PRIMARY, ");
+		else {
+			addr_to_string(tmp_addr_str, entry->addr);
+			seq_printf(seq, "SEC %s, ", tmp_addr_str);
 		}
-		/* Rewind the list to its head */
-		*if_entry = head_if_entry;
+		hlist_del(&entry->list);
+		kfree(entry);
 	}
 }
-/* read an entry  */
 
+/* read an entry  */
 static void proc_vis_read_entry(struct seq_file *seq,
 				struct vis_info_entry *entry,
-				struct vis_if_list **if_entry,
-				uint8_t *vis_orig,
-				uint8_t current_format,
-				uint8_t first_line)
+				struct hlist_head *if_list,
+				uint8_t *vis_orig)
 {
-	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);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", gateway   : \"%s\", label : \"HNA\" }",
-				   (first_line ? "" : ",\n"), from, to);
-		}
+		proc_vis_insert_interface(vis_orig, if_list, true);
+		seq_printf(seq, "HNA %s, ", 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",
-				   from, to, int_part, frac_part);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }",
-				   (first_line ? "" : ",\n"), from, to, int_part, frac_part);
-		}
+		proc_vis_insert_interface(entry->src, if_list,
+					  compare_orig(entry->src, vis_orig));
+		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
 	}
 }
 
@@ -416,72 +401,40 @@ 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;
-	struct vis_if_list *if_entries = NULL;
+	HLIST_HEAD(vis_if_list);
 	int i;
-	uint8_t current_format, first_line = 1;
-#ifndef VIS_SUBCLUSTERS_DISABLED
+	uint8_t current_format;
 	char tmp_addr_str[ETH_STR_LEN];
-	struct vis_if_list *tmp_if_next;
-#endif /* VIS_SUBCLUSTERS_DISABLED */
 
 	current_format = vis_format;
 
 	rcu_read_lock();
 	if (list_empty(&if_list) || (!is_vis_server())) {
 		rcu_read_unlock();
-		if (current_format == DOT_DRAW)
-			seq_printf(seq, "digraph {\n}\n");
 		goto end;
 	}
 
 	rcu_read_unlock();
 
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "digraph {\n");
-
 	spin_lock(&vis_hash_lock);
 	while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
 		info = hashit->bucket->data;
 		entries = (struct vis_info_entry *)
 			((char *)info + sizeof(struct vis_info));
+		addr_to_string(tmp_addr_str, info->packet.vis_orig);
+		seq_printf(seq, "%s,", tmp_addr_str);
 
 		for (i = 0; i < info->packet.entries; i++) {
-			proc_vis_read_entry(seq, &entries[i], &if_entries,
-					    info->packet.vis_orig,
-					    current_format, first_line);
-			if (first_line)
-				first_line = 0;
+			proc_vis_read_entry(seq, &entries[i], &vis_if_list,
+					    info->packet.vis_orig);
 		}
 
-#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);
+		/* add primary/secondary records */
+		proc_vis_read_prim_sec(seq, &vis_if_list);
 
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "}\n");
-	else
 		seq_printf(seq, "\n");
+	}
+	spin_unlock(&vis_hash_lock);
 end:
 	return 0;
 }
diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h
index 16d3efd..761c5f8 100644
--- a/drivers/staging/batman-adv/proc.h
+++ b/drivers/staging/batman-adv/proc.h
@@ -38,12 +38,3 @@
 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;
-};

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-11-30 21:14 [B.A.T.M.A.N.] /proc vis rework Andrew Lunn
@ 2009-12-11 22:58 ` Linus Lüssing
  2009-12-11 23:20   ` Linus Lüssing
                     ` (2 more replies)
  2009-12-13 16:11 ` Andrew Lunn
  2009-12-19 17:01 ` Marek Lindner
  2 siblings, 3 replies; 13+ messages in thread
From: Linus Lüssing @ 2009-12-11 22:58 UTC (permalink / raw)
  To: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 1087 bytes --]

Hi Andrew,

your patch seems to work pretty well here, tested it with 9
batman-nodes in the same room. Nevertheless I found a couple of
smaller bugs in there:
- batctl segfaults, if "batctl vis" has no following argument
- batctl now displays the help-page in certain situations where we
  don't want it to
- batctl ommits the first TQ tupel
The attached patch for your patch should fix these issues :).

And I wanted to ask, what do you think about unifying the specific
help output? For instance having this "Usage: ..."-header and the
alignment for the following items the same way as it is done for
other batctl commands as well.

Cheers, Linus

PS:
Hmm, I'm also missing a couple of link/TQ entries already in the
unified /proc/../vis. The 9 nodes in the same room should be able
to see each other - the originator table on those nodes is also
saying so. But I think I had seen this before without your patch,
the problems has to be somewhere else. I'm attaching a batctl-vis-
and proc-vis-output of the setup here too, just in case someone
might spot some (more) parsing mistakes.

[-- Attachment #1.2: batctl-vis-patch.patch --]
[-- Type: text/x-diff, Size: 1760 bytes --]

diff -ur batctl/functions.c batctl2/functions.c
--- batctl/functions.c	2009-12-11 23:10:31.000000000 +0100
+++ batctl2/functions.c	2009-12-11 23:09:48.000000000 +0100
@@ -161,10 +161,10 @@
 
 	if (read_opt & USE_READ_BUFF) {
 		read_ptr = read_buff;
-		read_len = sizeof(read_buff);
+		read_len = sizeof(read_buff)-1;
 	} else {
 		read_ptr = lbuff;
-		read_len = sizeof(lbuff);
+		read_len = sizeof(lbuff)-1;
 	}
 
 open:
diff -ur batctl/main.c batctl2/main.c
--- batctl/main.c	2009-12-11 23:10:31.000000000 +0100
+++ batctl2/main.c	2009-12-11 23:09:48.000000000 +0100
@@ -121,7 +121,7 @@
 
 		ret = handle_proc_setting(argc - 1, argv + 1, PROC_ORIG_INTERVAL, orig_interval_usage);
 
-	} if (strcmp(argv[1], "vis") == 0) {
+	} else if (strcmp(argv[1], "vis") == 0) {
 
 		ret = vis(argc - 1, argv + 1);
 
diff -ur batctl/vis.c batctl2/vis.c
--- batctl/vis.c	2009-12-11 23:10:48.000000000 +0100
+++ batctl2/vis.c	2009-12-11 23:29:04.000000000 +0100
@@ -215,7 +215,7 @@
   
   while ((read = getline(&line, &len, fp)) != -1) {
     /* First MAC address is the originator */
-    orig = strtok_r(line, " ", &line_save_ptr);
+    orig = strtok_r(line, ",", &line_save_ptr);
 
     duplet_save_ptr = line_save_ptr;
     while ((duplet = strtok_r(NULL, ",", &duplet_save_ptr)) != NULL) {
@@ -265,10 +265,12 @@
   int c;
   
   /* Do we know the requested format? */
-  if (strcmp(argv[1], "dot") == 0)
-    dot=true;
-  if (strcmp(argv[1], "json") == 0)
-    json=true;
+  if(argc > 1) {
+    if (strcmp(argv[1], "dot") == 0)
+      dot=true;
+    if (strcmp(argv[1], "json") == 0)
+      json=true;
+  }
   
   if (!dot && !json) {
     usage();
@@ -319,5 +321,3 @@
 
   return EXIT_FAILURE;
 }
-  
-

[-- Attachment #1.3: batctl-vis.log --]
[-- Type: text/plain, Size: 2212 bytes --]

06:24:01:b7:69:c1,TQ 06:24:01:b7:6a:d9 247, TQ 06:24:01:b7:6a:d1 247, TQ 06:24:01:b7:61:1b 255, TQ 06:24:01:b7:6a:b3 255, TQ 06:24:01:b7:6a:fd 255, TQ 06:24:01:b7:61:49 251, HNA 72:43:e7:02:8f:96, HNA 00:24:01:b7:69:c1, PRIMARY, 
06:24:01:b7:61:19,TQ 06:24:01:b7:6a:d9 249, TQ 06:24:01:b7:6a:d1 255, TQ 06:24:01:b7:61:1b 255, TQ 06:24:01:b7:6a:b3 247, TQ 00:13:e8:50:c0:ff 248, HNA 00:24:01:b7:61:19, HNA d6:59:34:c6:ee:ce, PRIMARY, 
06:24:01:b7:6a:b3,TQ 06:24:01:b7:69:c1 251, TQ 06:24:01:b7:6a:d9 255, TQ 06:24:01:b7:6a:d1 254, TQ 06:24:01:b7:61:19 247, TQ 06:24:01:b7:61:1b 255, TQ 00:13:e8:50:c0:ff 247, TQ 06:24:01:b7:6a:fd 255, TQ 06:24:01:b7:61:49 255, HNA 6e:49:09:0e:30:1f, HNA 00:24:01:b7:6a:b3, PRIMARY, 
06:24:01:b7:6a:fd,TQ 06:24:01:b7:69:c1 255, TQ 06:24:01:b7:6a:d9 251, TQ 06:24:01:b7:61:19 247, TQ 06:24:01:b7:61:1b 255, TQ 06:24:01:b7:6a:b3 255, TQ 00:13:e8:50:c0:ff 251, TQ 06:24:01:b7:61:49 247, HNA be:38:d5:48:ad:58, HNA 00:24:01:b7:6a:fd, PRIMARY, 
06:24:01:b7:61:49,TQ 06:24:01:b7:69:c1 254, TQ 06:24:01:b7:6a:d1 251, TQ 06:24:01:b7:61:19 255, TQ 06:24:01:b7:61:1b 252, TQ 06:24:01:b7:6a:b3 255, TQ 00:13:e8:50:c0:ff 255, TQ 06:24:01:b7:6a:fd 255, HNA 00:24:01:b7:61:49, HNA 86:44:91:74:79:cc, PRIMARY, 
06:24:01:b7:6a:d9,TQ 06:24:01:b7:69:c1 255, TQ 06:24:01:b7:6a:d1 251, TQ 06:24:01:b7:61:19 255, TQ 06:24:01:b7:61:1b 251, TQ 06:24:01:b7:6a:b3 255, TQ 00:13:e8:50:c0:ff 255, TQ 06:24:01:b7:6a:fd 247, TQ 06:24:01:b7:61:49 250, HNA 00:24:01:b7:6a:d9, HNA 9a:6e:8f:f0:90:a2, PRIMARY, 
06:24:01:b7:6a:d1,TQ 06:24:01:b7:69:c1 251, TQ 06:24:01:b7:6a:d9 250, TQ 06:24:01:b7:61:19 255, TQ 06:24:01:b7:61:1b 255, TQ 06:24:01:b7:6a:b3 253, TQ 00:13:e8:50:c0:ff 251, TQ 06:24:01:b7:6a:fd 255, HNA 00:24:01:b7:6a:d1, HNA 9a:8e:ad:ea:e0:dc, PRIMARY, 
06:24:01:b7:61:1b,TQ 06:24:01:b7:6a:d9 255, TQ 06:24:01:b7:6a:d1 255, TQ 06:24:01:b7:61:19 247, TQ 06:24:01:b7:6a:b3 255, TQ 00:13:e8:50:c0:ff 255, TQ 06:24:01:b7:6a:fd 251, HNA 5e:2b:6b:67:d7:17, HNA 00:24:01:b7:61:1b, PRIMARY, 
00:13:e8:50:c0:ff,TQ 06:24:01:b7:69:c1 255, TQ 06:24:01:b7:6a:d9 251, TQ 06:24:01:b7:6a:d1 255, TQ 06:24:01:b7:61:1b 247, TQ 06:24:01:b7:6a:b3 255, TQ 06:24:01:b7:6a:fd 255, HNA 72:c5:18:83:3a:a3, PRIMARY, 

[-- Attachment #1.4: proc-vis.log --]
[-- Type: text/plain, Size: 5233 bytes --]

digraph {
	"06:24:01:b7:69:c1" -> "06:24:01:b7:6a:d9" [label="1.32"]
	"06:24:01:b7:69:c1" -> "06:24:01:b7:6a:d1" [label="1.32"]
	"06:24:01:b7:69:c1" -> "06:24:01:b7:61:1b" [label="1.0"]
	"06:24:01:b7:69:c1" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"06:24:01:b7:69:c1" -> "06:24:01:b7:6a:fd" [label="1.0"]
	"06:24:01:b7:69:c1" -> "06:24:01:b7:61:49" [label="1.15"]
	"06:24:01:b7:69:c1" -> "72:43:e7:02:8f:96" [label="HNA"]
	"06:24:01:b7:69:c1" -> "00:24:01:b7:69:c1" [label="HNA"]
	subgraph "cluster_06:24:01:b7:69:c1" {
		"06:24:01:b7:69:c1" [peripheries=2]
	}
	"06:24:01:b7:61:19" -> "06:24:01:b7:6a:d9" [label="1.24"]
	"06:24:01:b7:61:19" -> "06:24:01:b7:6a:d1" [label="1.0"]
	"06:24:01:b7:61:19" -> "06:24:01:b7:61:1b" [label="1.0"]
	"06:24:01:b7:61:19" -> "06:24:01:b7:6a:b3" [label="1.32"]
	"06:24:01:b7:61:19" -> "00:13:e8:50:c0:ff" [label="1.28"]
	"06:24:01:b7:61:19" -> "00:24:01:b7:61:19" [label="HNA"]
	"06:24:01:b7:61:19" -> "d6:59:34:c6:ee:ce" [label="HNA"]
	subgraph "cluster_06:24:01:b7:61:19" {
		"06:24:01:b7:61:19" [peripheries=2]
	}
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:69:c1" [label="1.15"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:6a:d9" [label="1.0"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:6a:d1" [label="1.3"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:61:19" [label="1.32"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:61:1b" [label="1.0"]
	"06:24:01:b7:6a:b3" -> "00:13:e8:50:c0:ff" [label="1.32"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:6a:fd" [label="1.0"]
	"06:24:01:b7:6a:b3" -> "06:24:01:b7:61:49" [label="1.0"]
	"06:24:01:b7:6a:b3" -> "6e:49:09:0e:30:1f" [label="HNA"]
	"06:24:01:b7:6a:b3" -> "00:24:01:b7:6a:b3" [label="HNA"]
	subgraph "cluster_06:24:01:b7:6a:b3" {
		"06:24:01:b7:6a:b3" [peripheries=2]
	}
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:69:c1" [label="1.0"]
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:6a:d9" [label="1.15"]
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:61:19" [label="1.32"]
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:61:1b" [label="1.0"]
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"06:24:01:b7:6a:fd" -> "00:13:e8:50:c0:ff" [label="1.15"]
	"06:24:01:b7:6a:fd" -> "06:24:01:b7:61:49" [label="1.32"]
	"06:24:01:b7:6a:fd" -> "be:38:d5:48:ad:58" [label="HNA"]
	"06:24:01:b7:6a:fd" -> "00:24:01:b7:6a:fd" [label="HNA"]
	subgraph "cluster_06:24:01:b7:6a:fd" {
		"06:24:01:b7:6a:fd" [peripheries=2]
	}
	"06:24:01:b7:61:49" -> "06:24:01:b7:69:c1" [label="1.3"]
	"06:24:01:b7:61:49" -> "06:24:01:b7:6a:d1" [label="1.15"]
	"06:24:01:b7:61:49" -> "06:24:01:b7:61:19" [label="1.0"]
	"06:24:01:b7:61:49" -> "06:24:01:b7:61:1b" [label="1.11"]
	"06:24:01:b7:61:49" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"06:24:01:b7:61:49" -> "00:13:e8:50:c0:ff" [label="1.0"]
	"06:24:01:b7:61:49" -> "06:24:01:b7:6a:fd" [label="1.0"]
	"06:24:01:b7:61:49" -> "00:24:01:b7:61:49" [label="HNA"]
	"06:24:01:b7:61:49" -> "86:44:91:74:79:cc" [label="HNA"]
	subgraph "cluster_06:24:01:b7:61:49" {
		"06:24:01:b7:61:49" [peripheries=2]
	}
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:69:c1" [label="1.0"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:6a:d1" [label="1.15"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:61:19" [label="1.0"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:61:1b" [label="1.15"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"06:24:01:b7:6a:d9" -> "00:13:e8:50:c0:ff" [label="1.0"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:6a:fd" [label="1.32"]
	"06:24:01:b7:6a:d9" -> "06:24:01:b7:61:49" [label="1.20"]
	"06:24:01:b7:6a:d9" -> "00:24:01:b7:6a:d9" [label="HNA"]
	"06:24:01:b7:6a:d9" -> "9a:6e:8f:f0:90:a2" [label="HNA"]
	subgraph "cluster_06:24:01:b7:6a:d9" {
		"06:24:01:b7:6a:d9" [peripheries=2]
	}
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:69:c1" [label="1.15"]
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:6a:d9" [label="1.20"]
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:61:19" [label="1.0"]
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:61:1b" [label="1.0"]
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:6a:b3" [label="1.7"]
	"06:24:01:b7:6a:d1" -> "00:13:e8:50:c0:ff" [label="1.15"]
	"06:24:01:b7:6a:d1" -> "06:24:01:b7:6a:fd" [label="1.0"]
	"06:24:01:b7:6a:d1" -> "00:24:01:b7:6a:d1" [label="HNA"]
	"06:24:01:b7:6a:d1" -> "9a:8e:ad:ea:e0:dc" [label="HNA"]
	subgraph "cluster_06:24:01:b7:6a:d1" {
		"06:24:01:b7:6a:d1" [peripheries=2]
	}
	"06:24:01:b7:61:1b" -> "06:24:01:b7:6a:d9" [label="1.0"]
	"06:24:01:b7:61:1b" -> "06:24:01:b7:6a:d1" [label="1.0"]
	"06:24:01:b7:61:1b" -> "06:24:01:b7:61:19" [label="1.32"]
	"06:24:01:b7:61:1b" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"06:24:01:b7:61:1b" -> "00:13:e8:50:c0:ff" [label="1.0"]
	"06:24:01:b7:61:1b" -> "06:24:01:b7:6a:fd" [label="1.15"]
	"06:24:01:b7:61:1b" -> "5e:2b:6b:67:d7:17" [label="HNA"]
	"06:24:01:b7:61:1b" -> "00:24:01:b7:61:1b" [label="HNA"]
	subgraph "cluster_06:24:01:b7:61:1b" {
		"06:24:01:b7:61:1b" [peripheries=2]
	}
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:69:c1" [label="1.0"]
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:6a:d9" [label="1.15"]
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:6a:d1" [label="1.0"]
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:61:1b" [label="1.32"]
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:6a:b3" [label="1.0"]
	"00:13:e8:50:c0:ff" -> "06:24:01:b7:6a:fd" [label="1.0"]
	"00:13:e8:50:c0:ff" -> "72:c5:18:83:3a:a3" [label="HNA"]
	subgraph "cluster_00:13:e8:50:c0:ff" {
		"00:13:e8:50:c0:ff" [peripheries=2]
	}
}

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-12-11 22:58 ` Linus Lüssing
@ 2009-12-11 23:20   ` Linus Lüssing
  2009-12-12 10:43   ` Andrew Lunn
  2009-12-13 16:14   ` Andrew Lunn
  2 siblings, 0 replies; 13+ messages in thread
From: Linus Lüssing @ 2009-12-11 23:20 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 1356 bytes --]

Ah, sorry, and skip the functions.c-part please, I had submitted a
seperate patch for that here already.

Cheers, Linus

On Fri, Dec 11, 2009 at 11:58:35PM +0100, Linus Lüssing wrote:
> Hi Andrew,
> 
> your patch seems to work pretty well here, tested it with 9
> batman-nodes in the same room. Nevertheless I found a couple of
> smaller bugs in there:
> - batctl segfaults, if "batctl vis" has no following argument
> - batctl now displays the help-page in certain situations where we
>   don't want it to
> - batctl ommits the first TQ tupel
> The attached patch for your patch should fix these issues :).
> 
> And I wanted to ask, what do you think about unifying the specific
> help output? For instance having this "Usage: ..."-header and the
> alignment for the following items the same way as it is done for
> other batctl commands as well.
> 
> Cheers, Linus
> 
> PS:
> Hmm, I'm also missing a couple of link/TQ entries already in the
> unified /proc/../vis. The 9 nodes in the same room should be able
> to see each other - the originator table on those nodes is also
> saying so. But I think I had seen this before without your patch,
> the problems has to be somewhere else. I'm attaching a batctl-vis-
> and proc-vis-output of the setup here too, just in case someone
> might spot some (more) parsing mistakes.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-12-11 22:58 ` Linus Lüssing
  2009-12-11 23:20   ` Linus Lüssing
@ 2009-12-12 10:43   ` Andrew Lunn
  2009-12-13 16:14   ` Andrew Lunn
  2 siblings, 0 replies; 13+ messages in thread
From: Andrew Lunn @ 2009-12-12 10:43 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking

On Fri, Dec 11, 2009 at 11:58:35PM +0100, Linus L??ssing wrote:
> Hi Andrew,
> 
> your patch seems to work pretty well here, tested it with 9
> batman-nodes in the same room. Nevertheless I found a couple of
> smaller bugs in there:
> - batctl segfaults, if "batctl vis" has no following argument
> - batctl now displays the help-page in certain situations where we
>   don't want it to
> - batctl ommits the first TQ tupel
> The attached patch for your patch should fix these issues :).

Thanks for the review. I will try to look at the details today or
tomorrow.

	Andrew

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-11-30 21:14 [B.A.T.M.A.N.] /proc vis rework Andrew Lunn
  2009-12-11 22:58 ` Linus Lüssing
@ 2009-12-13 16:11 ` Andrew Lunn
  2009-12-13 20:02   ` Linus Lüssing
  2009-12-19 17:01 ` Marek Lindner
  2 siblings, 1 reply; 13+ messages in thread
From: Andrew Lunn @ 2009-12-13 16:11 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking; +Cc: Marek Lindner

Subject: batctl: Parse the new /proc vis format.

Add code to batctl so that it can parse /proc/net/batman-adv/vis and
generate either graphvis dot or JSON output.

Tested and bugs found and fixed by Linus Luessing.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Index: vis.c
===================================================================
--- vis.c	(revision 0)
+++ vis.c	(revision 0)
@@ -0,0 +1,326 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "main.h"
+#include "vis.h"
+#include "functions.h"
+#include "bat-hosts.h"
+#include "proc.h"
+
+#define TQ_MAX_VALUE 255
+
+typedef void (*print_tq_t)(char * orig, char * from, const long tq);
+typedef void (*print_HNA_t)(char * orig, char * from);
+typedef void (*print_1st_t)(char * orig);
+typedef void (*print_2nd_t)(char * orig, char * from);
+typedef void (*print_header_t)(void);
+typedef void (*print_footer_t)(void);
+
+struct funcs 
+{
+  print_tq_t print_tq;
+  print_HNA_t print_HNA;
+  print_1st_t print_1st;
+  print_2nd_t print_2nd;
+  print_header_t print_header;
+  print_footer_t print_footer;
+};
+
+static bool with_HNA = true;
+static bool with_2nd = true;
+static bool with_names = true;
+
+static void 
+usage(void)
+{
+  printf("batctl vis dot {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+  printf("or\n");
+  printf("batctl vis json {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+}
+
+static void 
+dot_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t\"%s\" -> ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\"%s\" [label=\"%d.%d\"]\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+dot_print_HNA(char * orig, char * from)
+{
+        printf("\t\"%s\" -> ",
+               get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+        printf("\"%s\" [label=\"HNA\"]\n", 
+               get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+dot_print_1st(char * orig)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_2nd(char * orig, char * from)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\"\n",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_header(void) 
+{
+  printf("digraph {\n");
+}
+
+static void
+dot_print_footer(void) 
+{
+  printf("}\n");
+}
+
+const struct funcs dot_funcs = 
+  { dot_print_tq,
+    dot_print_HNA,
+    dot_print_1st,
+    dot_print_2nd,
+    dot_print_header,
+    dot_print_footer
+};
+
+static void 
+json_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("neighbor : \"%s\", label : \"%d.%d\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+json_print_HNA(char * orig, char * from)
+{
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("gateway : \"%s\", label : \"HNA\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_1st(char * orig)
+{
+  printf("\t{ primary : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_2nd(char * orig, char * from)
+{
+  printf("\t{ secondary : \"%s\", ",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+
+  printf("of : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+const struct funcs json_funcs = 
+  { json_print_tq,
+    json_print_HNA,
+    json_print_1st,
+    json_print_2nd,
+    NULL,
+    NULL
+};
+
+static FILE *
+open_vis(void) 
+{
+  char full_path[500];
+  
+  if (check_proc_dir("/proc") != EXIT_SUCCESS)
+    return NULL;
+
+  strncpy(full_path, PROC_ROOT_PATH, strlen(PROC_ROOT_PATH));
+  full_path[strlen(PROC_ROOT_PATH)] = '\0';
+  strncat(full_path, "vis", sizeof(full_path) - strlen(full_path));
+
+  return fopen(full_path, "r");
+}
+
+static int 
+format(const struct funcs *funcs)
+{
+  size_t len = 0;
+  ssize_t read;
+  char * line = NULL;
+  char * orig, * from;
+  char * duplet;
+  char * line_save_ptr;
+  char * duplet_save_ptr;
+  char * endptr;
+  char * value;
+  long tq;
+  char * flag;
+  
+  FILE * fp = open_vis(); 
+
+  if (!fp)
+    return EXIT_FAILURE;
+  
+  if (funcs->print_header)
+    funcs->print_header();
+  
+  while ((read = getline(&line, &len, fp)) != -1) {
+    /* First MAC address is the originator */
+    orig = strtok_r(line, ",", &line_save_ptr);
+
+    duplet_save_ptr = line_save_ptr;
+    while ((duplet = strtok_r(NULL, ",", &duplet_save_ptr)) != NULL) {
+      flag = strtok(duplet, " ");
+      if (!flag) 
+        continue;
+      if (!strcmp(flag, "TQ")) {
+        from = strtok(NULL, " ");
+        value = strtok(NULL, " ");
+        tq = strtoul(value, &endptr, 0);
+        funcs->print_tq(orig, from, tq);
+        continue;
+      }
+      if (!strcmp(flag, "HNA")) {
+        /* We have an HNA record */
+        if (!with_HNA) 
+          continue;
+        from = strtok(NULL, " ");
+        funcs->print_HNA(orig, from);
+        continue;
+      }
+      if (!strcmp(flag, "SEC") && with_2nd) {
+        /* We found a secondary interface MAC address.*/
+        from = strtok(NULL, " ");
+        funcs->print_2nd(orig, from);
+      }
+      if (!strcmp(flag, "PRIMARY") && with_2nd) {
+        /* We found a primary interface MAC address.*/
+        funcs->print_1st(orig);
+      }
+    }
+  }
+  
+  if (funcs->print_footer)
+    funcs->print_footer();
+  
+  if (line)
+    free(line);
+  return EXIT_SUCCESS;
+}
+
+int 
+vis(int argc, char *argv[])
+{
+  bool dot = false;
+  bool json = false;
+  int c;
+
+  if (argc <=1) {
+    usage();
+    return EXIT_FAILURE;
+  }
+  
+  /* Do we know the requested format? */
+  if (strcmp(argv[1], "dot") == 0)
+    dot=true;
+  if (strcmp(argv[1], "json") == 0)
+    json=true;
+  
+  if (!dot && !json) {
+    usage();
+    return EXIT_FAILURE;
+  }
+  
+  /* Move over the output format */
+  argc--;
+  argv++;
+  
+  while (1) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      {"no-HNA", 0, 0, 'h'},
+      {"no-2nd", 0, 0, '2'},
+      {"numbers", 0, 0, 'n'},
+      {0, 0, 0, 0}
+    };
+    
+    c = getopt_long(argc, argv, "h2n", long_options, &option_index);
+    if (c == -1)
+      break;
+    
+    switch(c) {
+      case 'h':
+        with_HNA = false;
+        break;
+      case '2':
+        with_2nd = false;
+        break;
+      case 'n':
+        with_names = false;
+        break;
+      default:
+        usage();
+        return -1;
+    }
+  }
+  
+  if (with_names)
+	  bat_hosts_init();
+  
+  if (dot) 
+    return format(&dot_funcs);
+  
+  if (json)
+    return format(&json_funcs);
+
+  return EXIT_FAILURE;
+}
Index: vis.h
===================================================================
--- vis.h	(revision 0)
+++ vis.h	(revision 0)
@@ -0,0 +1,21 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int vis(int argc, char * argv[]);
+
Index: functions.c
===================================================================
--- functions.c	(revision 1489)
+++ functions.c	(working copy)
@@ -99,7 +99,7 @@
 	return get_name_by_macaddr(mac_addr, read_opt);
 }
 
-static int check_proc_dir(char *dir)
+int check_proc_dir(char *dir)
 {
 	struct stat st;
 
Index: functions.h
===================================================================
--- functions.h	(revision 1489)
+++ functions.h	(working copy)
@@ -34,6 +34,7 @@
 char *get_name_by_macstr(char *mac_str, int read_opt);
 int read_file(char *dir, char *path, int read_opt);
 int write_file(char *dir, char *path, char *value);
+int check_proc_dir(char *dir);
 
 extern char read_buff[10];
 
Index: main.c
===================================================================
--- main.c	(revision 1489)
+++ main.c	(working copy)
@@ -35,6 +35,7 @@
 #include "traceroute.h"
 #include "tcpdump.h"
 #include "bisect.h"
+#include "vis.h"
 
 
 void print_usage(void) {
@@ -47,7 +48,7 @@
 	printf(" \tlog|l                           \tread the log produced by the kernel module\n");
 	printf(" \ttranslocal|tl                   \tdisplay the local translation table\n");
 	printf(" \ttransglobal|tg                  \tdisplay the global translation table\n");
-	printf(" \tvisformat|vf  [format]          \tdisplay or modify the vis output format\n");
+	printf(" \tvis [dot|JSON]                  \tdisplay the VIS data in dot or JSON format\n");
 	printf(" \taggregation|ag   [0|1]          \tdisplay or modify the packet aggregation setting\n");
 	printf("\n");
 	printf(" \tping|p        <destination>     \tping another batman adv host via layer 2\n");
@@ -74,7 +75,8 @@
 	}
 
 	/* check if user is root */
-	if ((strcmp(argv[1], "bisect") != 0) && ((getuid()) || (getgid()))) {
+	if (((strcmp(argv[1], "bisect") != 0) && (strcmp(argv[1], "vis") != 0))
+	    && ((getuid()) || (getgid()))) {
 		fprintf(stderr, "Error - you must be root to run '%s' !\n", argv[0]);
 		exit(EXIT_FAILURE);
 	}
@@ -119,9 +121,9 @@
 
 		ret = handle_proc_setting(argc - 1, argv + 1, PROC_ORIG_INTERVAL, orig_interval_usage);
 
-	} else if ((strcmp(argv[1], "visformat") == 0) || (strcmp(argv[1], "vf") == 0)) {
+	} else if (strcmp(argv[1], "vis") == 0) {
 
-		ret = handle_proc_setting(argc - 1, argv + 1, PROC_VIS_FORMAT, vis_format_usage);
+		ret = vis(argc - 1, argv + 1);
 
 	} else if ((strcmp(argv[1], "aggregation") == 0) || (strcmp(argv[1], "ag") == 0)) {
 
Index: man/batctl.8
===================================================================
--- man/batctl.8	(revision 1489)
+++ man/batctl.8	(working copy)
@@ -63,9 +63,22 @@
 .IP "\fBtransglobal|tg\fP"
 Once started batctl will refresh the displayed global translation table every second. Use the "\-b" option to let batctl display the table only once (useful for scripts). If "\-n" was given batctl will not replace the mac addresses with bat\-host names in the output.
 .br
-.IP "\fBvisformat|vf	[format]\fP"
-If no parameter is given the current vis format settings are displayed otherwise the parameter is used to set the vis format.
+.IP "\fBvis dot\fP"
+Display the visualisation data in graphviz dot(1) format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
 .br
+.IP "\fBvis json\fP"
+Display the visualisation data in JSON format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
+.br
 .IP "\fBaggregation|ag	[0|1]\fP"
 If no parameter is given the current aggregation settings are displayed otherwise the parameter is used to enable or disable the packet aggregation.
 .br
Index: Makefile
===================================================================
--- Makefile	(revision 1489)
+++ Makefile	(working copy)
@@ -39,8 +39,8 @@
 EXTRA_MODULES_C := bisect.c
 EXTRA_MODULES_H := bisect.h
 
-SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c $(EXTRA_MODULES_C)
-SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h $(EXTRA_MODULES_H)
+SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C)
+SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H)
 SRC_O = $(SRC_C:.c=.o)
 
 PACKAGE_NAME = batctl

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-12-11 22:58 ` Linus Lüssing
  2009-12-11 23:20   ` Linus Lüssing
  2009-12-12 10:43   ` Andrew Lunn
@ 2009-12-13 16:14   ` Andrew Lunn
  2 siblings, 0 replies; 13+ messages in thread
From: Andrew Lunn @ 2009-12-13 16:14 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking

> And I wanted to ask, what do you think about unifying the specific
> help output? For instance having this "Usage: ..."-header and the
> alignment for the following items the same way as it is done for
> other batctl commands as well.

I thought about that. However the architecture allows different
formats to be easily added. Different formats might need different
optional arguments. It just seems easier the way it is at the moment.

	 Andrew


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-12-13 16:11 ` Andrew Lunn
@ 2009-12-13 20:02   ` Linus Lüssing
  0 siblings, 0 replies; 13+ messages in thread
From: Linus Lüssing @ 2009-12-13 20:02 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking


[-- Attachment #1.1: Type: text/plain, Size: 254 bytes --]

Hmm, everything related to vis-format can be removed from the
kernel(-module) as well, can't it?
This patch applying on top of your batman-adv patch should remove
the vis-format-proc entry and all this dead code if I didn't miss
anything.

Cheers, Linus

[-- Attachment #1.2: batman-adv-vis-format-rm.patch --]
[-- Type: text/x-diff, Size: 3859 bytes --]

diff -ru batman-adv-kernelland/proc.c batman-adv-kernelland2/proc.c
--- batman-adv-kernelland/proc.c	2009-12-13 20:53:50.000000000 +0100
+++ batman-adv-kernelland2/proc.c	2009-12-13 20:53:07.000000000 +0100
@@ -29,8 +29,6 @@
 #include "vis.h"
 #include "compat.h"
 
-static uint8_t vis_format = DOT_DRAW;
-
 static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
 static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
 static struct proc_dir_entry *proc_transt_local_file;
@@ -403,11 +401,8 @@
 	struct vis_info_entry *entries;
 	HLIST_HEAD(vis_if_list);
 	int i;
-	uint8_t current_format;
 	char tmp_addr_str[ETH_STR_LEN];
 
-	current_format = vis_format;
-
 	rcu_read_lock();
 	if (list_empty(&if_list) || (!is_vis_server())) {
 		rcu_read_unlock();
@@ -473,55 +468,6 @@
 	return single_open(file, proc_vis_read, NULL);
 }
 
-static int proc_vis_format_read(struct seq_file *seq, void *offset)
-{
-	uint8_t current_format = vis_format;
-
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == DOT_DRAW) ? 'x' : ' ',
-		   VIS_FORMAT_DD_NAME);
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == JSON) ? 'x' : ' ',
-		   VIS_FORMAT_JSON_NAME);
-	return 0;
-}
-
-static int proc_vis_format_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_vis_format_read, NULL);
-}
-
-static ssize_t proc_vis_format_write(struct file *file,
-				     const char __user *buffer,
-				     size_t count, loff_t *ppos)
-{
-	char *vis_format_string;
-	int not_copied = 0;
-
-	vis_format_string = kmalloc(count, GFP_KERNEL);
-
-	if (!vis_format_string)
-		return -ENOMEM;
-
-	not_copied = copy_from_user(vis_format_string, buffer, count);
-	vis_format_string[count - not_copied - 1] = 0;
-
-	if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
-		       VIS_FORMAT_DD_NAME);
-		vis_format = DOT_DRAW;
-	} else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
-		       VIS_FORMAT_JSON_NAME);
-		vis_format = JSON;
-	} else
-		printk(KERN_ERR "batman-adv:Unknown VIS output format: %s\n",
-		       vis_format_string);
-
-	kfree(vis_format_string);
-	return count;
-}
-
 static int proc_aggr_read(struct seq_file *seq, void *offset)
 {
 	seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
@@ -585,15 +531,6 @@
 	.release	= single_release,
 };
 
-static const struct file_operations proc_vis_format_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_vis_format_open,
-	.read		= seq_read,
-	.write		= proc_vis_format_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 static const struct file_operations proc_vis_fops = {
 	.owner		= THIS_MODULE,
 	.open		= proc_vis_open,
@@ -757,17 +694,6 @@
 		return -EFAULT;
 	}
 
-	proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
-						 S_IWUSR | S_IRUGO,
-						 proc_batman_dir);
-	if (proc_vis_format_file) {
-		proc_vis_format_file->proc_fops = &proc_vis_format_fops;
-	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
-		cleanup_procfs();
-		return -EFAULT;
-	}
-
 	proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
 					   proc_batman_dir);
 	if (proc_aggr_file) {
diff -ru batman-adv-kernelland/vis.h batman-adv-kernelland2/vis.h
--- batman-adv-kernelland/vis.h	2009-12-13 20:53:26.000000000 +0100
+++ batman-adv-kernelland2/vis.h	2009-12-13 20:53:07.000000000 +0100
@@ -45,11 +45,6 @@
 	uint8_t mac[ETH_ALEN];
 };
 
-enum vis_formats {
-	DOT_DRAW,
-	JSON,
-};
-
 extern struct hashtable_t *vis_hash;
 extern spinlock_t vis_hash_lock;
 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [B.A.T.M.A.N.] /proc vis rework
  2009-11-30 21:14 [B.A.T.M.A.N.] /proc vis rework Andrew Lunn
  2009-12-11 22:58 ` Linus Lüssing
  2009-12-13 16:11 ` Andrew Lunn
@ 2009-12-19 17:01 ` Marek Lindner
  2009-12-19 17:11   ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: moving vis output formats out of the kernel land Marek Lindner
  2 siblings, 1 reply; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:01 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking


Hey,

> A while back i suggested we re-work the /proc/net/batman/vis format.
> Attached are two patches to achieve this. One patch is for the kernel
> model sources and the second extends batctl so that it can read from
> the /proc file and output dot or json format as before. The patch
> includes documentation for the new new batctl command in the man page.

I reviewed the patches & fixed some issues:
* vis raw data (kernel): I upgraded the patch to make it apply on the latest 
trunk and added a descriptive commit message
* vis raw data (batctl): I did not change anything but I'd like to suggest we 
adapt the coding style to match the rest of batctl (maybe using Lindent?). 
Also, all other batctl modules follow the same behaviour regarding the "-h" 
option. To be consistent we may want to adapt that as well.
* vis_format remove: This patch removed the vis_format initializations but not 
the corresponding free calls. I fixed that.
* I added an additional patch (splitting /proc vis file into vis_server and 
vis_data) to follow the roadmap we layed out in Brussels.
* Last but not least: the mandatory batctl vis data path change

Please give it some more testing,
Marek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: moving vis output formats out of the kernel land
  2009-12-19 17:01 ` Marek Lindner
@ 2009-12-19 17:11   ` Marek Lindner
  2009-12-19 17:11     ` [B.A.T.M.A.N.] [PATCH 2/5] batctl: Parse the new /proc vis format Marek Lindner
  0 siblings, 1 reply; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:11 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

The batman-adv kernel module is able to output visualization data using the
dot draw or JSON format. This patch transforms the output into a generic
format (called vis raw). User space tool may convert the raw data to support
a variety of formats without the need of modifying the kernel module.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
 batman-adv-kernelland/proc.c |  171 +++++++++++++++---------------------------
 batman-adv-kernelland/proc.h |    9 --
 2 files changed, 61 insertions(+), 119 deletions(-)

diff --git a/batman-adv-kernelland/proc.c b/batman-adv-kernelland/proc.c
index 22471ee..60eec83 100644
--- a/batman-adv-kernelland/proc.c
+++ b/batman-adv-kernelland/proc.c
@@ -322,166 +322,117 @@ static int proc_transt_global_open(struct inode *inode, struct file *file)
 	return single_open(file, proc_transt_global_read, NULL);
 }
 
-/* insert interface to the list of interfaces of one originator */
+/* 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 if_list_entry {
+	uint8_t addr[ETH_ALEN];
+	bool primary;
+	struct hlist_node list;
+};
 
+/* insert interface to the list of interfaces of one originator, if it
+ * does not already exist in the list */
 static void proc_vis_insert_interface(const uint8_t *interface,
-				      struct vis_if_list **if_entry,
+				      struct hlist_head *if_list,
 				      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)
+	struct if_list_entry *entry;
+	struct hlist_node *pos;
+
+	hlist_for_each_entry(entry, pos, if_list, list) {
+		if (compare_orig(entry->addr, (void *)interface))
 			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;
+	/* its a new address, add it to the list */
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return;
+	memcpy(entry->addr, interface, ETH_ALEN);
+	entry->primary = primary;
+	hlist_add_head(&entry->list, if_list);
+}
+
+static void proc_vis_read_prim_sec(struct seq_file *seq,
+				   struct hlist_head *if_list)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
+	char tmp_addr_str[ETH_STR_LEN];
+
+	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
+		if (entry->primary) {
+			seq_printf(seq, "PRIMARY, ");
+		} else {
+			addr_to_string(tmp_addr_str, entry->addr);
+			seq_printf(seq, "SEC %s, ", tmp_addr_str);
 		}
-		/* Rewind the list to its head */
-		*if_entry = head_if_entry;
+
+		hlist_del(&entry->list);
+		kfree(entry);
 	}
 }
-/* read an entry  */
 
+/* read an entry  */
 static void proc_vis_read_entry(struct seq_file *seq,
 				struct vis_info_entry *entry,
-				struct vis_if_list **if_entry,
-				uint8_t *vis_orig,
-				uint8_t current_format,
-				uint8_t first_line)
+				struct hlist_head *if_list,
+				uint8_t *vis_orig)
 {
-	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);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", gateway   : \"%s\", label : \"HNA\" }",
-				   (first_line ? "" : ",\n"), from, to);
-		}
+		proc_vis_insert_interface(vis_orig, if_list, true);
+		seq_printf(seq, "HNA %s, ", 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",
-				   from, to, int_part, frac_part);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", neighbor : \"%s\", label : %d.%d }",
-				   (first_line ? "" : ",\n"), from, to, int_part, frac_part);
-		}
+		proc_vis_insert_interface(entry->src, if_list,
+					  compare_orig(entry->src, vis_orig));
+		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
 	}
 }
 
-
 static int proc_vis_read(struct seq_file *seq, void *offset)
 {
 	HASHIT(hashit);
 	struct vis_info *info;
 	struct vis_info_entry *entries;
-	struct vis_if_list *if_entries = NULL;
+	HLIST_HEAD(vis_if_list);
 	int i;
-	uint8_t current_format, first_line = 1;
-#ifndef VIS_SUBCLUSTERS_DISABLED
+	uint8_t current_format;
 	char tmp_addr_str[ETH_STR_LEN];
-	struct vis_if_list *tmp_if_next;
-#endif /* VIS_SUBCLUSTERS_DISABLED */
 
 	current_format = vis_format;
 
 	rcu_read_lock();
 	if (list_empty(&if_list) || (!is_vis_server())) {
 		rcu_read_unlock();
-		if (current_format == DOT_DRAW)
-			seq_printf(seq, "digraph {\n}\n");
 		goto end;
 	}
 
 	rcu_read_unlock();
 
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "digraph {\n");
-
 	spin_lock(&vis_hash_lock);
 	while (hash_iterate(vis_hash, &hashit)) {
 		info = hashit.bucket->data;
 		entries = (struct vis_info_entry *)
 			((char *)info + sizeof(struct vis_info));
+		addr_to_string(tmp_addr_str, info->packet.vis_orig);
+		seq_printf(seq, "%s,", tmp_addr_str);
 
 		for (i = 0; i < info->packet.entries; i++) {
-			proc_vis_read_entry(seq, &entries[i], &if_entries,
-					    info->packet.vis_orig,
-					    current_format, first_line);
-			if (first_line)
-				first_line = 0;
+			proc_vis_read_entry(seq, &entries[i], &vis_if_list,
+					    info->packet.vis_orig);
 		}
 
-#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 */
+		/* add primary/secondary records */
+		proc_vis_read_prim_sec(seq, &vis_if_list);
+		seq_printf(seq, "\n");
 	}
 	spin_unlock(&vis_hash_lock);
 
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "}\n");
-	else
-		seq_printf(seq, "\n");
 end:
 	return 0;
 }
diff --git a/batman-adv-kernelland/proc.h b/batman-adv-kernelland/proc.h
index 16d3efd..761c5f8 100644
--- a/batman-adv-kernelland/proc.h
+++ b/batman-adv-kernelland/proc.h
@@ -38,12 +38,3 @@
 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;
-};
-- 
1.6.5.7


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [B.A.T.M.A.N.] [PATCH 2/5] batctl: Parse the new /proc vis format.
  2009-12-19 17:11   ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: moving vis output formats out of the kernel land Marek Lindner
@ 2009-12-19 17:11     ` Marek Lindner
  2009-12-19 17:11       ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: remove obsoleted vis_format /proc file Marek Lindner
  0 siblings, 1 reply; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:11 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

Add code to batctl so that it can parse /proc/net/batman-adv/vis and
generate either graphvis dot or JSON output.

Tested and bugs found and fixed by Linus Luessing.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Linus Luessing <linus.luessing@web.de>
---
 batctl/Makefile     |    4 +-
 batctl/functions.c  |    2 +-
 batctl/functions.h  |    1 +
 batctl/main.c       |   10 +-
 batctl/man/batctl.8 |   17 +++-
 batctl/vis.c        |  326 +++++++++++++++++++++++++++++++++++++++++++++++++++
 batctl/vis.h        |   21 ++++
 7 files changed, 372 insertions(+), 9 deletions(-)
 create mode 100644 batctl/vis.c
 create mode 100644 batctl/vis.h

diff --git a/batctl/Makefile b/batctl/Makefile
index b5255d2..8ecdd76 100644
--- a/batctl/Makefile
+++ b/batctl/Makefile
@@ -39,8 +39,8 @@ SRC_FILES = "\(\.c\)\|\(\.h\)\|\(Makefile\)\|\(INSTALL\)\|\(LIESMICH\)\|\(README
 EXTRA_MODULES_C := bisect.c
 EXTRA_MODULES_H := bisect.h
 
-SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c $(EXTRA_MODULES_C)
-SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h $(EXTRA_MODULES_H)
+SRC_C = main.c bat-hosts.c functions.c proc.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C)
+SRC_H = main.h bat-hosts.h functions.h proc.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H)
 SRC_O = $(SRC_C:.c=.o)
 
 PACKAGE_NAME = batctl
diff --git a/batctl/functions.c b/batctl/functions.c
index 697be1f..8d38764 100644
--- a/batctl/functions.c
+++ b/batctl/functions.c
@@ -99,7 +99,7 @@ char *get_name_by_macstr(char *mac_str, int read_opt)
 	return get_name_by_macaddr(mac_addr, read_opt);
 }
 
-static int check_proc_dir(char *dir)
+int check_proc_dir(char *dir)
 {
 	struct stat st;
 
diff --git a/batctl/functions.h b/batctl/functions.h
index f819754..445a619 100644
--- a/batctl/functions.h
+++ b/batctl/functions.h
@@ -34,6 +34,7 @@ char *get_name_by_macaddr(struct ether_addr *mac_addr, int read_opt);
 char *get_name_by_macstr(char *mac_str, int read_opt);
 int read_file(char *dir, char *path, int read_opt);
 int write_file(char *dir, char *path, char *value);
+int check_proc_dir(char *dir);
 
 extern char read_buff[10];
 
diff --git a/batctl/main.c b/batctl/main.c
index c0f1f88..ee5ed17 100644
--- a/batctl/main.c
+++ b/batctl/main.c
@@ -35,6 +35,7 @@
 #include "traceroute.h"
 #include "tcpdump.h"
 #include "bisect.h"
+#include "vis.h"
 
 
 void print_usage(void) {
@@ -47,7 +48,7 @@ void print_usage(void) {
 	printf(" \tlog|l                           \tread the log produced by the kernel module\n");
 	printf(" \ttranslocal|tl                   \tdisplay the local translation table\n");
 	printf(" \ttransglobal|tg                  \tdisplay the global translation table\n");
-	printf(" \tvisformat|vf  [format]          \tdisplay or modify the vis output format\n");
+	printf(" \tvis [dot|JSON]                  \tdisplay the VIS data in dot or JSON format\n");
 	printf(" \taggregation|ag   [0|1]          \tdisplay or modify the packet aggregation setting\n");
 	printf("\n");
 	printf(" \tping|p        <destination>     \tping another batman adv host via layer 2\n");
@@ -74,7 +75,8 @@ int main(int argc, char **argv)
 	}
 
 	/* check if user is root */
-	if ((strcmp(argv[1], "bisect") != 0) && ((getuid()) || (getgid()))) {
+	if (((strcmp(argv[1], "bisect") != 0) && (strcmp(argv[1], "vis") != 0))
+	    && ((getuid()) || (getgid()))) {
 		fprintf(stderr, "Error - you must be root to run '%s' !\n", argv[0]);
 		exit(EXIT_FAILURE);
 	}
@@ -119,9 +121,9 @@ int main(int argc, char **argv)
 
 		ret = handle_proc_setting(argc - 1, argv + 1, PROC_ORIG_INTERVAL, orig_interval_usage);
 
-	} else if ((strcmp(argv[1], "visformat") == 0) || (strcmp(argv[1], "vf") == 0)) {
+	} else if (strcmp(argv[1], "vis") == 0) {
 
-		ret = handle_proc_setting(argc - 1, argv + 1, PROC_VIS_FORMAT, vis_format_usage);
+		ret = vis(argc - 1, argv + 1);
 
 	} else if ((strcmp(argv[1], "aggregation") == 0) || (strcmp(argv[1], "ag") == 0)) {
 
diff --git a/batctl/man/batctl.8 b/batctl/man/batctl.8
index cdedacb..1aa68df 100644
--- a/batctl/man/batctl.8
+++ b/batctl/man/batctl.8
@@ -63,8 +63,21 @@ Once started batctl will refresh the displayed local translation table every sec
 .IP "\fBtransglobal|tg\fP"
 Once started batctl will refresh the displayed global translation table every second. Use the "\-b" option to let batctl display the table only once (useful for scripts). If "\-n" was given batctl will not replace the mac addresses with bat\-host names in the output.
 .br
-.IP "\fBvisformat|vf	[format]\fP"
-If no parameter is given the current vis format settings are displayed otherwise the parameter is used to set the vis format.
+.IP "\fBvis dot\fP"
+Display the visualisation data in graphviz dot(1) format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
+.br
+.IP "\fBvis json\fP"
+Display the visualisation data in JSON format. If
+"\--numbers" or "\-n" batctl will not replace the mac addresses with
+bat-host names in the output. With "\--no-HNA" or "\-h" the HNA
+entries are not displayed, so the pure mesh topology can be seen. With
+"\--no-2nd" or "\-2" a dot cluster is not formed around primary and
+secondary addresses from the same device.
 .br
 .IP "\fBaggregation|ag	[0|1]\fP"
 If no parameter is given the current aggregation settings are displayed otherwise the parameter is used to enable or disable the packet aggregation.
diff --git a/batctl/vis.c b/batctl/vis.c
new file mode 100644
index 0000000..450310c
--- /dev/null
+++ b/batctl/vis.c
@@ -0,0 +1,326 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "main.h"
+#include "vis.h"
+#include "functions.h"
+#include "bat-hosts.h"
+#include "proc.h"
+
+#define TQ_MAX_VALUE 255
+
+typedef void (*print_tq_t)(char * orig, char * from, const long tq);
+typedef void (*print_HNA_t)(char * orig, char * from);
+typedef void (*print_1st_t)(char * orig);
+typedef void (*print_2nd_t)(char * orig, char * from);
+typedef void (*print_header_t)(void);
+typedef void (*print_footer_t)(void);
+
+struct funcs 
+{
+  print_tq_t print_tq;
+  print_HNA_t print_HNA;
+  print_1st_t print_1st;
+  print_2nd_t print_2nd;
+  print_header_t print_header;
+  print_footer_t print_footer;
+};
+
+static bool with_HNA = true;
+static bool with_2nd = true;
+static bool with_names = true;
+
+static void 
+usage(void)
+{
+  printf("batctl vis dot {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+  printf("or\n");
+  printf("batctl vis json {--no-HNA|-h} {--no-2nd|-2} {--numbers|-n}\n");
+}
+
+static void 
+dot_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t\"%s\" -> ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\"%s\" [label=\"%d.%d\"]\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+dot_print_HNA(char * orig, char * from)
+{
+        printf("\t\"%s\" -> ",
+               get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+        printf("\"%s\" [label=\"HNA\"]\n", 
+               get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+dot_print_1st(char * orig)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_2nd(char * orig, char * from)
+{
+  printf("\tsubgraph \"cluster_%s\" {\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\" [peripheries=2]\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t\t\"%s\"\n",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("\t}\n");
+}
+
+static void
+dot_print_header(void) 
+{
+  printf("digraph {\n");
+}
+
+static void
+dot_print_footer(void) 
+{
+  printf("}\n");
+}
+
+const struct funcs dot_funcs = 
+  { dot_print_tq,
+    dot_print_HNA,
+    dot_print_1st,
+    dot_print_2nd,
+    dot_print_header,
+    dot_print_footer
+};
+
+static void 
+json_print_tq(char * orig, char * from, const long tq)
+{
+  int int_part = TQ_MAX_VALUE / tq;
+  int frac_part = (1000 * TQ_MAX_VALUE / tq) - (int_part * 1000);
+        
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("neighbor : \"%s\", label : \"%d.%d\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)),
+         int_part, frac_part);
+}
+
+static void 
+json_print_HNA(char * orig, char * from)
+{
+  printf("\t{ router : \"%s\", ",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+  printf("gateway : \"%s\", label : \"HNA\" }\n", 
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_1st(char * orig)
+{
+  printf("\t{ primary : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+static void
+json_print_2nd(char * orig, char * from)
+{
+  printf("\t{ secondary : \"%s\", ",
+         get_name_by_macstr(from, (with_names ? USE_BAT_HOSTS : 0)));
+
+  printf("of : \"%s\" }\n",
+         get_name_by_macstr(orig, (with_names ? USE_BAT_HOSTS : 0)));
+}
+
+const struct funcs json_funcs = 
+  { json_print_tq,
+    json_print_HNA,
+    json_print_1st,
+    json_print_2nd,
+    NULL,
+    NULL
+};
+
+static FILE *
+open_vis(void) 
+{
+  char full_path[500];
+  
+  if (check_proc_dir("/proc") != EXIT_SUCCESS)
+    return NULL;
+
+  strncpy(full_path, PROC_ROOT_PATH, strlen(PROC_ROOT_PATH));
+  full_path[strlen(PROC_ROOT_PATH)] = '\0';
+  strncat(full_path, "vis", sizeof(full_path) - strlen(full_path));
+
+  return fopen(full_path, "r");
+}
+
+static int 
+format(const struct funcs *funcs)
+{
+  size_t len = 0;
+  ssize_t read;
+  char * line = NULL;
+  char * orig, * from;
+  char * duplet;
+  char * line_save_ptr;
+  char * duplet_save_ptr;
+  char * endptr;
+  char * value;
+  long tq;
+  char * flag;
+  
+  FILE * fp = open_vis(); 
+
+  if (!fp)
+    return EXIT_FAILURE;
+  
+  if (funcs->print_header)
+    funcs->print_header();
+  
+  while ((read = getline(&line, &len, fp)) != -1) {
+    /* First MAC address is the originator */
+    orig = strtok_r(line, ",", &line_save_ptr);
+
+    duplet_save_ptr = line_save_ptr;
+    while ((duplet = strtok_r(NULL, ",", &duplet_save_ptr)) != NULL) {
+      flag = strtok(duplet, " ");
+      if (!flag) 
+        continue;
+      if (!strcmp(flag, "TQ")) {
+        from = strtok(NULL, " ");
+        value = strtok(NULL, " ");
+        tq = strtoul(value, &endptr, 0);
+        funcs->print_tq(orig, from, tq);
+        continue;
+      }
+      if (!strcmp(flag, "HNA")) {
+        /* We have an HNA record */
+        if (!with_HNA) 
+          continue;
+        from = strtok(NULL, " ");
+        funcs->print_HNA(orig, from);
+        continue;
+      }
+      if (!strcmp(flag, "SEC") && with_2nd) {
+        /* We found a secondary interface MAC address.*/
+        from = strtok(NULL, " ");
+        funcs->print_2nd(orig, from);
+      }
+      if (!strcmp(flag, "PRIMARY") && with_2nd) {
+        /* We found a primary interface MAC address.*/
+        funcs->print_1st(orig);
+      }
+    }
+  }
+  
+  if (funcs->print_footer)
+    funcs->print_footer();
+  
+  if (line)
+    free(line);
+  return EXIT_SUCCESS;
+}
+
+int 
+vis(int argc, char *argv[])
+{
+  bool dot = false;
+  bool json = false;
+  int c;
+
+  if (argc <=1) {
+    usage();
+    return EXIT_FAILURE;
+  }
+  
+  /* Do we know the requested format? */
+  if (strcmp(argv[1], "dot") == 0)
+    dot=true;
+  if (strcmp(argv[1], "json") == 0)
+    json=true;
+  
+  if (!dot && !json) {
+    usage();
+    return EXIT_FAILURE;
+  }
+  
+  /* Move over the output format */
+  argc--;
+  argv++;
+  
+  while (1) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      {"no-HNA", 0, 0, 'h'},
+      {"no-2nd", 0, 0, '2'},
+      {"numbers", 0, 0, 'n'},
+      {0, 0, 0, 0}
+    };
+    
+    c = getopt_long(argc, argv, "h2n", long_options, &option_index);
+    if (c == -1)
+      break;
+    
+    switch(c) {
+      case 'h':
+        with_HNA = false;
+        break;
+      case '2':
+        with_2nd = false;
+        break;
+      case 'n':
+        with_names = false;
+        break;
+      default:
+        usage();
+        return -1;
+    }
+  }
+  
+  if (with_names)
+	  bat_hosts_init();
+  
+  if (dot) 
+    return format(&dot_funcs);
+  
+  if (json)
+    return format(&json_funcs);
+
+  return EXIT_FAILURE;
+}
diff --git a/batctl/vis.h b/batctl/vis.h
new file mode 100644
index 0000000..734528e
--- /dev/null
+++ b/batctl/vis.h
@@ -0,0 +1,21 @@
+/* Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int vis(int argc, char * argv[]);
+
-- 
1.6.5.7


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: remove obsoleted vis_format /proc file
  2009-12-19 17:11     ` [B.A.T.M.A.N.] [PATCH 2/5] batctl: Parse the new /proc vis format Marek Lindner
@ 2009-12-19 17:11       ` Marek Lindner
  2009-12-19 17:11         ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: splitting /proc vis file into vis_server and vis_data Marek Lindner
  0 siblings, 1 reply; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:11 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

batman-adv used to export the vis data using different formats that were
switchable via /proc/net/batman-adv/vis_format. The various formats moved
to user space and rendered this configuration switch useless.

Signed-off-by: Linus Luessing <linus.luessing@web.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
 batman-adv-kernelland/proc.c |   79 +-----------------------------------------
 batman-adv-kernelland/vis.h  |    5 ---
 2 files changed, 1 insertions(+), 83 deletions(-)

diff --git a/batman-adv-kernelland/proc.c b/batman-adv-kernelland/proc.c
index 60eec83..d98f86a 100644
--- a/batman-adv-kernelland/proc.c
+++ b/batman-adv-kernelland/proc.c
@@ -29,13 +29,11 @@
 #include "vis.h"
 #include "compat.h"
 
-static uint8_t vis_format = DOT_DRAW;
-
 static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
 static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
 static struct proc_dir_entry *proc_transt_local_file;
 static struct proc_dir_entry *proc_transt_global_file;
-static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file;
+static struct proc_dir_entry *proc_vis_file;
 static struct proc_dir_entry *proc_aggr_file;
 
 static int proc_interfaces_read(struct seq_file *seq, void *offset)
@@ -401,11 +399,8 @@ static int proc_vis_read(struct seq_file *seq, void *offset)
 	struct vis_info_entry *entries;
 	HLIST_HEAD(vis_if_list);
 	int i;
-	uint8_t current_format;
 	char tmp_addr_str[ETH_STR_LEN];
 
-	current_format = vis_format;
-
 	rcu_read_lock();
 	if (list_empty(&if_list) || (!is_vis_server())) {
 		rcu_read_unlock();
@@ -471,55 +466,6 @@ static int proc_vis_open(struct inode *inode, struct file *file)
 	return single_open(file, proc_vis_read, NULL);
 }
 
-static int proc_vis_format_read(struct seq_file *seq, void *offset)
-{
-	uint8_t current_format = vis_format;
-
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == DOT_DRAW) ? 'x' : ' ',
-		   VIS_FORMAT_DD_NAME);
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == JSON) ? 'x' : ' ',
-		   VIS_FORMAT_JSON_NAME);
-	return 0;
-}
-
-static int proc_vis_format_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_vis_format_read, NULL);
-}
-
-static ssize_t proc_vis_format_write(struct file *file,
-				     const char __user *buffer,
-				     size_t count, loff_t *ppos)
-{
-	char *vis_format_string;
-	int not_copied = 0;
-
-	vis_format_string = kmalloc(count, GFP_KERNEL);
-
-	if (!vis_format_string)
-		return -ENOMEM;
-
-	not_copied = copy_from_user(vis_format_string, buffer, count);
-	vis_format_string[count - not_copied - 1] = 0;
-
-	if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
-		       VIS_FORMAT_DD_NAME);
-		vis_format = DOT_DRAW;
-	} else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
-		       VIS_FORMAT_JSON_NAME);
-		vis_format = JSON;
-	} else
-		printk(KERN_ERR "batman-adv:Unknown VIS output format: %s\n",
-		       vis_format_string);
-
-	kfree(vis_format_string);
-	return count;
-}
-
 static int proc_aggr_read(struct seq_file *seq, void *offset)
 {
 	seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
@@ -583,15 +529,6 @@ static const struct file_operations proc_aggr_fops = {
 	.release	= single_release,
 };
 
-static const struct file_operations proc_vis_format_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_vis_format_open,
-	.read		= seq_read,
-	.write		= proc_vis_format_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 static const struct file_operations proc_vis_fops = {
 	.owner		= THIS_MODULE,
 	.open		= proc_vis_open,
@@ -666,9 +603,6 @@ void cleanup_procfs(void)
 	if (proc_vis_file)
 		remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
 
-	if (proc_vis_format_file)
-		remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir);
-
 	if (proc_aggr_file)
 		remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
 
@@ -755,17 +689,6 @@ int setup_procfs(void)
 		return -EFAULT;
 	}
 
-	proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
-						 S_IWUSR | S_IRUGO,
-						 proc_batman_dir);
-	if (proc_vis_format_file) {
-		proc_vis_format_file->proc_fops = &proc_vis_format_fops;
-	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
-		cleanup_procfs();
-		return -EFAULT;
-	}
-
 	proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
 					   proc_batman_dir);
 	if (proc_aggr_file) {
diff --git a/batman-adv-kernelland/vis.h b/batman-adv-kernelland/vis.h
index 276faba..ff88a43 100644
--- a/batman-adv-kernelland/vis.h
+++ b/batman-adv-kernelland/vis.h
@@ -45,11 +45,6 @@ struct recvlist_node {
 	uint8_t mac[ETH_ALEN];
 };
 
-enum vis_formats {
-	DOT_DRAW,
-	JSON,
-};
-
 extern struct hashtable_t *vis_hash;
 extern spinlock_t vis_hash_lock;
 
-- 
1.6.5.7


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: splitting /proc vis file into vis_server and vis_data
  2009-12-19 17:11       ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: remove obsoleted vis_format /proc file Marek Lindner
@ 2009-12-19 17:11         ` Marek Lindner
  2009-12-19 17:11           ` [B.A.T.M.A.N.] [PATCH 5/5] batctl: adjust vis data file path Marek Lindner
  0 siblings, 1 reply; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:11 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

The /proc vis file was used to enable/disable the vis server and to output
the vis data at the same time. This behaviour was confusing and lacked a
proper method to display the current vis server status.
This patch seperates the 2 functionalities:
* use vis_server to enable/disable the vis server and to retrieve its status
* use vis_data to retrieve the vis raw data (if the server is enabled)

Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
 batman-adv-kernelland/proc.c  |  172 +++++++++++++++++------------------------
 batman-adv-kernelland/proc.h  |    4 +-
 batman-adv-kernelland/types.h |   10 +++
 batman-adv-kernelland/vis.c   |   62 +++++++++++++++
 batman-adv-kernelland/vis.h   |    6 ++
 5 files changed, 151 insertions(+), 103 deletions(-)

diff --git a/batman-adv-kernelland/proc.c b/batman-adv-kernelland/proc.c
index d98f86a..9cfab8f 100644
--- a/batman-adv-kernelland/proc.c
+++ b/batman-adv-kernelland/proc.c
@@ -33,7 +33,7 @@ static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
 static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
 static struct proc_dir_entry *proc_transt_local_file;
 static struct proc_dir_entry *proc_transt_global_file;
-static struct proc_dir_entry *proc_vis_file;
+static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file;
 static struct proc_dir_entry *proc_aggr_file;
 
 static int proc_interfaces_read(struct seq_file *seq, void *offset)
@@ -320,79 +320,55 @@ static int proc_transt_global_open(struct inode *inode, struct file *file)
 	return single_open(file, proc_transt_global_read, NULL);
 }
 
-/* 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 if_list_entry {
-	uint8_t addr[ETH_ALEN];
-	bool primary;
-	struct hlist_node list;
-};
-
-/* insert interface to the list of interfaces of one originator, if it
- * does not already exist in the list */
-static void proc_vis_insert_interface(const uint8_t *interface,
-				      struct hlist_head *if_list,
-				      bool primary)
+/* setting the mode of the vis server by the user */
+static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
+			      size_t count, loff_t *ppos)
 {
-	struct if_list_entry *entry;
-	struct hlist_node *pos;
+	char *vis_mode_string;
+	int not_copied = 0;
 
-	hlist_for_each_entry(entry, pos, if_list, list) {
-		if (compare_orig(entry->addr, (void *)interface))
-			return;
-	}
+	vis_mode_string = kmalloc(count, GFP_KERNEL);
 
-	/* its a new address, add it to the list */
-	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-	if (!entry)
-		return;
-	memcpy(entry->addr, interface, ETH_ALEN);
-	entry->primary = primary;
-	hlist_add_head(&entry->list, if_list);
+	if (!vis_mode_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(vis_mode_string, buffer, count);
+	vis_mode_string[count - not_copied - 1] = 0;
+
+	if ((strcmp(vis_mode_string, "client") == 0) ||
+			(strcmp(vis_mode_string, "disabled") == 0)) {
+		printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
+		vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
+	} else if ((strcmp(vis_mode_string, "server") == 0) ||
+			(strcmp(vis_mode_string, "enabled") == 0)) {
+		printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
+		vis_set_mode(VIS_TYPE_SERVER_SYNC);
+	} else
+		printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
+		       vis_mode_string);
+
+	kfree(vis_mode_string);
+	return count;
 }
 
-static void proc_vis_read_prim_sec(struct seq_file *seq,
-				   struct hlist_head *if_list)
+static int proc_vis_srv_read(struct seq_file *seq, void *offset)
 {
-	struct if_list_entry *entry;
-	struct hlist_node *pos, *n;
-	char tmp_addr_str[ETH_STR_LEN];
+	int vis_server = is_vis_server();
 
-	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
-		if (entry->primary) {
-			seq_printf(seq, "PRIMARY, ");
-		} else {
-			addr_to_string(tmp_addr_str, entry->addr);
-			seq_printf(seq, "SEC %s, ", tmp_addr_str);
-		}
+	seq_printf(seq, "[%c] client mode (server disabled) \n",
+			(!vis_server) ? 'x' : ' ');
+	seq_printf(seq, "[%c] server mode (server enabled) \n",
+			(vis_server) ? 'x' : ' ');
 
-		hlist_del(&entry->list);
-		kfree(entry);
-	}
+	return 0;
 }
 
-/* read an entry  */
-static void proc_vis_read_entry(struct seq_file *seq,
-				struct vis_info_entry *entry,
-				struct hlist_head *if_list,
-				uint8_t *vis_orig)
+static int proc_vis_srv_open(struct inode *inode, struct file *file)
 {
-	char to[40];
-
-	addr_to_string(to, entry->dest);
-	if (entry->quality == 0) {
-		proc_vis_insert_interface(vis_orig, if_list, true);
-		seq_printf(seq, "HNA %s, ", to);
-	} else {
-		proc_vis_insert_interface(entry->src, if_list,
-					  compare_orig(entry->src, vis_orig));
-		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
-	}
+	return single_open(file, proc_vis_srv_read, NULL);
 }
 
-static int proc_vis_read(struct seq_file *seq, void *offset)
+static int proc_vis_data_read(struct seq_file *seq, void *offset)
 {
 	HASHIT(hashit);
 	struct vis_info *info;
@@ -432,38 +408,9 @@ end:
 	return 0;
 }
 
-/* setting the mode of the vis server by the user */
-static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
-			      size_t count, loff_t *ppos)
+static int proc_vis_data_open(struct inode *inode, struct file *file)
 {
-	char *vis_mode_string;
-	int not_copied = 0;
-
-	vis_mode_string = kmalloc(count, GFP_KERNEL);
-
-	if (!vis_mode_string)
-		return -ENOMEM;
-
-	not_copied = copy_from_user(vis_mode_string, buffer, count);
-	vis_mode_string[count - not_copied - 1] = 0;
-
-	if (strcmp(vis_mode_string, "client") == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS mode to client\n");
-		vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
-	} else if (strcmp(vis_mode_string, "server") == 0) {
-		printk(KERN_INFO "batman-adv:Setting VIS mode to server\n");
-		vis_set_mode(VIS_TYPE_SERVER_SYNC);
-	} else
-		printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
-		       vis_mode_string);
-
-	kfree(vis_mode_string);
-	return count;
-}
-
-static int proc_vis_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_vis_read, NULL);
+	return single_open(file, proc_vis_data_read, NULL);
 }
 
 static int proc_aggr_read(struct seq_file *seq, void *offset)
@@ -529,11 +476,20 @@ static const struct file_operations proc_aggr_fops = {
 	.release	= single_release,
 };
 
-static const struct file_operations proc_vis_fops = {
+static const struct file_operations proc_vis_srv_fops = {
 	.owner		= THIS_MODULE,
-	.open		= proc_vis_open,
+	.open		= proc_vis_srv_open,
 	.read		= seq_read,
-	.write		= proc_vis_write,
+	.write		= proc_vis_srv_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_vis_data_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_vis_data_open,
+	.read		= seq_read,
+	.write		= proc_dummy_write,
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
@@ -600,8 +556,11 @@ void cleanup_procfs(void)
 	if (proc_interface_file)
 		remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
 
-	if (proc_vis_file)
-		remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
+	if (proc_vis_data_file)
+		remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir);
+
+	if (proc_vis_srv_file)
+		remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
 
 	if (proc_aggr_file)
 		remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
@@ -679,12 +638,23 @@ int setup_procfs(void)
 		return -EFAULT;
 	}
 
-	proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO,
+	proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV,
+						S_IWUSR | S_IRUGO,
+						proc_batman_dir);
+	if (proc_vis_srv_file) {
+		proc_vis_srv_file->proc_fops = &proc_vis_srv_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO,
 					  proc_batman_dir);
-	if (proc_vis_file) {
-		proc_vis_file->proc_fops = &proc_vis_fops;
+	if (proc_vis_data_file) {
+		proc_vis_data_file->proc_fops = &proc_vis_data_fops;
 	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS);
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA);
 		cleanup_procfs();
 		return -EFAULT;
 	}
diff --git a/batman-adv-kernelland/proc.h b/batman-adv-kernelland/proc.h
index 761c5f8..cd690e0 100644
--- a/batman-adv-kernelland/proc.h
+++ b/batman-adv-kernelland/proc.h
@@ -31,8 +31,8 @@
 #define PROC_FILE_LOG_LEVEL "log_level"
 #define PROC_FILE_TRANST_LOCAL "transtable_local"
 #define PROC_FILE_TRANST_GLOBAL "transtable_global"
-#define PROC_FILE_VIS "vis"
-#define PROC_FILE_VIS_FORMAT "vis_format"
+#define PROC_FILE_VIS_SRV "vis_server"
+#define PROC_FILE_VIS_DATA "vis_data"
 #define PROC_FILE_AGGR "aggregate_ogm"
 
 void cleanup_procfs(void);
diff --git a/batman-adv-kernelland/types.h b/batman-adv-kernelland/types.h
index 9739358..d708e6f 100644
--- a/batman-adv-kernelland/types.h
+++ b/batman-adv-kernelland/types.h
@@ -121,4 +121,14 @@ struct forw_packet {               /* structure for forw_list maintaining packet
 	struct batman_if *if_incoming;
 };
 
+/* 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 if_list_entry {
+	uint8_t addr[ETH_ALEN];
+	bool primary;
+	struct hlist_node list;
+};
+
 #endif
diff --git a/batman-adv-kernelland/vis.c b/batman-adv-kernelland/vis.c
index ac7c7c5..daa4a49 100644
--- a/batman-adv-kernelland/vis.c
+++ b/batman-adv-kernelland/vis.c
@@ -114,6 +114,68 @@ static int vis_info_choose(void *data, int size)
 	return hash % size;
 }
 
+/* insert interface to the list of interfaces of one originator, if it
+ * does not already exist in the list */
+static void proc_vis_insert_interface(const uint8_t *interface,
+				      struct hlist_head *if_list,
+				      bool primary)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos;
+
+	hlist_for_each_entry(entry, pos, if_list, list) {
+		if (compare_orig(entry->addr, (void *)interface))
+			return;
+	}
+
+	/* its a new address, add it to the list */
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return;
+	memcpy(entry->addr, interface, ETH_ALEN);
+	entry->primary = primary;
+	hlist_add_head(&entry->list, if_list);
+}
+
+void proc_vis_read_prim_sec(struct seq_file *seq,
+			    struct hlist_head *if_list)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
+	char tmp_addr_str[ETH_STR_LEN];
+
+	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
+		if (entry->primary) {
+			seq_printf(seq, "PRIMARY, ");
+		} else {
+			addr_to_string(tmp_addr_str, entry->addr);
+			seq_printf(seq, "SEC %s, ", tmp_addr_str);
+		}
+
+		hlist_del(&entry->list);
+		kfree(entry);
+	}
+}
+
+/* read an entry  */
+void proc_vis_read_entry(struct seq_file *seq,
+				struct vis_info_entry *entry,
+				struct hlist_head *if_list,
+				uint8_t *vis_orig)
+{
+	char to[40];
+
+	addr_to_string(to, entry->dest);
+	if (entry->quality == 0) {
+		proc_vis_insert_interface(vis_orig, if_list, true);
+		seq_printf(seq, "HNA %s, ", to);
+	} else {
+		proc_vis_insert_interface(entry->src, if_list,
+					  compare_orig(entry->src, vis_orig));
+		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
+	}
+}
+
 /* tries to add one entry to the receive list. */
 static void recv_list_add(struct list_head *recv_list, char *mac)
 {
diff --git a/batman-adv-kernelland/vis.h b/batman-adv-kernelland/vis.h
index ff88a43..2e24258 100644
--- a/batman-adv-kernelland/vis.h
+++ b/batman-adv-kernelland/vis.h
@@ -50,6 +50,12 @@ extern spinlock_t vis_hash_lock;
 
 void vis_set_mode(int mode);
 int is_vis_server(void);
+void proc_vis_read_entry(struct seq_file *seq,
+				struct vis_info_entry *entry,
+				struct hlist_head *if_list,
+				uint8_t *vis_orig);
+void proc_vis_read_prim_sec(struct seq_file *seq,
+			    struct hlist_head *if_list);
 void receive_server_sync_packet(struct vis_packet *vis_packet,
 				int vis_info_len);
 void receive_client_update_packet(struct vis_packet *vis_packet,
-- 
1.6.5.7


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [B.A.T.M.A.N.] [PATCH 5/5] batctl: adjust vis data file path
  2009-12-19 17:11         ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: splitting /proc vis file into vis_server and vis_data Marek Lindner
@ 2009-12-19 17:11           ` Marek Lindner
  0 siblings, 0 replies; 13+ messages in thread
From: Marek Lindner @ 2009-12-19 17:11 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

The kernel module changed the vis data file path which need to be changed
in batctl as well. This patch depends on the "splitting /proc vis file into
vis_server and vis_data" patch.

Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
 batctl/vis.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/batctl/vis.c b/batctl/vis.c
index 450310c..f1e95ee 100644
--- a/batctl/vis.c
+++ b/batctl/vis.c
@@ -185,7 +185,7 @@ open_vis(void)
 
   strncpy(full_path, PROC_ROOT_PATH, strlen(PROC_ROOT_PATH));
   full_path[strlen(PROC_ROOT_PATH)] = '\0';
-  strncat(full_path, "vis", sizeof(full_path) - strlen(full_path));
+  strncat(full_path, "vis_data", sizeof(full_path) - strlen(full_path));
 
   return fopen(full_path, "r");
 }
-- 
1.6.5.7


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-12-19 17:11 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-30 21:14 [B.A.T.M.A.N.] /proc vis rework Andrew Lunn
2009-12-11 22:58 ` Linus Lüssing
2009-12-11 23:20   ` Linus Lüssing
2009-12-12 10:43   ` Andrew Lunn
2009-12-13 16:14   ` Andrew Lunn
2009-12-13 16:11 ` Andrew Lunn
2009-12-13 20:02   ` Linus Lüssing
2009-12-19 17:01 ` Marek Lindner
2009-12-19 17:11   ` [B.A.T.M.A.N.] [PATCH 1/5] batman-adv: moving vis output formats out of the kernel land Marek Lindner
2009-12-19 17:11     ` [B.A.T.M.A.N.] [PATCH 2/5] batctl: Parse the new /proc vis format Marek Lindner
2009-12-19 17:11       ` [B.A.T.M.A.N.] [PATCH 3/5] batman-adv: remove obsoleted vis_format /proc file Marek Lindner
2009-12-19 17:11         ` [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: splitting /proc vis file into vis_server and vis_data Marek Lindner
2009-12-19 17:11           ` [B.A.T.M.A.N.] [PATCH 5/5] batctl: adjust vis data file path Marek Lindner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).