Re: [PATCH] iproute2: show network device dependency tree

2017-03-02 Thread Zaboj Campula
On Wed, 2017-03-01 at 11:22 +0100, Jiri Benc wrote:
> On Tue, 28 Feb 2017 20:07:37 +0000, Zaboj Campula wrote:
> > Well it is impossible to draw a simple tree showing the configuration
> > exactly with all details. May be it is too ambitious to draw a tree
> > at all.
> 
> I tried that and failed. I didn't want to have something that would
> work only "somehow" as that would create confusion instead of helping.

OK, I give up. My patch was naive and I deleted it.
Nevertheless I still think it would be useful to show network
interfaces dependencies in a pure text format.


> Consider the very simple case of an interface with two vlan interfaces
> and both of them in a bridge.
> 
>  vlan0
>   /\
> eth0 br0
>   \/
>  vlan1
> 
> You can't represent this in a tree view. And this is just a very simple
> example, in reality it tends to be much more complex.

Perhaps something like that:
eth0
vlan0
br0
vlan1
br0


Re: [PATCH] iproute2: show network device dependency tree

2017-02-28 Thread Zaboj Campula
On Mon, 2017-02-27 at 10:55 -0800, Stephen Hemminger wrote:
> 
> Another alternative format would be to make -tree a output modifier and ident 
> (like ps tree options).
> 
> $ ip -t link
> 1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode 
> DEFAULT group default qlen 1
> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> 8: bond0  mtu 1500 qdisc pfifo_fast state DOWN mode 
> DEFAULT group default qlen 1000
> link/ether 52:54:00:66:24:cd brd ff:ff:ff:ff:ff:ff 
> 2: eth1:  mtu 1500 qdisc pfifo_fast master bond0 
> state DOWN mode DEFAULT group default qlen 1000
> link/ether 52:54:00:66:24:cd brd ff:ff:ff:ff:ff:ff

OK, it looks better because the information is complete.

I looked at several tree printing utilities and I like
the lsblk format. But tabular format does not fit the ip-show
well. I will try to indent the current ip-show output may be
with fancy lines.



Re: [PATCH] iproute2: show network device dependency tree

2017-02-28 Thread Zaboj Campula
On Mon, 2017-02-27 at 17:38 +0100, Jiri Benc wrote:
> 
> It produces dot (graphviz) output or json and has no dependencies on
> anything GUI related. Just run it on the remote machine and display the
> output locally.
> 
> ssh root@remote plotnetcfg | dot -Tpdf | whatever_pdf_viewer
> 
> Note that some pdf viewers can't read stdin or require dash as the
> parameter to use stdin.
> 
> I don't think it's possible to enhance iproute2 to display the network
> interface dependencies in an useful way. It's just too complex. It's
> not even a (undirected) tree.

I know there is an option to execute something remotely but I think 
a pure text output may be useful to get a quick overview.

Well it is impossible to draw a simple tree showing the configuration
exactly with all details. May be it is too ambitious to draw a tree
at all. But neither directory structure is a tree (when consider links)
and there are a plenty of tools showing directory tree.


Re: [PATCH] iproute2: show network device dependency tree

2017-02-26 Thread Zaboj Campula
On Sun, 2017-02-26 at 08:56 +0100, Jiri Pirko wrote:
> Sat, Feb 25, 2017 at 09:22:22PM CET, zaboj.camp...@post.cz wrote:
> > On Sat, 2017-02-25 at 18:39 +0100, Jiri Pirko wrote:
> > > > Sat, Feb 25, 2017 at 05:59:00PM CET, zaboj.camp...@post.cz
> > > > wrote:
> > > > Add the argument '-tree' to ip-link to show network devices
> > > > dependency tree.
> > > > 
> > > > Example:
> > > > 
> > > > $ ip -tree link
> > > > eth0
> > > >    bond0
> > > > eth1
> > > >    bond0
> > > > eth2
> > > >    bond1
> > > > eth3
> > > >    bond1
> > > 
> > > 
> > > Hmm, what is this good for? I'm probably missing something...
> > 
> > I consider this kind of output useful when troubleshooting a complex
> > configuration with many interfaces. It may show relations among
> > interfaces.
> 
> Did you see https://github.com/jbenc/plotnetcfg ?
> 

Thanks for the link. I haven't seen plotnetcfg and I like it.
It is handy when the analyzed system has GUI.


