All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 iproute2 0/6] Add support for vrf keyword
@ 2016-06-27 18:50 David Ahern
  2016-06-27 18:50 ` [PATCH iproute2 1/6] ip vrf: Add name_is_vrf David Ahern
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:50 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Currently the syntax for VRF related commands is rather kludgy and
inconsistent from one subcommand to another. This set adds support
for the VRF keyword to the link, address, neigh, and route commands
to improve the user experience listing data associated with vrfs,
modifying routes or doing a route lookup.

v2
- rebased to top of tree
- all checkpatch warnings are usage lines. The change in these
  patches is consistent with existing code for usage lines

David Ahern (6):
  ip vrf: Add name_is_vrf
  ip link/addr: Add support for vrf keyword
  ip neigh: Add support for keyword
  ip route: Change type mask to bitmask
  ip vrf: Add ipvrf_get_table
  ip route: Add support for vrf keyword

 ip/ip_common.h  |   3 ++
 ip/ipaddress.c  |  12 +++++-
 ip/iplink.c     |  15 ++++++-
 ip/iplink_vrf.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ip/ipneigh.c    |  14 ++++++-
 ip/iproute.c    |  43 ++++++++++++++++----
 6 files changed, 195 insertions(+), 11 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH iproute2 1/6] ip vrf: Add name_is_vrf
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
@ 2016-06-27 18:50 ` David Ahern
  2016-06-29 15:06   ` Stephen Hemminger
  2016-06-27 18:50 ` [PATCH v2 iproute2 2/6] ip link/addr: Add support for vrf keyword David Ahern
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:50 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Add name_is_vrf function to determine if given name corresponds to a
VRF device.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/ip_common.h  |  2 ++
 ip/iplink_vrf.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index e8da9e034b15..410eb135774a 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -90,6 +90,8 @@ struct link_util *get_link_slave_kind(const char *slave_kind);
 
 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
 
+bool name_is_vrf(char *name);
+
 #ifndef	INFINITY_LIFE_TIME
 #define     INFINITY_LIFE_TIME      0xFFFFFFFFU
 #endif
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index e3c7b4652da5..abd43c08423e 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -96,3 +96,56 @@ struct link_util vrf_slave_link_util = {
 	.print_opt	= vrf_slave_print_opt,
 	.slave          = true,
 };
