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...



>
>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