> 
> > 
> > 
> > > 
> > > 
> > > 
> > > > 
> > > > > > > > Signed-off-by: Zaboj Campula <zaboj.camp...@post.cz>
> > > > 
> > > > ---
> > > > include/utils.h |  1 +
> > > > ip/ip.c |  5 ++-
> > > > ip/ipaddress.c  | 97 
> > > > -
> > > > 3 files changed, 87 insertions(+), 16 deletions(-)
> > > > 
> > > > diff --git a/include/utils.h b/include/utils.h
> > > > index 22369e0..f1acf4d 100644
> > > > --- a/include/utils.h
> > > > +++ b/include/utils.h
> > > > @@ -20,6 +20,7 @@ extern int show_raw;
> > > > extern int resolve_hosts;
> > > > extern int oneline;
> > > > extern int brief;
> > > > +extern int tree;;
> > > > extern int timestamp;
> > > > extern int timestamp_short;
> > > > extern const char * _SL_;
> > > > diff --git a/ip/ip.c b/ip/ip.c
> > > > index 07050b0..29747a5 100644
> > > > --- a/ip/ip.c
> > > > +++ b/ip/ip.c
> > > > @@ -33,6 +33,7 @@ int show_details;
> > > > int resolve_hosts;
> > > > int oneline;
> > > > int brief;
> > > > +int tree;
> > > > int timestamp;
> > > > const char *_SL_;
> > > > int force;
> > > > @@ -57,7 +58,7 @@ static void usage(void)
> > > > "-h[uman-readable] | -iec |\n"
> > > > "-f[amily] { inet | inet6 | ipx | dnet | mpls | 
> > > > bridge | link } |\n"
> > > > "-4 | -6 | -I | -D | -B | -0 |\n"
> > > > -"-l[oops] { maximum-addr-flush-attempts } | 
> > > > -br[ief] |\n"
> > > > +"-l[oops] { maximum-addr-flush-attempts } | 
> > > > -br[ief] | -tr[ee] |\n"
> > > > "-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] 
> > > > [filename] |\n"
> > > > "-rc[vbuf] [size] | -n[etns] name | -a[ll] | 
> > > > -c[olor]}\n");
> > > > exit(-1);
> > > > @@ -257,6 +258,8 @@ int main(int argc, char **argv)
> > > > > > > > > > > > batch_file = argv[1];
> > > > > > > > > > > > } else if (matches(opt, "-brief") == 0) 
> > > > > > > > > > > > {
> > > > > > > > > > > > ++brief;
> > > > > > > > > > > > +   } else if (matches(opt, "-tree") == 0) {
> > > > > > > > > > > > +   ++tree;
> > > > > > > > > > > > } else if (matches(opt, "-rcvbuf") == 
> > > > > > > > > > > > 0) {
> > > > > > unsigned int size;
> > > > 
> > > > diff --git a/ip/ipaddress.c b/ip/ipaddress.c
> > > > index 242c6ea..5ebcb1a 100644
> > > > --- a/ip/ipaddress.c
> > > > +++ b/ip/ipaddress.c
> > > > @@ -1534,6 +1534,69 @@ static int iplink_filter_req(struct nlmsghdr 
> > > > *nlh, int reqlen)
&g

Re: [PATCH] iproute2: show network device dependency tree

2017-02-25 Thread Zaboj Campula
On Sat, 2017-02-25 at 18:39 +0100, Jiri Pirko wrote:
> > Sat, Feb 25, 2017 at 05:59:00PM CET, zaboj.camp...@post.cz wrote:
> > Add the argument '-tree' to ip-link to show network devices dependency tree.
> > 
> > Example:
> > 
> > $ ip -tree link
> > eth0
> >    bond0
> > eth1
> >    bond0
> > eth2
> >    bond1
> > eth3
> >    bond1
> 
> 
> Hmm, what is this good for? I'm probably missing something...

I consider this kind of output useful when troubleshooting a complex
configuration with many interfaces. It may show relations among
interfaces.


> 
> 
> 
> > 
> > > > Signed-off-by: Zaboj Campula <zaboj.camp...@post.cz>
> > ---
> > include/utils.h |  1 +
> > ip/ip.c |  5 ++-
> > ip/ipaddress.c  | 97 
> > -
> > 3 files changed, 87 insertions(+), 16 deletions(-)
> > 
> > diff --git a/include/utils.h b/include/utils.h
> > index 22369e0..f1acf4d 100644
> > --- a/include/utils.h
> > +++ b/include/utils.h
> > @@ -20,6 +20,7 @@ extern int show_raw;
> > extern int resolve_hosts;
> > extern int oneline;
> > extern int brief;
> > +extern int tree;;
> > extern int timestamp;
> > extern int timestamp_short;
> > extern const char * _SL_;
> > diff --git a/ip/ip.c b/ip/ip.c
> > index 07050b0..29747a5 100644
> > --- a/ip/ip.c
> > +++ b/ip/ip.c
> > @@ -33,6 +33,7 @@ int show_details;
> > int resolve_hosts;
> > int oneline;
> > int brief;
> > +int tree;
> > int timestamp;
> > const char *_SL_;
> > int force;
> > @@ -57,7 +58,7 @@ static void usage(void)
> > "-h[uman-readable] | -iec |\n"
> > "-f[amily] { inet | inet6 | ipx | dnet | mpls | bridge 
> > | link } |\n"
> > "-4 | -6 | -I | -D | -B | -0 |\n"
> > -"-l[oops] { maximum-addr-flush-attempts } | -br[ief] 
> > |\n"
> > +"-l[oops] { maximum-addr-flush-attempts } | -br[ief] | 
> > -tr[ee] |\n"
> > "-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] 
> > [filename] |\n"
> > "-rc[vbuf] [size] | -n[etns] name | -a[ll] | 
> > -c[olor]}\n");
> > exit(-1);
> > @@ -257,6 +258,8 @@ int main(int argc, char **argv)
> > > > batch_file = argv[1];
> > > > } else if (matches(opt, "-brief") == 0) {
> > > > ++brief;
> > > > +   } else if (matches(opt, "-tree") == 0) {
> > > > +   ++tree;
> > > > } else if (matches(opt, "-rcvbuf") == 0) {
> > > > unsigned int size;
> > 
> > diff --git a/ip/ipaddress.c b/ip/ipaddress.c
> > index 242c6ea..5ebcb1a 100644
> > --- a/ip/ipaddress.c
> > +++ b/ip/ipaddress.c
> > @@ -1534,6 +1534,69 @@ static int iplink_filter_req(struct nlmsghdr *nlh, 
> > int reqlen)
> > return 0;
> > }
> > 
> > +static int has_master(struct nlmsg_chain *linfo, int index)
> > +{
> > > > +   struct nlmsg_list *l;
> > > > +   struct rtattr *tb[IFLA_MAX+1];
> > > > +   int len;
> > > > +   for (l = linfo->head; l; l = l->next) {
> > > > +   struct ifinfomsg *ifi = NLMSG_DATA(>h);
> > > > +   len = l->h.nlmsg_len;
> > > > +   len -= NLMSG_LENGTH(sizeof(*ifi));
> > > > +   parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
> > > > +   if (tb[IFLA_MASTER] && *(int 
> > > > *)RTA_DATA(tb[IFLA_MASTER]) == index)
> > > > +   return 1;
> > > > +   }
> > > > +   return 0;
> > +}
> > +
> > +static struct nlmsg_list *get_master(struct nlmsg_chain *linfo, struct 
> > rtattr **tb)
> > +{
> > > > +   struct nlmsg_list *l;
> > > > +   if (tb[IFLA_MASTER]) {
> > > > +   int master = *(int *)RTA_DATA(tb[IFLA_MASTER]);
> > > > +   for (l = linfo->head; l; l = l->next) {
> > > > +   struct ifinfomsg *ifi = NLMSG_DATA(>h);
> > > > +   if (ifi->ifi_index == master)
> > > > +   return l;
> > > > +  

[PATCH] iproute2: show network device dependency tree

2017-02-25 Thread Zaboj Campula
Add the argument '-tree' to ip-link to show network devices dependency tree.

Example:

$ ip -tree link
eth0
bond0
eth1
bond0
eth2
bond1
eth3
bond1

Signed-off-by: Zaboj Campula <zaboj.camp...@post.cz>
---
 include/utils.h |  1 +
 ip/ip.c |  5 ++-
 ip/ipaddress.c  | 97 -
 3 files changed, 87 insertions(+), 16 deletions(-)

diff --git a/include/utils.h b/include/utils.h
index 22369e0..f1acf4d 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -20,6 +20,7 @@ extern int show_raw;
 extern int resolve_hosts;
 extern int oneline;
 extern int brief;
+extern int tree;;
 extern int timestamp;
 extern int timestamp_short;
 extern const char * _SL_;
diff --git a/ip/ip.c b/ip/ip.c
index 07050b0..29747a5 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -33,6 +33,7 @@ int show_details;
 int resolve_hosts;
 int oneline;
 int brief;
+int tree;
 int timestamp;
 const char *_SL_;
 int force;
@@ -57,7 +58,7 @@ static void usage(void)
 "-h[uman-readable] | -iec |\n"
 "-f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | 
link } |\n"
 "-4 | -6 | -I | -D | -B | -0 |\n"
-"-l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n"
+"-l[oops] { maximum-addr-flush-attempts } | -br[ief] | 
-tr[ee] |\n"
 "-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] 
[filename] |\n"
 "-rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
exit(-1);
@@ -257,6 +258,8 @@ int main(int argc, char **argv)
batch_file = argv[1];
} else if (matches(opt, "-brief") == 0) {
++brief;
+   } else if (matches(opt, "-tree") == 0) {
+   ++tree;
} else if (matches(opt, "-rcvbuf") == 0) {
unsigned int size;
 
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 242c6ea..5ebcb1a 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1534,6 +1534,69 @@ static int iplink_filter_req(struct nlmsghdr *nlh, int 
reqlen)
return 0;
 }
 
+static int has_master(struct nlmsg_chain *linfo, int index)
+{
+   struct nlmsg_list *l;
+   struct rtattr *tb[IFLA_MAX+1];
+   int len;
+   for (l = linfo->head; l; l = l->next) {
+   struct ifinfomsg *ifi = NLMSG_DATA(>h);
+   len = l->h.nlmsg_len;
+   len -= NLMSG_LENGTH(sizeof(*ifi));
+   parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+   if (tb[IFLA_MASTER] && *(int *)RTA_DATA(tb[IFLA_MASTER]) == 
index)
+   return 1;
+   }
+   return 0;
+}
+
+static struct nlmsg_list *get_master(struct nlmsg_chain *linfo, struct rtattr 
**tb)
+{
+   struct nlmsg_list *l;
+   if (tb[IFLA_MASTER]) {
+   int master = *(int *)RTA_DATA(tb[IFLA_MASTER]);
+   for (l = linfo->head; l; l = l->next) {
+   struct ifinfomsg *ifi = NLMSG_DATA(>h);
+   if (ifi->ifi_index == master)
+   return l;
+   }
+   }
+   return NULL;
+}
+
+static void print_dev_tree_item(struct nlmsg_chain *linfo, struct nlmsg_list 
*l, int indent) {
+   char *name;
+   int len;
+   struct ifinfomsg *ifi = NLMSG_DATA(>h);
+   struct rtattr *tb[IFLA_MAX+1];
+   len = l->h.nlmsg_len;
+   len -= NLMSG_LENGTH(sizeof(*ifi));
+   parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+   name = (char *)(tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : 
"");
+
+   printf("%*s%s\n", indent * 4, "", name);
+
+   struct nlmsg_list *master = get_master(linfo, tb);
+   if (master) {
+   if (indent > 8) {
+   printf("%*s...\n", (indent + 1) * 4, "");
+   } else {
+   print_dev_tree_item(linfo, master, indent + 1);
+   }
+   }
+}
+
+static void print_devtree(struct nlmsg_chain *linfo)
+{
+   struct nlmsg_list *l;
+   for (l = linfo->head; l; l = l->next) {
+   struct ifinfomsg *ifi = NLMSG_DATA(>h);
+   if (!has_master(linfo, ifi->ifi_index)) {
+   print_dev_tree_item(linfo, l, 0);
+   }
+   }
+}
+
 static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 {
struct nlmsg_chain linfo = { NULL, NULL};
@@ -1742,23 +1805,27 @@ static int ipaddr_list_flush_or_save(int argc, char 
**argv, int action)
ipaddr_filter(, );
}
 
-   for (l = linfo.head; l; l = l->next) {
-   int res = 0;
-   struct ifinfomsg *ifi = NLMSG_DATA(>h);
-
-