summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2017-05-27 17:34:50 -0600
committerStephen Hemminger <stephen@networkplumber.org>2017-05-30 17:54:03 -0700
commit1dddb60503fd79fc65f2692287965801677dcf20 (patch)
tree6d9d778b3410b9b6edf72681590131eba6186282
parent63891c70137f200105c539c92eb73abade2c05d5 (diff)
downloadiproute2-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.c153
-rw-r--r--man/man8/ip-vrf.811
2 files changed, 159 insertions, 5 deletions
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index 0f611b44..0094cf85 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -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