+
+bool name_is_vrf(char *name)
+{
+	struct {
+		struct nlmsghdr		n;
+		struct ifinfomsg	i;
+		char			buf[1024];
+	} req = {
+		.n = {
+			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_flags = NLM_F_REQUEST,
+			.nlmsg_type  = RTM_GETLINK,
+		},
+		.i = {
+			.ifi_family  = preferred_family,
+		},
+	};
+	struct {
+		struct nlmsghdr n;
+		char buf[8192];
+	} answer;
+	struct rtattr *tb[IFLA_MAX+1];
+	struct rtattr *li[IFLA_INFO_MAX+1];
+	struct ifinfomsg *ifi;
+	int len;
+
+	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
+
+	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
+		goto err;
+
+	ifi = NLMSG_DATA(&answer.n);
+	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
+	if (len < 0) {
+		fprintf(stderr, "BUG: Invalid response to link query.\n");
+		goto err;
+	}
+
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+
+	if (!tb[IFLA_LINKINFO])
+		goto err;
+
+	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+	if (!li[IFLA_INFO_KIND])
+		goto err;
+
+	return strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf") == 0;
+
+err:
+	return false;
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 iproute2 2/6] ip link/addr: Add support for vrf keyword
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
  2016-06-27 18:50 ` [PATCH iproute2 1/6] ip vrf: Add name_is_vrf David Ahern
@ 2016-06-27 18:50 ` David Ahern
  2016-06-27 18:50 ` [PATCH iproute2 3/6] ip neigh: Add support for keyword David Ahern
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:50 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Add vrf keyword to 'ip link' and 'ip addr' commands (common list code).

Allows:
1. Adding a link to a VRF
       $ ip link set NAME vrf NAME

   Removing a link from a VRF still uses 'ip link set NAME nomaster'

2. Showing links associated with a VRF:
       $ ip link show vrf NAME

3. List addresses associated with links in a VRF
       $ ip -br addr show vrf red

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/ipaddress.c | 12 +++++++++++-
 ip/iplink.c    | 15 +++++++++++++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 8766530f7fa7..03688d422dcc 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -79,7 +79,7 @@ static void usage(void)
 	fprintf(stderr, "                            [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n");
 	fprintf(stderr, "       ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n");
 	fprintf(stderr, "                         [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n");
-	fprintf(stderr, "                         [ label LABEL ] [up] ]\n");
+	fprintf(stderr, "                         [ label LABEL ] [up] [ vrf NAME ] ]\n");
 	fprintf(stderr, "       ip address {showdump|restore}\n");
 	fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
 	fprintf(stderr, "          [ broadcast ADDR ] [ anycast ADDR ]\n");
@@ -1620,6 +1620,16 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 			if (!ifindex)
 				invarg("Device does not exist\n", *argv);
 			filter.master = ifindex;
+		} else if (strcmp(*argv, "vrf") == 0) {
+			int ifindex;
+
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (!ifindex)
+				invarg("Not a valid VRF name\n", *argv);
+			if (!name_is_vrf(*argv))
+				invarg("Not a valid VRF name\n", *argv);
+			filter.master = ifindex;
 		} else if (strcmp(*argv, "type") == 0) {
 			NEXT_ARG();
 			filter.kind = *argv;
diff --git a/ip/iplink.c b/ip/iplink.c
index b1f8a37922f5..f2a2e13cf0c5 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -82,11 +82,11 @@ void iplink_usage(void)
 	fprintf(stderr, "				   [ query_rss { on | off} ]\n");
 	fprintf(stderr, "				   [ state { auto | enable | disable} ] ]\n");
 	fprintf(stderr, "				   [ trust { on | off} ] ]\n");
-	fprintf(stderr, "			  [ master DEVICE ]\n");
+	fprintf(stderr, "			  [ master DEVICE ][ vrf NAME ]\n");
 	fprintf(stderr, "			  [ nomaster ]\n");
 	fprintf(stderr, "			  [ addrgenmode { eui64 | none | stable_secret | random } ]\n");
 	fprintf(stderr, "	                  [ protodown { on | off } ]\n");
-	fprintf(stderr, "       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
+	fprintf(stderr, "       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
 
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "       ip link help [ TYPE ]\n");
@@ -603,6 +603,17 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 				invarg("Device does not exist\n", *argv);
 			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
 				  &ifindex, 4);
+		} else if (strcmp(*argv, "vrf") == 0) {
+			int ifindex;
+
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (!ifindex)
+				invarg("Not a valid VRF name\n", *argv);
+			if (!name_is_vrf(*argv))
+				invarg("Not a valid VRF name\n", *argv);
+			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
+				  &ifindex, sizeof(ifindex));
 		} else if (matches(*argv, "nomaster") == 0) {
 			int ifindex = 0;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH iproute2 3/6] ip neigh: Add support for keyword
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
  2016-06-27 18:50 ` [PATCH iproute2 1/6] ip vrf: Add name_is_vrf David Ahern
  2016-06-27 18:50 ` [PATCH v2 iproute2 2/6] ip link/addr: Add support for vrf keyword David Ahern
@ 2016-06-27 18:50 ` David Ahern
  2016-06-27 18:50 ` [PATCH iproute2 4/6] ip route: Change type mask to bitmask David Ahern
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:50 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Add vrf keyword to 'ip neigh' commands. Allows listing neighbor
entries for all links associated with a given VRF.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/ipneigh.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 4ddb747e2086..3e444712645f 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -48,7 +48,8 @@ static void usage(void)
 {
 	fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n"
 			"                { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]\n");
-	fprintf(stderr, "       ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n\n");
+	fprintf(stderr, "       ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n");
+	fprintf(stderr, "                                 [ vrf NAME ]\n\n");
 	fprintf(stderr, "STATE := { permanent | noarp | stale | reachable | none |\n"
 			"           incomplete | delay | probe | failed }\n");
 	exit(-1);
@@ -385,6 +386,17 @@ static int do_show_or_flush(int argc, char **argv, int flush)
 				invarg("Device does not exist\n", *argv);
 			addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
 			filter.master = ifindex;
+		} else if (strcmp(*argv, "vrf") == 0) {
+			int ifindex;
+
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (!ifindex)
+				invarg("Not a valid VRF name\n", *argv);
+			if (!name_is_vrf(*argv))
+				invarg("Not a valid VRF name\n", *argv);
+			addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
+			filter.master = ifindex;
 		} else if (strcmp(*argv, "unused") == 0) {
 			filter.unused_only = 1;
 		} else if (strcmp(*argv, "nud") == 0) {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH iproute2 4/6] ip route: Change type mask to bitmask
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
                   ` (2 preceding siblings ...)
  2016-06-27 18:50 ` [PATCH iproute2 3/6] ip neigh: Add support for keyword David Ahern
@ 2016-06-27 18:50 ` David Ahern
  2016-06-27 18:51 ` [PATCH iproute2 5/6] ip vrf: Add ipvrf_get_table David Ahern
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:50 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Allow option to select multiple route types to show or exlude
specific route types.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/iproute.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index 8224d7ffa94b..aae693d17be8 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -113,7 +113,7 @@ static struct
 	int flushe;
 	int protocol, protocolmask;
 	int scope, scopemask;
-	int type, typemask;
+	__u64 typemask;
 	int tos, tosmask;
 	int iif, iifmask;
 	int oif, oifmask;
@@ -178,7 +178,8 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
 		return 0;
 	if ((filter.scope^r->rtm_scope)&filter.scopemask)
 		return 0;
-	if ((filter.type^r->rtm_type)&filter.typemask)
+
+	if (filter.typemask && !(filter.typemask & (1 << r->rtm_type)))
 		return 0;
 	if ((filter.tos^r->rtm_tos)&filter.tosmask)
 		return 0;
@@ -365,7 +366,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 
 	if (n->nlmsg_type == RTM_DELROUTE)
 		fprintf(fp, "Deleted ");
-	if ((r->rtm_type != RTN_UNICAST || show_details > 0) && !filter.type)
+	if ((r->rtm_type != RTN_UNICAST || show_details > 0) &&
+	    (!filter.typemask || (filter.typemask & (1 << r->rtm_type))))
 		fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
 
 	if (tb[RTA_DST]) {
@@ -1433,10 +1435,9 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 			int type;
 
 			NEXT_ARG();
-			filter.typemask = -1;
 			if (rtnl_rtntype_a2n(&type, *argv))
 				invarg("node type value is invalid\n", *argv);
-			filter.type = type;
+			filter.typemask = (1<<type);
 		} else if (strcmp(*argv, "dev") == 0 ||
 			   strcmp(*argv, "oif") == 0) {
 			NEXT_ARG();
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH iproute2 5/6] ip vrf: Add ipvrf_get_table
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
                   ` (3 preceding siblings ...)
  2016-06-27 18:50 ` [PATCH iproute2 4/6] ip route: Change type mask to bitmask David Ahern
@ 2016-06-27 18:51 ` David Ahern
  2016-06-27 18:51 ` [PATCH iproute2 6/6] ip route: Add support for vrf keyword David Ahern
  2016-06-29 15:07 ` [PATCH v2 iproute2 0/6] " Stephen Hemminger
  6 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:51 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Add ipvrf_get_table to lookup table id for device name. Returns 0
