diff options
author | David Ahern <dsahern@gmail.com> | 2017-05-27 17:34:50 -0600 |
---|---|---|
committer | Stephen Hemminger <stephen@networkplumber.org> | 2017-05-30 17:54:03 -0700 |
commit | 1dddb60503fd79fc65f2692287965801677dcf20 (patch) | |
tree | 6d9d778b3410b9b6edf72681590131eba6186282 | |
parent | 63891c70137f200105c539c92eb73abade2c05d5 (diff) | |
download | iproute2-1dddb60503fd79fc65f2692287965801677dcf20.tar.gz |
ip vrf: Add show command
Add show command to list all configured VRF and their table ids.
Signed-off-by: David Ahern <dsahern@gmail.com>
-rw-r--r-- | ip/ipvrf.c | 153 | ||||
-rw-r--r-- | man/man8/ip-vrf.8 | 11 |
2 files changed, 159 insertions, 5 deletions
@@ -32,9 +32,12 @@ #define CGRP_PROC_FILE "/cgroup.procs" +static struct link_filter vrf_filter; + static void usage(void) { - fprintf(stderr, "Usage: ip vrf exec [NAME] cmd ...\n"); + fprintf(stderr, "Usage: ip vrf show [NAME] ...\n"); + fprintf(stderr, " ip vrf exec [NAME] cmd ...\n"); fprintf(stderr, " ip vrf identify [PID]\n"); fprintf(stderr, " ip vrf pids [NAME]\n"); @@ -467,13 +470,148 @@ void vrf_reset(void) vrf_switch("default"); } -int do_ipvrf(int argc, char **argv) +static int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen) +{ + struct rtattr *linkinfo; + int err; + + if (vrf_filter.kind) { + linkinfo = addattr_nest(nlh, reqlen, IFLA_LINKINFO); + + err = addattr_l(nlh, reqlen, IFLA_INFO_KIND, vrf_filter.kind, + strlen(vrf_filter.kind)); + if (err) + return err; + + addattr_nest_end(nlh, linkinfo); + } + + return 0; +} + +/* input arg is linkinfo */ +static __u32 vrf_table_linkinfo(struct rtattr *li[]) +{ + struct rtattr *attr[IFLA_VRF_MAX + 1]; + + if (li[IFLA_INFO_DATA]) { + parse_rtattr_nested(attr, IFLA_VRF_MAX, li[IFLA_INFO_DATA]); + + if (attr[IFLA_VRF_TABLE]) + return rta_getattr_u32(attr[IFLA_VRF_TABLE]); + } + + return 0; +} + +static int ipvrf_print(struct nlmsghdr *n) +{ + struct ifinfomsg *ifi = NLMSG_DATA(n); + struct rtattr *tb[IFLA_MAX+1]; + struct rtattr *li[IFLA_INFO_MAX+1]; + int len = n->nlmsg_len; + const char *name; + __u32 tb_id; + + len -= NLMSG_LENGTH(sizeof(*ifi)); + if (len < 0) + return 0; + + if (vrf_filter.ifindex && vrf_filter.ifindex != ifi->ifi_index) + return 0; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + + /* kernel does not support filter by master device */ + if (tb[IFLA_MASTER]) { + int master = *(int *)RTA_DATA(tb[IFLA_MASTER]); + + if (vrf_filter.master && master != vrf_filter.master) + return 0; + } + + if (!tb[IFLA_IFNAME]) { + fprintf(stderr, + "BUG: device with ifindex %d has nil ifname\n", + ifi->ifi_index); + return 0; + } + name = rta_getattr_str(tb[IFLA_IFNAME]); + + /* missing LINKINFO means not VRF. e.g., kernel does not + * support filtering on kind, so userspace needs to handle + */ + if (!tb[IFLA_LINKINFO]) + return 0; + + parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + + if (!li[IFLA_INFO_KIND]) + return 0; + + if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf")) + return 0; + + tb_id = vrf_table_linkinfo(li); + if (!tb_id) { + fprintf(stderr, + "BUG: VRF %s is missing table id\n", name); + return 0; + } + + printf("%-16s %5u", name, tb_id); + + printf("\n"); + return 1; +} + +static int ipvrf_show(int argc, char **argv) { - if (argc == 0) { - fprintf(stderr, "No command given. Try \"ip vrf help\".\n"); - exit(-1); + struct nlmsg_chain linfo = { NULL, NULL}; + int rc = 0; + + vrf_filter.kind = "vrf"; + + if (argc > 1) + usage(); + + if (argc == 1) { + __u32 tb_id; + + tb_id = ipvrf_get_table(argv[0]); + if (!tb_id) { + fprintf(stderr, "Invalid VRF\n"); + return 1; + } + printf("%s %u\n", argv[0], tb_id); + return 0; } + if (ip_linkaddr_list(0, ipvrf_filter_req, &linfo, NULL) == 0) { + struct nlmsg_list *l; + unsigned nvrf = 0; + int n; + + n = printf("%-16s %5s\n", "Name", "Table"); + printf("%.*s\n", n-1, "-----------------------"); + for (l = linfo.head; l; l = l->next) + nvrf += ipvrf_print(&l->h); + + if (!nvrf) + printf("No VRF has been configured\n"); + } else + rc = 1; + + free_nlmsg_chain(&linfo); + + return rc; +} + +int do_ipvrf(int argc, char **argv) +{ + if (argc == 0) + return ipvrf_show(0, NULL); + if (matches(*argv, "identify") == 0) return ipvrf_identify(argc-1, argv+1); @@ -483,6 +621,11 @@ int do_ipvrf(int argc, char **argv) if (matches(*argv, "exec") == 0) return ipvrf_exec(argc-1, argv+1); + if (matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return ipvrf_show(argc-1, argv+1); + if (matches(*argv, "help") == 0) usage(); diff --git a/man/man8/ip-vrf.8 b/man/man8/ip-vrf.8 index 57a7c769..18789339 100644 --- a/man/man8/ip-vrf.8 +++ b/man/man8/ip-vrf.8 @@ -13,6 +13,10 @@ ip-vrf \- run a command against a vrf .sp .ti -8 +.BR "ip vrf show" +.RI "[ " NAME " ]" + +.ti -8 .BR "ip vrf identify" .RI "[ " PID " ]" @@ -45,6 +49,13 @@ is a helper to run a command against a specific VRF with the VRF association inherited parent to child. .TP +.B ip vrf show [ NAME ] - Show all configured VRF +.sp +This command lists all VRF and their corresponding table ids. If NAME is +given, then only that VRF and table id is shown. The latter command is +useful for scripting where the table id for a VRF is needed. + +.TP .B ip vrf exec [ NAME ] cmd ... - Run cmd against the named VRF .sp This command allows applications that are VRF unaware to be run against |