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(&l->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(&l->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(&l->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]) : "<nil>");
> > +
> > > > +       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(&l->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(&linfo, &ainfo);
> >     }
> > 
> > > > -       for (l = linfo.head; l; l = l->next) {
> > > > -               int res = 0;
> > > > -               struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
> > -
> > > > -               if (brief) {
> > > > -                       if (print_linkinfo_brief(NULL, &l->h, stdout) 
> > > > == 0)
> > > > +       if (tree) {
> > > > +               print_devtree(&linfo);
> > > > +       } else {
> > > > +               for (l = linfo.head; l; l = l->next) {
> > > > +                       int res = 0;
> > > > +                       struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
> > +
> > > > +                        if (brief) {
> > > > +                               if (print_linkinfo_brief(NULL, &l->h, 
> > > > stdout) == 0)
> > > > +                                       if (filter.family != AF_PACKET)
> > > > +                                               
> > > > print_selected_addrinfo(ifi,
> > > > +                                                                       
> > > > ainfo.head,
> > > > +                                                                       
> > > > stdout);
> > > > +                       } else if (no_link ||
> > > > +                                (res = print_linkinfo(NULL, &l->h, 
> > > > stdout)) >= 0) {
> > > >                                 if (filter.family != AF_PACKET)
> > > >                                         print_selected_addrinfo(ifi,
> > > > -                                                               
> > > > ainfo.head,
> > > > -                                                               stdout);
> > > > -               } else if (no_link ||
> > > > -                        (res = print_linkinfo(NULL, &l->h, stdout)) >= 
> > > > 0) {
> > > > -                       if (filter.family != AF_PACKET)
> > > > -                               print_selected_addrinfo(ifi,
> > > > -                                                       ainfo.head, 
> > > > stdout);
> > > > -                       if (res > 0 && !do_link && show_stats)
> > > > -                               print_link_stats(stdout, &l->h);
> > > > +                                                               
> > > > ainfo.head, stdout);
> > > > +                               if (res > 0 && !do_link && show_stats)
> > > > +                                       print_link_stats(stdout, &l->h);
> > > > +                       }
> > > >                 }
> >     }
> >     fflush(stdout);
> > -- 
> > 2.9.3
> > 

Reply via email to