on any error or if name is not a VRF device.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/ip_common.h  |  1 +
 ip/iplink_vrf.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index 410eb135774a..8fdb7219fc2b 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -90,6 +90,7 @@ struct link_util *get_link_slave_kind(const char *slave_kind);
 
 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
 
+__u32 ipvrf_get_table(char *name);
 bool name_is_vrf(char *name);
 
 #ifndef	INFINITY_LIFE_TIME
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index abd43c08423e..2eecb4564f7e 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -97,6 +97,72 @@ struct link_util vrf_slave_link_util = {
 	.slave          = true,
 };
 
+/* returns table id if name is a VRF device */
+__u32 ipvrf_get_table(char *name)
+{
+	struct {
+		struct nlmsghdr		n;
+		struct ifinfomsg	i;
+		char			buf[1024];
+	} req = {
+		.n = {
+			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_flags = NLM_F_REQUEST,
+			.nlmsg_type  = RTM_GETLINK,
+		},
+		.i = {
+			.ifi_family  = preferred_family,
+		},
+	};
+	struct {
+		struct nlmsghdr n;
+		char buf[8192];
+	} answer;
+	struct rtattr *tb[IFLA_MAX+1];
+	struct rtattr *li[IFLA_INFO_MAX+1];
+	struct rtattr *vrf_attr[IFLA_VRF_MAX + 1];
+	struct ifinfomsg *ifi;
+	__u32 tb_id = 0;
+	int len;
+
+	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
+
+	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
+		goto err;
+
+	ifi = NLMSG_DATA(&answer.n);
+	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
+	if (len < 0) {
+		fprintf(stderr, "BUG: Invalid response to link query.\n");
+		goto err;
+	}
+
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+
+	if (!tb[IFLA_LINKINFO])
+		goto err;
+
+	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+	if (!li[IFLA_INFO_KIND] || !li[IFLA_INFO_DATA])
+		goto err;
+
+	if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
+		goto err;
+
+	parse_rtattr_nested(vrf_attr, IFLA_VRF_MAX, li[IFLA_INFO_DATA]);
+	if (vrf_attr[IFLA_VRF_TABLE])
+		tb_id = rta_getattr_u32(vrf_attr[IFLA_VRF_TABLE]);
+
+	if (!tb_id)
+		fprintf(stderr, "BUG: VRF %s is missing table id\n", name);
+
+	return tb_id;
+
+err:
+	return 0;
+}
+
 bool name_is_vrf(char *name)
 {
 	struct {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH iproute2 6/6] ip route: Add support for vrf keyword
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
                   ` (4 preceding siblings ...)
  2016-06-27 18:51 ` [PATCH iproute2 5/6] ip vrf: Add ipvrf_get_table David Ahern
@ 2016-06-27 18:51 ` David Ahern
  2016-06-29 15:07 ` [PATCH v2 iproute2 0/6] " Stephen Hemminger
  6 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-27 18:51 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

Add vrf keyword to 'ip route' commands. Allows:
1. Users can list routes by VRF name:
       $ ip route show vrf NAME

   VRF tables have all routes including local and broadcast routes.
   The VRF keyword filters LOCAL and BROADCAST routes; to see all
   routes the table option can be used. Or to see local routes only
   for a VRF:
       $ ip route show vrf NAME type local

2. Add or delete a route for a VRF:
       $ ip route {add|delete} vrf NAME <route spec>

3. Do a route lookup for a VRF:
       $ ip route get vrf NAME ADDRESS

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/iproute.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index aae693d17be8..bd661c16cb46 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -67,10 +67,10 @@ static void usage(void)
 	fprintf(stderr, "       ip route showdump\n");
 	fprintf(stderr, "       ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
 	fprintf(stderr, "                            [ oif STRING ] [ tos TOS ]\n");
-	fprintf(stderr, "                            [ mark NUMBER ]\n");
+	fprintf(stderr, "                            [ mark NUMBER ] [ vrf NAME ]\n");
 	fprintf(stderr, "       ip route { add | del | change | append | replace } ROUTE\n");
 	fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n");
-	fprintf(stderr, "            [ table TABLE_ID ] [ proto RTPROTO ]\n");
+	fprintf(stderr, "            [ table TABLE_ID ] [ vrf NAME ] [ proto RTPROTO ]\n");
 	fprintf(stderr, "            [ type TYPE ] [ scope SCOPE ]\n");
 	fprintf(stderr, "ROUTE := NODE_SPEC [ INFO_SPEC ]\n");
 	fprintf(stderr, "NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]\n");
@@ -1141,6 +1141,20 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
 				addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
 			}
 			table_ok = 1;
+		} else if (matches(*argv, "vrf") == 0) {
+			__u32 tid;
+
+			NEXT_ARG();
+			tid = ipvrf_get_table(*argv);
+			if (tid == 0)
+				invarg("Invalid VRF\n", *argv);
+			if (tid < 256)
+				req.r.rtm_table = tid;
+			else {
+				req.r.rtm_table = RT_TABLE_UNSPEC;
+				addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
+			}
+			table_ok = 1;
 		} else if (strcmp(*argv, "dev") == 0 ||
 			   strcmp(*argv, "oif") == 0) {
 			NEXT_ARG();
@@ -1395,6 +1409,15 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 				}
 			} else
 				filter.tb = tid;
+		} else if (matches(*argv, "vrf") == 0) {
+			__u32 tid;
+
+			NEXT_ARG();
+			tid = ipvrf_get_table(*argv);
+			if (tid == 0)
+				invarg("Invalid VRF\n", *argv);
+			filter.tb = tid;
+			filter.typemask = ~(1 << RTN_LOCAL | 1<<RTN_BROADCAST);
 		} else if (matches(*argv, "cached") == 0 ||
 			   matches(*argv, "cloned") == 0) {
 			filter.cloned = 1;
@@ -1681,6 +1704,11 @@ static int iproute_get(int argc, char **argv)
 			req.r.rtm_flags |= RTM_F_NOTIFY;
 		} else if (matches(*argv, "connected") == 0) {
 			connected = 1;
+		} else if (matches(*argv, "vrf") == 0) {
+			NEXT_ARG();
+			if (!name_is_vrf(*argv))
+				invarg("Invalid VRF\n", *argv);
+			odev = *argv;
 		} else {
 			inet_prefix addr;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH iproute2 1/6] ip vrf: Add name_is_vrf
  2016-06-27 18:50 ` [PATCH iproute2 1/6] ip vrf: Add name_is_vrf David Ahern
@ 2016-06-29 15:06   ` Stephen Hemminger
  2016-06-29 16:57     ` David Ahern
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen Hemminger @ 2016-06-29 15:06 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev

On Mon, 27 Jun 2016 11:50:56 -0700
David Ahern <dsa@cumulusnetworks.com> wrote:

> diff --git a/ip/ip_common.h b/ip/ip_common.h
> index e8da9e034b15..410eb135774a 100644
> --- a/ip/ip_common.h
> +++ b/ip/ip_common.h
> @@ -90,6 +90,8 @@ struct link_util *get_link_slave_kind(const char *slave_kind);
>  
>  void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
>  
> +bool name_is_vrf(char *name);
> +
>  #ifndef	INFINITY_LIFE_TIME
>  #define     INFINITY_LIFE_TIME      0xFFFFFFFFU
>  #endif
> diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
> index e3c7b4652da5..abd43c08423e 100644
> --- a/ip/iplink_vrf.c
> +++ b/ip/iplink_vrf.c
> @@ -96,3 +96,56 @@ struct link_util vrf_slave_link_util = {
>  	.print_opt	= vrf_slave_print_opt,
>  	.slave          = true,
>  };
> +
> +bool name_is_vrf(char *name)

Why not?
bool name_is_vrf(const char *name)

> +{
> +	struct {
> +		struct nlmsghdr		n;
> +		struct ifinfomsg	i;
> +		char			buf[1024];
> +	} req = {
> +		.n = {
> +			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
> +			.nlmsg_flags = NLM_F_REQUEST,
> +			.nlmsg_type  = RTM_GETLINK,
> +		},
> +		.i = {
> +			.ifi_family  = preferred_family,
> +		},
> +	};
> +	struct {
> +		struct nlmsghdr n;
> +		char buf[8192];
> +	} answer;
> +	struct rtattr *tb[IFLA_MAX+1];
> +	struct rtattr *li[IFLA_INFO_MAX+1];
> +	struct ifinfomsg *ifi;
> +	int len;
> +
> +	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
> +
> +	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
> +		goto err;
Just return false instead of all these goto's?
Also you might want to give some indication of error.

> +
> +	ifi = NLMSG_DATA(&answer.n);
> +	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
> +	if (len < 0) {
> +		fprintf(stderr, "BUG: Invalid response to link query.\n");
> +		goto err;
> +	}
> +
> +	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
> +
> +	if (!tb[IFLA_LINKINFO])
> +		goto err;
> +
> +	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
> +
> +	if (!li[IFLA_INFO_KIND])
> +		goto err;
> +
> +	return strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf") == 0;
> +
> +err:
> +	return false;
> +}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 iproute2 0/6] Add support for vrf keyword
  2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
                   ` (5 preceding siblings ...)
  2016-06-27 18:51 ` [PATCH iproute2 6/6] ip route: Add support for vrf keyword David Ahern
@ 2016-06-29 15:07 ` Stephen Hemminger
  2016-06-29 17:06   ` David Ahern
  6 siblings, 1 reply; 11+ messages in thread
From: Stephen Hemminger @ 2016-06-29 15:07 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev

On Mon, 27 Jun 2016 11:50:55 -0700
David Ahern <dsa@cumulusnetworks.com> wrote:

> Currently the syntax for VRF related commands is rather kludgy and
> inconsistent from one subcommand to another. This set adds support
> for the VRF keyword to the link, address, neigh, and route commands
> to improve the user experience listing data associated with vrfs,
> modifying routes or doing a route lookup.
> 
> v2
> - rebased to top of tree
> - all checkpatch warnings are usage lines. The change in these
>   patches is consistent with existing code for usage lines

Does this break current user scripts?

It seems this method will cause lots of additional netlink requests
to check if device is a vrf. Won't this impact users with 1000's of devices?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH iproute2 1/6] ip vrf: Add name_is_vrf
  2016-06-29 15:06   ` Stephen Hemminger
@ 2016-06-29 16:57     ` David Ahern
  0 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-29 16:57 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

On 6/29/16 9:06 AM, Stephen Hemminger wrote:
> On Mon, 27 Jun 2016 11:50:56 -0700
> David Ahern <dsa@cumulusnetworks.com> wrote:
>
>> diff --git a/ip/ip_common.h b/ip/ip_common.h
>> index e8da9e034b15..410eb135774a 100644
>> --- a/ip/ip_common.h
>> +++ b/ip/ip_common.h
>> @@ -90,6 +90,8 @@ struct link_util *get_link_slave_kind(const char *slave_kind);
>>
>>  void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
>>
>> +bool name_is_vrf(char *name);
>> +
>>  #ifndef	INFINITY_LIFE_TIME
>>  #define     INFINITY_LIFE_TIME      0xFFFFFFFFU
>>  #endif
>> diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
>> index e3c7b4652da5..abd43c08423e 100644
>> --- a/ip/iplink_vrf.c
>> +++ b/ip/iplink_vrf.c
>> @@ -96,3 +96,56 @@ struct link_util vrf_slave_link_util = {
>>  	.print_opt	= vrf_slave_print_opt,
>>  	.slave          = true,
>>  };
>> +
>> +bool name_is_vrf(char *name)
>
> Why not?
> bool name_is_vrf(const char *name)

sure.

>
>> +{
>> +	struct {
>> +		struct nlmsghdr		n;
>> +		struct ifinfomsg	i;
>> +		char			buf[1024];
>> +	} req = {
>> +		.n = {
>> +			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
>> +			.nlmsg_flags = NLM_F_REQUEST,
>> +			.nlmsg_type  = RTM_GETLINK,
>> +		},
>> +		.i = {
>> +			.ifi_family  = preferred_family,
>> +		},
>> +	};
>> +	struct {
>> +		struct nlmsghdr n;
>> +		char buf[8192];
>> +	} answer;
>> +	struct rtattr *tb[IFLA_MAX+1];
>> +	struct rtattr *li[IFLA_INFO_MAX+1];
>> +	struct ifinfomsg *ifi;
>> +	int len;
>> +
>> +	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
>> +
>> +	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
>> +		goto err;
> Just return false instead of all these goto's?
> Also you might want to give some indication of error.

Any failure and the user gets the message "not a VRF". The reason can be 
the device is not a VRF or the device does not exist but that's the same 
thing in this case:

$ ./ip link show vrf foo
Error: argument "foo" is wrong: Not a valid VRF name

$ ./ip link show vrf eth1
Error: argument "eth1" is wrong: Not a valid VRF name

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 iproute2 0/6] Add support for vrf keyword
  2016-06-29 15:07 ` [PATCH v2 iproute2 0/6] " Stephen Hemminger
@ 2016-06-29 17:06   ` David Ahern
  0 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2016-06-29 17:06 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

On 6/29/16 9:07 AM, Stephen Hemminger wrote:
> On Mon, 27 Jun 2016 11:50:55 -0700
> David Ahern <dsa@cumulusnetworks.com> wrote:
>
>> Currently the syntax for VRF related commands is rather kludgy and
>> inconsistent from one subcommand to another. This set adds support
>> for the VRF keyword to the link, address, neigh, and route commands
>> to improve the user experience listing data associated with vrfs,
>> modifying routes or doing a route lookup.
>>
>> v2
>> - rebased to top of tree
>> - all checkpatch warnings are usage lines. The change in these
>>   patches is consistent with existing code for usage lines
>
> Does this break current user scripts?

I don't see how it can. Existing syntax is not touched so if a user 
wants to run:

$ ip link show master red
$ ip ro sh table 1001

it still works. Using the vrf keyword just makes for a more natural syntax:

$ ip link show vrf red
$ ip ro sh vrf red

in this case I don't have to lookup what table device red is associated 
with ip learns it and shows that table.

>
> It seems this method will cause lots of additional netlink requests
> to check if device is a vrf. Won't this impact users with 1000's of devices?
>

It only adds 1 GETLINK request if the vrf keyword is used. The lookup 
verifies the name is actually a VRF. It's really no different than the 
ll_name_to_index lookups used when processing the command line 
(ll_name_to_index relies on a cache or an ioctl, if_nametoindex).

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-06-29 17:06 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-27 18:50 [PATCH v2 iproute2 0/6] Add support for vrf keyword David Ahern
2016-06-27 18:50 ` [PATCH iproute2 1/6] ip vrf: Add name_is_vrf David Ahern
2016-06-29 15:06   ` Stephen Hemminger
2016-06-29 16:57     ` David Ahern
2016-06-27 18:50 ` [PATCH v2 iproute2 2/6] ip link/addr: Add support for vrf keyword David Ahern
2016-06-27 18:50 ` [PATCH iproute2 3/6] ip neigh: Add support for keyword David Ahern
2016-06-27 18:50 ` [PATCH iproute2 4/6] ip route: Change type mask to bitmask David Ahern
2016-06-27 18:51 ` [PATCH iproute2 5/6] ip vrf: Add ipvrf_get_table David Ahern
2016-06-27 18:51 ` [PATCH iproute2 6/6] ip route: Add support for vrf keyword David Ahern
2016-06-29 15:07 ` [PATCH v2 iproute2 0/6] " Stephen Hemminger
2016-06-29 17:06   ` David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.