All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse()
@ 2018-02-20 21:37 Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine Serhey Popovych
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

This is main routine to parse ip-link(8) configuration parameters.

Main reason to improve it is to pass network device @name, @dev and
other parameters to kind specific ->parse_opt() function so they can use
this information.

For example later we will extend iplink_get() to parse netlink
attributes deeper and replace open coded rtnl_talk() in ip/tunnel
modules to simplify getting existing tunnel information.

Among main change there is a number of patches to prepare for it
that improve iplink_parse() in some way.

See individual patch description message for more information.

v2
  Terminate via exit() when failing to parse command line arguments
  to help identify failing line in batch mode.

Thanks,
Serhii

Serhey Popovych (7):
  utils: Introduce and use nodev() helper routine
  iplink: Correctly report error when network device isn't found
  iplink: Use "dev" and "name" parameters interchangeable when possible
  iplink: Follow documented behaviour when "index" is given
  iplink: Perform most of request buffer setups and checks in
    iplink_parse()
  iplink: Move data structures to block of their users
  iplink: Reduce number of arguments to iplink_parse()

 bridge/fdb.c             |   17 ++--
 bridge/link.c            |    8 +-
 bridge/mdb.c             |   19 ++---
 bridge/vlan.c            |    7 +-
 include/utils.h          |    1 +
 ip/ip6tunnel.c           |    6 +-
 ip/ip_common.h           |   17 +++-
 ip/ipaddress.c           |    7 +-
 ip/iplink.c              |  200 +++++++++++++++++++++++++++-------------------
 ip/iplink_bond.c         |    8 +-
 ip/iplink_bond_slave.c   |    4 +-
 ip/iplink_bridge.c       |   11 ++-
 ip/iplink_bridge_slave.c |    4 +-
 ip/iplink_can.c          |    4 +-
 ip/iplink_geneve.c       |    4 +-
 ip/iplink_hsr.c          |    4 +-
 ip/iplink_ipoib.c        |    4 +-
 ip/iplink_ipvlan.c       |    4 +-
 ip/iplink_macvlan.c      |    4 +-
 ip/iplink_vlan.c         |    4 +-
 ip/iplink_vrf.c          |    5 +-
 ip/iplink_vxcan.c        |   39 +++------
 ip/iplink_vxlan.c        |   11 ++-
 ip/iplink_xdp.c          |    7 +-
 ip/ipmacsec.c            |    4 +-
 ip/ipmroute.c            |    7 +-
 ip/ipneigh.c             |   15 ++--
 ip/ipntable.c            |    6 +-
 ip/iproute.c             |   36 +++------
 ip/iproute_lwtunnel.c    |    4 +-
 ip/iptunnel.c            |    6 +-
 ip/link_gre.c            |   43 +++++-----
 ip/link_gre6.c           |   43 +++++-----
 ip/link_ip6tnl.c         |   40 +++++-----
 ip/link_iptnl.c          |   40 +++++-----
 ip/link_veth.c           |   39 +++------
 ip/link_vti.c            |   43 +++++-----
 ip/link_vti6.c           |   43 +++++-----
 lib/utils.c              |    6 ++
 tc/m_mirred.c            |    6 +-
 tc/tc_class.c            |   14 ++--
 tc/tc_filter.c           |   18 ++---
 tc/tc_qdisc.c            |   12 +--
 43 files changed, 405 insertions(+), 419 deletions(-)

-- 
1.7.10.4

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

* [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-21  5:13   ` David Ahern
  2018-02-20 21:37 ` [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found Serhey Popovych
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

There is a couple of places where we report error in case of no network
device is found. In all of them we output message in the same format to
stderr and either return -1 or 1 to the caller or exit with -1.

Introduce new helper function nodev() that takes name of the network
device caused error and returns -1 to it's caller. Either call exit()
or return to the caller to preserve behaviour before change.

Use -nodev() in traffic control (tc) code to return 1.

Simplify expression for checking for argument being 0/NULL in @if
statement.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 bridge/fdb.c          |   17 ++++++-----------
 bridge/link.c         |    8 +++-----
 bridge/mdb.c          |   19 ++++++-------------
 bridge/vlan.c         |    7 ++-----
 include/utils.h       |    1 +
 ip/ip6tunnel.c        |    6 ++----
 ip/ipaddress.c        |    7 +++----
 ip/iplink.c           |   13 ++++---------
 ip/iplink_bond.c      |    4 ++--
 ip/iplink_bridge.c    |    7 ++-----
 ip/iplink_vxlan.c     |    7 ++-----
 ip/ipmroute.c         |    7 +++----
 ip/ipneigh.c          |   15 ++++++++-------
 ip/ipntable.c         |    6 ++----
 ip/iproute.c          |   36 ++++++++++++------------------------
 ip/iproute_lwtunnel.c |    4 ++--
 ip/iptunnel.c         |    6 ++----
 ip/link_gre.c         |    7 ++-----
 ip/link_gre6.c        |    7 ++-----
 ip/link_ip6tnl.c      |    4 ++--
 ip/link_iptnl.c       |    4 ++--
 ip/link_vti.c         |    7 ++-----
 ip/link_vti6.c        |    7 ++-----
 lib/utils.c           |    6 ++++++
 tc/m_mirred.c         |    6 ++----
 tc/tc_class.c         |   14 ++++++--------
 tc/tc_filter.c        |   18 ++++++------------
 tc/tc_qdisc.c         |   12 ++++--------
 28 files changed, 98 insertions(+), 164 deletions(-)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index 8b133f9..2ba1cde 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -375,11 +375,8 @@ static int fdb_show(int argc, char **argv)
 	/*we'll keep around filter_dev for older kernels */
 	if (filter_dev) {
 		filter_index = ll_name_to_index(filter_dev);
-		if (filter_index == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n",
-				filter_dev);
-			return -1;
-		}
+		if (!filter_index)
+			return nodev(filter_dev);
 		req.ifm.ifi_index = filter_index;
 	}
 
@@ -464,8 +461,8 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
 		} else if (strcmp(*argv, "via") == 0) {
 			NEXT_ARG();
 			via = ll_name_to_index(*argv);
-			if (via == 0)
-				invarg("invalid device\n", *argv);
+			if (!via)
+				exit(nodev(*argv));
 		} else if (strcmp(*argv, "self") == 0) {
 			req.ndm.ndm_flags |= NTF_SELF;
 		} else if (matches(*argv, "master") == 0) {
@@ -540,10 +537,8 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
 		addattr32(&req.n, sizeof(req), NDA_IFINDEX, via);
 
 	req.ndm.ndm_ifindex = ll_name_to_index(d);
-	if (req.ndm.ndm_ifindex == 0) {
-		fprintf(stderr, "Cannot find device \"%s\"\n", d);
-		return -1;
-	}
+	if (!req.ndm.ndm_ifindex)
+		return nodev(d);
 
 	if (rtnl_talk(&rth, &req.n, NULL) < 0)
 		return -1;
diff --git a/bridge/link.c b/bridge/link.c
index 90c9734..1ea9c00 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -470,11 +470,9 @@ static int brlink_show(int argc, char **argv)
 	}
 
 	if (filter_dev) {
-		if ((filter_index = ll_name_to_index(filter_dev)) == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n",
-				filter_dev);
-			return -1;
-		}
+		filter_index = ll_name_to_index(filter_dev);
+		if (!filter_index)
+			return nodev(filter_dev);
 	}
 
 	if (show_details) {
diff --git a/bridge/mdb.c b/bridge/mdb.c
index 62dc8a0..e3f6978 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -312,11 +312,8 @@ static int mdb_show(int argc, char **argv)
 
 	if (filter_dev) {
 		filter_index = ll_name_to_index(filter_dev);
-		if (filter_index == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n",
-				filter_dev);
-			return -1;
-		}
+		if (!filter_index)
+			return nodev(filter_dev);
 	}
 
 	/* get mdb entries*/
@@ -418,16 +415,12 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
 	}
 
 	req.bpm.ifindex = ll_name_to_index(d);
-	if (req.bpm.ifindex == 0) {
-		fprintf(stderr, "Cannot find device \"%s\"\n", d);
-		return -1;
-	}
+	if (!req.bpm.ifindex)
+		return nodev(d);
 
 	entry.ifindex = ll_name_to_index(p);
-	if (entry.ifindex == 0) {
-		fprintf(stderr, "Cannot find device \"%s\"\n", p);
-		return -1;
-	}
+	if (!entry.ifindex)
+		return nodev(p);
 
 	if (!inet_pton(AF_INET, grp, &entry.addr.u.ip4)) {
 		if (!inet_pton(AF_INET6, grp, &entry.addr.u.ip6)) {
diff --git a/bridge/vlan.c b/bridge/vlan.c
index f42d7e6..3304348 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -568,11 +568,8 @@ static int vlan_show(int argc, char **argv)
 
 	if (filter_dev) {
 		filter_index = ll_name_to_index(filter_dev);
-		if (filter_index == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n",
-				filter_dev);
-			return -1;
-		}
+		if (!filter_index)
+			return nodev(filter_dev);
 	}
 
 	if (!show_stats) {
diff --git a/include/utils.h b/include/utils.h
index 75ddb4a..50721f2 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -182,6 +182,7 @@ void missarg(const char *) __attribute__((noreturn));
 void invarg(const char *, const char *) __attribute__((noreturn));
 void duparg(const char *, const char *) __attribute__((noreturn));
 void duparg2(const char *, const char *) __attribute__((noreturn));
+int nodev(const char *dev);
 int check_ifname(const char *);
 int get_ifname(char *, const char *);
 const char *get_ifname_rta(int ifindex, const struct rtattr *rta);
diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c
index c7fa082..999408e 100644
--- a/ip/ip6tunnel.c
+++ b/ip/ip6tunnel.c
@@ -296,10 +296,8 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
 	}
 	if (medium) {
 		p->link = ll_name_to_index(medium);
-		if (p->link == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", medium);
-			return -1;
-		}
+		if (!p->link)
+			return nodev(medium);
 	}
 	return 0;
 }
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 768e2ed..5cf13ef 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -2211,10 +2211,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 	if (!scoped && cmd != RTM_DELADDR)
 		req.ifa.ifa_scope = default_scope(&lcl);
 
-	if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
-		fprintf(stderr, "Cannot find device \"%s\"\n", d);
-		return -1;
-	}
+	req.ifa.ifa_index = ll_name_to_index(d);
+	if (!req.ifa.ifa_index)
+		return nodev(d);
 
 	if (valid_lftp || preferred_lftp) {
 		struct ifa_cacheinfo cinfo = {};
diff --git a/ip/iplink.c b/ip/iplink.c
index 74c377c..5471626 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -981,10 +981,8 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 		}
 
 		req.i.ifi_index = ll_name_to_index(dev);
-		if (req.i.ifi_index == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", dev);
-			return -1;
-		}
+		if (!req.i.ifi_index)
+			return nodev(dev);
 	} else {
 		/* Allow "ip link add dev" and "ip link add name" */
 		if (!name)
@@ -994,11 +992,8 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 			int ifindex;
 
 			ifindex = ll_name_to_index(link);
-			if (ifindex == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					link);
-				return -1;
-			}
+			if (!ifindex)
+				return nodev(link);
 			addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4);
 		}
 
diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c
index 8e8723a..f906e7f 100644
--- a/ip/iplink_bond.c
+++ b/ip/iplink_bond.c
@@ -179,7 +179,7 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
 			NEXT_ARG();
 			ifindex = ll_name_to_index(*argv);
 			if (!ifindex)
-				return -1;
+				return nodev(*argv);
 			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
 		} else if (matches(*argv, "clear_active_slave") == 0) {
 			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
@@ -242,7 +242,7 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
 			NEXT_ARG();
 			ifindex = ll_name_to_index(*argv);
 			if (!ifindex)
-				return -1;
+				return nodev(*argv);
 			addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
 		} else if (matches(*argv, "primary_reselect") == 0) {
 			NEXT_ARG();
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 06ec092..3008e44 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -793,11 +793,8 @@ int bridge_parse_xstats(struct link_util *lu, int argc, char **argv)
 		} else if (strcmp(*argv, "dev") == 0) {
 			NEXT_ARG();
 			filter_index = ll_name_to_index(*argv);
-			if (filter_index == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				return -1;
-			}
+			if (!filter_index)
+				return nodev(*argv);
 		} else if (strcmp(*argv, "help") == 0) {
 			bridge_print_xstats_help(lu, stdout);
 			exit(0);
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index d768c07..be9f35e 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -133,11 +133,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 			NEXT_ARG();
 			check_duparg(&attrs, IFLA_VXLAN_LINK, "dev", *argv);
 			link = ll_name_to_index(*argv);
-			if (link == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				exit(-1);
-			}
+			if (!link)
+				exit(nodev(*argv));
 			addattr32(n, 1024, IFLA_VXLAN_LINK, link);
 		} else if (!matches(*argv, "ttl") ||
 			   !matches(*argv, "hoplimit")) {
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b..5c232e8 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -244,10 +244,9 @@ static int mroute_list(int argc, char **argv)
 	if (id)  {
 		int idx;
 
-		if ((idx = ll_name_to_index(id)) == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", id);
-			return -1;
-		}
+		idx = ll_name_to_index(id);
+		if (!idx)
+			return nodev(id);
 		filter.iif = idx;
 	}
 
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 0735424..9c9cd23 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -178,11 +178,13 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
 
 	ll_init_map(&rth);
 
-	if (dev && (req.ndm.ndm_ifindex = ll_name_to_index(dev)) == 0) {
-		fprintf(stderr, "Cannot find device \"%s\"\n", dev);
-		return -1;
+	if (dev) {
+		req.ndm.ndm_ifindex = ll_name_to_index(dev);
+		if (!req.ndm.ndm_ifindex)
+			return nodev(dev);
 	}
 
+
 	if (rtnl_talk(&rth, &req.n, NULL) < 0)
 		exit(2);
 
@@ -423,10 +425,9 @@ static int do_show_or_flush(int argc, char **argv, int flush)
 	ll_init_map(&rth);
 
 	if (filter_dev) {
-		if ((filter.index = ll_name_to_index(filter_dev)) == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", filter_dev);
-			return -1;
-		}
+		filter.index = ll_name_to_index(filter_dev);
+		if (!filter.index)
+			return nodev(filter_dev);
 		addattr32(&req.n, sizeof(req), NDA_IFINDEX, filter.index);
 	}
 
diff --git a/ip/ipntable.c b/ip/ipntable.c
index 2f72c98..fbbf232 100644
--- a/ip/ipntable.c
+++ b/ip/ipntable.c
@@ -139,10 +139,8 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv)
 
 			NEXT_ARG();
 			ifindex = ll_name_to_index(*argv);
-			if (ifindex == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", *argv);
-				return -1;
-			}
+			if (!ifindex)
+				return nodev(*argv);
 
 			rta_addattr32(parms_rta, sizeof(parms_buf),
 				      NDTPA_IFINDEX, ifindex);
diff --git a/ip/iproute.c b/ip/iproute.c
index e4809a4..1d8fd81 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -973,10 +973,8 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
 		} else if (strcmp(*argv, "dev") == 0) {
 			NEXT_ARG();
 			rtnh->rtnh_ifindex = ll_name_to_index(*argv);
-			if (rtnh->rtnh_ifindex == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", *argv);
-				return -1;
-			}
+			if (!rtnh->rtnh_ifindex)
+				return nodev(*argv);
 		} else if (strcmp(*argv, "weight") == 0) {
 			unsigned int w;
 
@@ -1474,10 +1472,8 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
 	if (d) {
 		int idx = ll_name_to_index(d);
 
-		if (idx == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return -1;
-		}
+		if (!idx)
+			return nodev(d);
 		addattr32(&req.n, sizeof(req), RTA_OIF, idx);
 	}
 
@@ -1866,19 +1862,15 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 
 		if (id) {
 			idx = ll_name_to_index(id);
-			if (idx == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", id);
-				return -1;
-			}
+			if (!idx)
+				return nodev(id);
 			filter.iif = idx;
 			filter.iifmask = -1;
 		}
 		if (od) {
 			idx = ll_name_to_index(od);
-			if (idx == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", od);
-				return -1;
-			}
+			if (!idx)
+				return nodev(od);
 			filter.oif = idx;
 			filter.oifmask = -1;
 		}
@@ -2028,18 +2020,14 @@ static int iproute_get(int argc, char **argv)
 
 		if (idev) {
 			idx = ll_name_to_index(idev);
-			if (idx == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", idev);
-				return -1;
-			}
+			if (!idx)
+				return nodev(idev);
 			addattr32(&req.n, sizeof(req), RTA_IIF, idx);
 		}
 		if (odev) {
 			idx = ll_name_to_index(odev);
-			if (idx == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n", odev);
-				return -1;
-			}
+			if (!idx)
+				return nodev(odev);
 			addattr32(&req.n, sizeof(req), RTA_OIF, idx);
 		}
 	}
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index fa3feae..cde9b3d 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -594,7 +594,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
 				duparg2("iif", *argv);
 			iif = ll_name_to_index(*argv);
 			if (!iif)
-				invarg("\"iif\" interface not found\n", *argv);
+				exit(nodev(*argv));
 			rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif);
 		} else if (strcmp(*argv, "oif") == 0) {
 			NEXT_ARG();
@@ -602,7 +602,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
 				duparg2("oif", *argv);
 			oif = ll_name_to_index(*argv);
 			if (!oif)
-				invarg("\"oif\" interface not found\n", *argv);
+				exit(nodev(*argv));
 			rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
 		} else if (strcmp(*argv, "srh") == 0) {
 			NEXT_ARG();
diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index 1f04f95..d597908 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -213,10 +213,8 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
 
 	if (medium) {
 		p->link = ll_name_to_index(medium);
-		if (p->link == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", medium);
-			return -1;
-		}
+		if (!p->link)
+			return nodev(medium);
 	}
 
 	if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
diff --git a/ip/link_gre.c b/ip/link_gre.c
index 64588d7..bc1cee8 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -245,11 +245,8 @@ get_failed:
 		} else if (!matches(*argv, "dev")) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				exit(-1);
-			}
+			if (!link)
+				exit(nodev(*argv));
 		} else if (!matches(*argv, "ttl") ||
 			   !matches(*argv, "hoplimit") ||
 			   !matches(*argv, "hlim")) {
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
index 6c77038..83c61e2 100644
--- a/ip/link_gre6.c
+++ b/ip/link_gre6.c
@@ -250,11 +250,8 @@ get_failed:
 		} else if (!matches(*argv, "dev")) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				exit(-1);
-			}
+			if (!link)
+				exit(nodev(*argv));
 		} else if (!matches(*argv, "ttl") ||
 			   !matches(*argv, "hoplimit") ||
 			   !matches(*argv, "hlim")) {
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
index 77a9090..c7fef2e 100644
--- a/ip/link_ip6tnl.c
+++ b/ip/link_ip6tnl.c
@@ -197,8 +197,8 @@ get_failed:
 		} else if (matches(*argv, "dev") == 0) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0)
-				invarg("\"dev\" is invalid", *argv);
+			if (!link)
+				exit(nodev(*argv));
 		} else if (strcmp(*argv, "ttl") == 0 ||
 			   strcmp(*argv, "hoplimit") == 0 ||
 			   strcmp(*argv, "hlim") == 0) {
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
index acd9f45..57f4d0c 100644
--- a/ip/link_iptnl.c
+++ b/ip/link_iptnl.c
@@ -225,8 +225,8 @@ get_failed:
 		} else if (matches(*argv, "dev") == 0) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0)
-				invarg("\"dev\" is invalid", *argv);
+			if (!link)
+				exit(nodev(*argv));
 		} else if (strcmp(*argv, "ttl") == 0 ||
 			   strcmp(*argv, "hoplimit") == 0 ||
 			   strcmp(*argv, "hlim") == 0) {
diff --git a/ip/link_vti.c b/ip/link_vti.c
index 99e10e8..6196a1c 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -142,11 +142,8 @@ get_failed:
 		} else if (!matches(*argv, "dev")) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				exit(-1);
-			}
+			if (!link)
+				exit(nodev(*argv));
 		} else if (strcmp(*argv, "fwmark") == 0) {
 			NEXT_ARG();
 			if (get_u32(&fwmark, *argv, 0))
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
index 1df6579..4263615 100644
--- a/ip/link_vti6.c
+++ b/ip/link_vti6.c
@@ -144,11 +144,8 @@ get_failed:
 		} else if (!matches(*argv, "dev")) {
 			NEXT_ARG();
 			link = ll_name_to_index(*argv);
-			if (link == 0) {
-				fprintf(stderr, "Cannot find device \"%s\"\n",
-					*argv);
-				exit(-1);
-			}
+			if (!link)
+				exit(nodev(*argv));
 		} else if (strcmp(*argv, "fwmark") == 0) {
 			NEXT_ARG();
 			if (get_u32(&fwmark, *argv, 0))
diff --git a/lib/utils.c b/lib/utils.c
index 61af123..c0535a1 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -845,6 +845,12 @@ void duparg2(const char *key, const char *arg)
 	exit(-1);
 }
 
+int nodev(const char *dev)
+{
+	fprintf(stderr, "Cannot find device \"%s\"\n", dev);
+	return -1;
+}
+
 int check_ifname(const char *name)
 {
 	/* These checks mimic kernel checks in dev_valid_name */
diff --git a/tc/m_mirred.c b/tc/m_mirred.c
index eb42b7c..b25b9ac 100644
--- a/tc/m_mirred.c
+++ b/tc/m_mirred.c
@@ -193,10 +193,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
 		ll_init_map(&rth);
 
 		idx = ll_name_to_index(d);
-		if (idx == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return -1;
-		}
+		if (!idx)
+			return nodev(d);
 
 		p.ifindex = idx;
 	}
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 1b214b8..e1ca29c 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -142,10 +142,9 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)
 	if (d[0])  {
 		ll_init_map(&rth);
 
-		if ((req.t.tcm_ifindex = ll_name_to_index(d)) == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		req.t.tcm_ifindex = ll_name_to_index(d);
+		if (!req.t.tcm_ifindex)
+			return -nodev(d);
 	}
 
 	if (rtnl_talk(&rth, &req.n, NULL) < 0)
@@ -440,10 +439,9 @@ static int tc_class_list(int argc, char **argv)
 	ll_init_map(&rth);
 
 	if (d[0]) {
-		if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		t.tcm_ifindex = ll_name_to_index(d);
+		if (!t.tcm_ifindex)
+			return -nodev(d);
 		filter_ifindex = t.tcm_ifindex;
 	}
 
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 5c31a4c..f2313cd 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -198,10 +198,8 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv,
 		ll_init_map(&rth);
 
 		req->t.tcm_ifindex = ll_name_to_index(d);
-		if (req->t.tcm_ifindex == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		if (!req->t.tcm_ifindex)
+			return -nodev(d);
 	} else if (block_index) {
 		req->t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
 		req->t.tcm_block_index = block_index;
@@ -530,10 +528,8 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
 		ll_init_map(&rth);
 
 		req.t.tcm_ifindex = ll_name_to_index(d);
-		if (req.t.tcm_ifindex  == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		if (!req.t.tcm_ifindex)
+			return -nodev(d);
 		filter_ifindex = req.t.tcm_ifindex;
 	} else if (block_index) {
 		req.t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
@@ -696,10 +692,8 @@ static int tc_filter_list(int argc, char **argv)
 
 	if (d[0]) {
 		req.t.tcm_ifindex = ll_name_to_index(d);
-		if (req.t.tcm_ifindex == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		if (!req.t.tcm_ifindex)
+			return -nodev(d);
 		filter_ifindex = req.t.tcm_ifindex;
 	} else if (block_index) {
 		if (!tc_qdisc_block_exists(block_index)) {
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index 2fcf04c..e9a95a4 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -199,10 +199,8 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
 		ll_init_map(&rth);
 
 		idx = ll_name_to_index(d);
-		if (idx == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		if (!idx)
+			return -nodev(d);
 		req.t.tcm_ifindex = idx;
 	}
 
@@ -379,10 +377,8 @@ static int tc_qdisc_list(int argc, char **argv)
 
 	if (d[0]) {
 		t.tcm_ifindex = ll_name_to_index(d);
-		if (t.tcm_ifindex == 0) {
-			fprintf(stderr, "Cannot find device \"%s\"\n", d);
-			return 1;
-		}
+		if (!t.tcm_ifindex)
+			return -nodev(d);
 		filter_ifindex = t.tcm_ifindex;
 	}
 
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-21  5:15   ` David Ahern
  2018-02-20 21:37 ` [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

Distinguish cases when "dev" parameter isn't given from cases where no
network device corresponding to "dev" is found.

Do not check for index validity in xdp_parse(): caller should take care
of this because has more information (e.g. when "dev" is given or not
found) for this.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/iplink.c     |   16 +++++++++++++---
 ip/iplink_xdp.c |    7 +------
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index 5471626..fc358fc 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -569,6 +569,14 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
 	return 0;
 }
 
+static void has_dev(const char *dev, int dev_index)
+{
+	if (!dev)
+		missarg("dev");
+	if (!dev_index)
+		exit(nodev(dev));
+}
+
 int iplink_parse(int argc, char **argv, struct iplink_req *req,
 		 char **name, char **type, char **link, char **dev,
 		 int *group, int *index)
@@ -650,6 +658,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			bool drv = strcmp(*argv, "xdpdrv") == 0;
 			bool offload = strcmp(*argv, "xdpoffload") == 0;
 
+			if (offload)
+				has_dev(*dev, dev_index);
+
 			NEXT_ARG();
 			if (xdp_parse(&argc, &argv, req, dev_index,
 				      generic, drv, offload))
@@ -732,15 +743,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 		} else if (strcmp(*argv, "vf") == 0) {
 			struct rtattr *vflist;
 
+			has_dev(*dev, dev_index);
+
 			NEXT_ARG();
 			if (get_integer(&vf,  *argv, 0))
 				invarg("Invalid \"vf\" value\n", *argv);
 
 			vflist = addattr_nest(&req->n, sizeof(*req),
 					      IFLA_VFINFO_LIST);
-			if (dev_index == 0)
-				missarg("dev");
-
 			len = iplink_parse_vf(vf, &argc, &argv, req, dev_index);
 			if (len < 0)
 				return -1;
diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c
index 8382635..3df38b8 100644
--- a/ip/iplink_xdp.c
+++ b/ip/iplink_xdp.c
@@ -55,17 +55,12 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex,
 		.type = BPF_PROG_TYPE_XDP,
 		.argc = *argc,
 		.argv = *argv,
+		.ifindex = ifindex,
 	};
 	struct xdp_req xdp = {
 		.req = req,
 	};
 
-	if (offload) {
-		if (!ifindex)
-			incomplete_command();
-		cfg.ifindex = ifindex;
-	}
-
 	if (!force)
 		xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
 	if (generic)
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-20 23:04   ` Stephen Hemminger
  2018-02-20 21:37 ` [PATCH iproute2-next v2 4/7] iplink: Follow documented behaviour when "index" is given Serhey Popovych
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

Both of them accept network device name as argument, but have different
meaning:

  dev  - is a device by it's name,
  name - name for specific device device.

The only case where they treated separately is network device rename
case where need to specify both ifindex and new name. In rest of the
cases we can assume that dev == name.

With this change we do following:

  1) Kill ambiguity with both "dev" and "name" parameters given the same
     name:

       ip link {add|set} dev veth100a name veth100a ...

  2) Make sure we do not accept "name" more than once.

  3) For VF and XDP treat "name" as "dev". Fail in case of "dev" is
     given after VF and/or XDP parsing.

  4) Make veth and vxcan to accept both "name" and "dev" as their peer
     parameters, effectively following general ip-link(8) utility
     behaviour on link create:

       ip link add {name|dev} veth1a type veth peer {name|dev} veth1b

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/iplink.c |   34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index fc358fc..1359c0f 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -605,9 +605,15 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			req->i.ifi_flags &= ~IFF_UP;
 		} else if (strcmp(*argv, "name") == 0) {
 			NEXT_ARG();
+			if (*name)
+				duparg("name", *argv);
 			if (check_ifname(*argv))
 				invarg("\"name\" not a valid ifname", *argv);
 			*name = *argv;
+			if (!*dev) {
+				*dev = *name;
+				dev_index = ll_name_to_index(*dev);
+			}
 		} else if (strcmp(*argv, "index") == 0) {
 			NEXT_ARG();
 			if (*index)
@@ -665,6 +671,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			if (xdp_parse(&argc, &argv, req, dev_index,
 				      generic, drv, offload))
 				exit(-1);
+
+			if (offload && *name == *dev)
+				*dev = NULL;
 		} else if (strcmp(*argv, "netns") == 0) {
 			NEXT_ARG();
 			if (netns != -1)
@@ -755,6 +764,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			if (len < 0)
 				return -1;
 			addattr_nest_end(&req->n, vflist);
+
+			if (*name == *dev)
+				*dev = NULL;
 		} else if (matches(*argv, "master") == 0) {
 			int ifindex;
 
@@ -905,7 +917,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 
 			if (strcmp(*argv, "dev") == 0)
 				NEXT_ARG();
-			if (*dev)
+			if (*dev != *name)
 				duparg2("dev", *argv);
 			if (check_ifname(*argv))
 				invarg("\"dev\" not a valid ifname", *argv);
@@ -915,6 +927,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 		argc--; argv++;
 	}
 
+	/* Allow "ip link add dev" and "ip link add name" */
+	if (!*name)
+		*name = *dev;
+	else if (!*dev)
+		*dev = *name;
+	else if (!strcmp(*name, *dev))
+		*name = *dev;
+
 	if (dev_index && addr_len) {
 		int halen = nl_get_ll_addr_len(dev_index);
 
@@ -993,10 +1013,16 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 		req.i.ifi_index = ll_name_to_index(dev);
 		if (!req.i.ifi_index)
 			return nodev(dev);
+
+		/* Not renaming to the same name */
+		if (name == dev)
+			name = NULL;
 	} else {
-		/* Allow "ip link add dev" and "ip link add name" */
-		if (!name)
-			name = dev;
+		if (name != dev) {
+			fprintf(stderr,
+				"both \"name\" and \"dev\" cannot be used when creating devices.\n");
+			exit(-1);
+		}
 
 		if (link) {
 			int ifindex;
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 4/7] iplink: Follow documented behaviour when "index" is given
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
                   ` (2 preceding siblings ...)
  2018-02-20 21:37 ` [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 5/7] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

Both ip-link(8) and error message when "index" parameter is given for
set/delete case says that index can only be given during network
device creation.

Follow this documented behaviour and get rid of ambiguous behaviour in
case of both "dev" and "index" specified for ip link delete scenario
(actually "index" being ignored in favor to "dev").

Prohibit "index" when configuring/deleting group of network devices.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/iplink.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/ip/iplink.c b/ip/iplink.c
index 1359c0f..4e9f571 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -974,6 +974,12 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 	argc -= ret;
 	argv += ret;
 
+	if (!(flags & NLM_F_CREATE) && index) {
+		fprintf(stderr,
+			"index can be used only when creating devices.\n");
+		exit(-1);
+	}
+
 	if (group != -1) {
 		if (dev)
 			addattr_l(&req.n, sizeof(req), IFLA_GROUP,
@@ -1004,11 +1010,6 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 				"Not enough information: \"dev\" argument is required.\n");
 			exit(-1);
 		}
-		if (cmd == RTM_NEWLINK && index) {
-			fprintf(stderr,
-				"index can be used only when creating devices.\n");
-			exit(-1);
-		}
 
 		req.i.ifi_index = ll_name_to_index(dev);
 		if (!req.i.ifi_index)
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 5/7] iplink: Perform most of request buffer setups and checks in iplink_parse()
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
                   ` (3 preceding siblings ...)
  2018-02-20 21:37 ` [PATCH iproute2-next v2 4/7] iplink: Follow documented behaviour when "index" is given Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 6/7] iplink: Move data structures to block of their users Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 7/7] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
  6 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

To benefit other users (e.g. link_veth.c) of iplink_parse() from
additional attribute checks and setups made in iplink_modify().

This catches most of weired cobination of parameters to peer device
configuration in iplink_vxcan.c and link_veth.c. Use memcpy() to save
peer device @ifm data structure as now ->ifi_index is set inside
iplist_parse(): it will be inlined by the compiler anyway.

Drop @link, @group and @index from iplink_parse() parameters list: they
are not needed outside.

While there change return -1 to exit(-1) for group parsing errors: we
want to stop further command processing unless -force option is given
to get error line easily.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/ip_common.h    |    3 +-
 ip/iplink.c       |  118 +++++++++++++++++++++++++----------------------------
 ip/iplink_vxcan.c |   27 +++---------
 ip/link_veth.c    |   27 +++---------
 4 files changed, 69 insertions(+), 106 deletions(-)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index e4e628b..f762821 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -133,8 +133,7 @@ struct link_util {
 struct link_util *get_link_kind(const char *kind);
 
 int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **link, char **dev,
-		 int *group, int *index);
+		 char **name, char **type, char **dev);
 
 /* iplink_bridge.c */
 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
diff --git a/ip/iplink.c b/ip/iplink.c
index 4e9f571..e53d890 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -578,9 +578,9 @@ static void has_dev(const char *dev, int dev_index)
 }
 
 int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **link, char **dev,
-		 int *group, int *index)
+		 char **name, char **type, char **dev)
 {
+	char *link = NULL;
 	int ret, len;
 	char abuf[32];
 	int qlen = -1;
@@ -591,9 +591,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 	int numrxqueues = -1;
 	int dev_index = 0;
 	int link_netnsid = -1;
+	int index = 0;
+	int group = -1;
 	int addr_len = 0;
 
-	*group = -1;
 	ret = argc;
 
 	while (argc > 0) {
@@ -616,14 +617,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 			}
 		} else if (strcmp(*argv, "index") == 0) {
 			NEXT_ARG();
-			if (*index)
+			if (index)
 				duparg("index", *argv);
-			*index = atoi(*argv);
-			if (*index <= 0)
+			index = atoi(*argv);
+			if (index <= 0)
 				invarg("Invalid \"index\" value", *argv);
 		} else if (matches(*argv, "link") == 0) {
 			NEXT_ARG();
-			*link = *argv;
+			link = *argv;
 		} else if (matches(*argv, "address") == 0) {
 			NEXT_ARG();
 			addr_len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
@@ -816,10 +817,11 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 				  *argv, len);
 		} else if (strcmp(*argv, "group") == 0) {
 			NEXT_ARG();
-			if (*group != -1)
+			if (group != -1)
 				duparg("group", *argv);
-			if (rtnl_group_a2n(group, *argv))
+			if (rtnl_group_a2n(&group, *argv))
 				invarg("Invalid \"group\" value\n", *argv);
+			addattr32(&req->n, sizeof(*req), IFLA_GROUP, group);
 		} else if (strcmp(*argv, "mode") == 0) {
 			int mode;
 
@@ -946,80 +948,47 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 		}
 	}
 
-	return ret - argc;
-}
-
-static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
-{
-	char *dev = NULL;
-	char *name = NULL;
-	char *link = NULL;
-	char *type = NULL;
-	int index = 0;
-	int group;
-	struct link_util *lu = NULL;
-	struct iplink_req req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-		.n.nlmsg_flags = NLM_F_REQUEST | flags,
-		.n.nlmsg_type = cmd,
-		.i.ifi_family = preferred_family,
-	};
-	int ret;
-
-	ret = iplink_parse(argc, argv,
-			   &req, &name, &type, &link, &dev, &group, &index);
-	if (ret < 0)
-		return ret;
-
-	argc -= ret;
-	argv += ret;
-
-	if (!(flags & NLM_F_CREATE) && index) {
+	if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) {
 		fprintf(stderr,
 			"index can be used only when creating devices.\n");
 		exit(-1);
 	}
 
 	if (group != -1) {
-		if (dev)
-			addattr_l(&req.n, sizeof(req), IFLA_GROUP,
-					&group, sizeof(group));
-		else {
+		if (!*dev) {
 			if (argc) {
 				fprintf(stderr,
 					"Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
 					*argv);
-				return -1;
+				exit(-1);
 			}
-			if (flags & NLM_F_CREATE) {
+			if (req->n.nlmsg_flags & NLM_F_CREATE) {
 				fprintf(stderr,
 					"group cannot be used when creating devices.\n");
-				return -1;
+				exit(-1);
 			}
 
-			addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
-			if (rtnl_talk(&rth, &req.n, NULL) < 0)
-				return -2;
-			return 0;
+			*type = NULL;
+			goto out;
 		}
 	}
 
-	if (!(flags & NLM_F_CREATE)) {
-		if (!dev) {
+	if (!(req->n.nlmsg_flags & NLM_F_CREATE)) {
+		if (!*dev) {
 			fprintf(stderr,
 				"Not enough information: \"dev\" argument is required.\n");
 			exit(-1);
 		}
 
-		req.i.ifi_index = ll_name_to_index(dev);
-		if (!req.i.ifi_index)
-			return nodev(dev);
+		req->i.ifi_index = ll_name_to_index(*dev);
+		if (!req->i.ifi_index)
+			return nodev(*dev);
 
 		/* Not renaming to the same name */
-		if (name == dev)
-			name = NULL;
+		if (*name == *dev)
+			*name = NULL;
 	} else {
-		if (name != dev) {
+		if (*name != *dev) {
 			fprintf(stderr,
 				"both \"name\" and \"dev\" cannot be used when creating devices.\n");
 			exit(-1);
@@ -1031,18 +1000,39 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 			ifindex = ll_name_to_index(link);
 			if (!ifindex)
 				return nodev(link);
-			addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4);
+			addattr32(&req->n, sizeof(*req), IFLA_LINK, ifindex);
 		}
 
-		req.i.ifi_index = index;
+		req->i.ifi_index = index;
 	}
 
-	if (name) {
-		addattr_l(&req.n, sizeof(req),
-			  IFLA_IFNAME, name, strlen(name) + 1);
+	if (*name) {
+		addattr_l(&req->n, sizeof(*req),
+			  IFLA_IFNAME, *name, strlen(*name) + 1);
 	}
+out:
+	return ret - argc;
+}
+
+static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
+{
+	char *dev = NULL;
+	char *name = NULL;
+	char *type = NULL;
+	struct iplink_req req = {
+		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+		.n.nlmsg_flags = NLM_F_REQUEST | flags,
+		.n.nlmsg_type = cmd,
+		.i.ifi_family = preferred_family,
+	};
+	int ret;
+
+	ret = iplink_parse(argc, argv, &req, &name, &type, &dev);
+	if (ret < 0)
+		return ret;
 
 	if (type) {
+		struct link_util *lu;
 		struct rtattr *linkinfo;
 		char *ulinep = strchr(type, '_');
 		int iflatype;
@@ -1056,6 +1046,10 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 			iflatype = IFLA_INFO_SLAVE_DATA;
 		else
 			iflatype = IFLA_INFO_DATA;
+
+		argc -= ret;
+		argv += ret;
+
 		if (lu && argc) {
 			struct rtattr *data;
 
diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
index ebe9e56..43c80e7 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -35,14 +35,10 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 {
 	char *dev = NULL;
 	char *name = NULL;
-	char *link = NULL;
 	char *type = NULL;
-	int index = 0;
 	int err;
 	struct rtattr *data;
-	int group;
-	struct ifinfomsg *ifm, *peer_ifm;
-	unsigned int ifi_flags, ifi_change;
+	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
 
 	if (strcmp(argv[0], "peer") != 0) {
 		usage();
@@ -50,8 +46,8 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 	}
 
 	ifm = NLMSG_DATA(n);
-	ifi_flags = ifm->ifi_flags;
-	ifi_change = ifm->ifi_change;
+	memcpy(&ifm_save, ifm, sizeof(*ifm));
+	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
 	ifm->ifi_change = 0;
 
@@ -60,27 +56,16 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
 	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &link, &dev, &group, &index);
+			   &name, &type, &dev);
 	if (err < 0)
 		return err;
 
 	if (type)
 		duparg("type", argv[err]);
 
-	if (name) {
-		addattr_l(n, 1024,
-			  IFLA_IFNAME, name, strlen(name) + 1);
-	}
-
 	peer_ifm = RTA_DATA(data);
-	peer_ifm->ifi_index = index;
-	peer_ifm->ifi_flags = ifm->ifi_flags;
-	peer_ifm->ifi_change = ifm->ifi_change;
-	ifm->ifi_flags = ifi_flags;
-	ifm->ifi_change = ifi_change;
-
-	if (group != -1)
-		addattr32(n, 1024, IFLA_GROUP, group);
+	memcpy(peer_ifm, ifm, sizeof(*ifm));
+	memcpy(ifm, &ifm_save, sizeof(*ifm));
 
 	addattr_nest_end(n, data);
 	return argc - 1 - err;
diff --git a/ip/link_veth.c b/ip/link_veth.c
index a8e7cf7..bd8f36e 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -33,14 +33,10 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 {
 	char *dev = NULL;
 	char *name = NULL;
-	char *link = NULL;
 	char *type = NULL;
-	int index = 0;
 	int err;
 	struct rtattr *data;
-	int group;
-	struct ifinfomsg *ifm, *peer_ifm;
-	unsigned int ifi_flags, ifi_change;
+	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
 
 	if (strcmp(argv[0], "peer") != 0) {
 		usage();
@@ -48,8 +44,8 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 	}
 
 	ifm = NLMSG_DATA(n);
-	ifi_flags = ifm->ifi_flags;
-	ifi_change = ifm->ifi_change;
+	memcpy(&ifm_save, ifm, sizeof(*ifm));
+	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
 	ifm->ifi_change = 0;
 
@@ -58,27 +54,16 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
 	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &link, &dev, &group, &index);
+			   &name, &type, &dev);
 	if (err < 0)
 		return err;
 
 	if (type)
 		duparg("type", argv[err]);
 
-	if (name) {
-		addattr_l(n, 1024,
-			  IFLA_IFNAME, name, strlen(name) + 1);
-	}
-
 	peer_ifm = RTA_DATA(data);
-	peer_ifm->ifi_index = index;
-	peer_ifm->ifi_flags = ifm->ifi_flags;
-	peer_ifm->ifi_change = ifm->ifi_change;
-	ifm->ifi_flags = ifi_flags;
-	ifm->ifi_change = ifi_change;
-
-	if (group != -1)
-		addattr32(n, 1024, IFLA_GROUP, group);
+	memcpy(peer_ifm, ifm, sizeof(*ifm));
+	memcpy(ifm, &ifm_save, sizeof(*ifm));
 
 	addattr_nest_end(n, data);
 	return argc - 1 - err;
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 6/7] iplink: Move data structures to block of their users
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
                   ` (4 preceding siblings ...)
  2018-02-20 21:37 ` [PATCH iproute2-next v2 5/7] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  2018-02-20 21:37 ` [PATCH iproute2-next v2 7/7] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
  6 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

This will consolidate data and code using it in single place and prepare
for upcoming ->parse_opt() method change.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/link_gre.c    |   32 ++++++++++++++++----------------
 ip/link_gre6.c   |   32 ++++++++++++++++----------------
 ip/link_ip6tnl.c |   32 ++++++++++++++++----------------
 ip/link_iptnl.c  |   32 ++++++++++++++++----------------
 ip/link_vti.c    |   32 ++++++++++++++++----------------
 ip/link_vti6.c   |   32 ++++++++++++++++----------------
 6 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/ip/link_gre.c b/ip/link_gre.c
index bc1cee8..6654525 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -66,22 +66,6 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 			 struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
-	int len;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -107,7 +91,23 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *greinfo[IFLA_GRE_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
index 83c61e2..a92854d 100644
--- a/ip/link_gre6.c
+++ b/ip/link_gre6.c
@@ -77,22 +77,6 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 			 struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
-	int len;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -118,7 +102,23 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *greinfo[IFLA_GRE_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
index c7fef2e..edd7632 100644
--- a/ip/link_ip6tnl.c
+++ b/ip/link_ip6tnl.c
@@ -77,22 +77,6 @@ static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv,
 static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 			       struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
-	int len;
 	inet_prefix saddr, daddr;
 	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
 	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
@@ -111,7 +95,23 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
index 57f4d0c..0dc0db0 100644
--- a/ip/link_iptnl.c
+++ b/ip/link_iptnl.c
@@ -74,22 +74,6 @@ static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
 static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 			      struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
-	int len;
 	inet_prefix saddr, daddr, ip6rdprefix, ip6rdrelayprefix;
 	__u8 pmtudisc = 1;
 	__u8 tos = 0;
@@ -111,7 +95,23 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&ip6rdrelayprefix);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
diff --git a/ip/link_vti.c b/ip/link_vti.c
index 6196a1c..47c3b7f 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -47,33 +47,33 @@ static void vti_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
 			 struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
 	unsigned int link = 0;
 	__u32 fwmark = 0;
-	int len;
 
 	inet_prefix_reset(&saddr);
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
index 4263615..48c67b0 100644
--- a/ip/link_vti6.c
+++ b/ip/link_vti6.c
@@ -49,33 +49,33 @@ static void vti6_print_help(struct link_util *lu, int argc, char **argv,
 static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
 			  struct nlmsghdr *n)
 {
-	struct ifinfomsg *ifi = NLMSG_DATA(n);
-	struct {
-		struct nlmsghdr n;
-		struct ifinfomsg i;
-	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
-		.n.nlmsg_flags = NLM_F_REQUEST,
-		.n.nlmsg_type = RTM_GETLINK,
-		.i.ifi_family = preferred_family,
-		.i.ifi_index = ifi->ifi_index,
-	};
-	struct nlmsghdr *answer;
-	struct rtattr *tb[IFLA_MAX + 1];
-	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
-	struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
 	unsigned int link = 0;
 	__u32 fwmark = 0;
-	int len;
 
 	inet_prefix_reset(&saddr);
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct {
+			struct nlmsghdr n;
+			struct ifinfomsg i;
+		} req = {
+			.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
+			.n.nlmsg_flags = NLM_F_REQUEST,
+			.n.nlmsg_type = RTM_GETLINK,
+			.i.ifi_family = preferred_family,
+			.i.ifi_index = ifi->ifi_index,
+		};
+		struct nlmsghdr *answer;
+		struct rtattr *tb[IFLA_MAX + 1];
+		struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+		struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
 		const struct rtattr *rta;
+		int len;
 
 		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
-- 
1.7.10.4

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

* [PATCH iproute2-next v2 7/7] iplink: Reduce number of arguments to iplink_parse()
  2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
                   ` (5 preceding siblings ...)
  2018-02-20 21:37 ` [PATCH iproute2-next v2 6/7] iplink: Move data structures to block of their users Serhey Popovych
@ 2018-02-20 21:37 ` Serhey Popovych
  6 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-20 21:37 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

Introduce new @struct iplink_parse_args data structure to consolidate
arguments to iplink_parse(). This will reduce number of arguments
passed to it.

Pass this data structure to ->parse_opt() in iplink specific modules:
it may be used to get network device name and other information.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/ip_common.h           |   16 +++++++++++++---
 ip/iplink.c              |   34 ++++++++++++++++++++++------------
 ip/iplink_bond.c         |    4 +++-
 ip/iplink_bond_slave.c   |    4 +++-
 ip/iplink_bridge.c       |    4 +++-
 ip/iplink_bridge_slave.c |    4 +++-
 ip/iplink_can.c          |    4 +++-
 ip/iplink_geneve.c       |    4 +++-
 ip/iplink_hsr.c          |    4 +++-
 ip/iplink_ipoib.c        |    4 +++-
 ip/iplink_ipvlan.c       |    4 +++-
 ip/iplink_macvlan.c      |    4 +++-
 ip/iplink_vlan.c         |    4 +++-
 ip/iplink_vrf.c          |    5 ++++-
 ip/iplink_vxcan.c        |   14 ++++++--------
 ip/iplink_vxlan.c        |    4 +++-
 ip/ipmacsec.c            |    4 +++-
 ip/link_gre.c            |    6 ++++--
 ip/link_gre6.c           |    6 ++++--
 ip/link_ip6tnl.c         |    6 ++++--
 ip/link_iptnl.c          |    6 ++++--
 ip/link_veth.c           |   14 ++++++--------
 ip/link_vti.c            |    6 ++++--
 ip/link_vti6.c           |    6 ++++--
 24 files changed, 114 insertions(+), 57 deletions(-)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index f762821..aef70de 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -112,12 +112,23 @@ struct iplink_req {
 	char			buf[1024];
 };
 
+struct iplink_parse_args {
+	const char *dev;
+	const char *name;
+	const char *type;
+
+	/* This definitely must be the last one and initialized
+	 * by the caller of iplink_parse() that will initialize rest.
+	 */
+	struct iplink_req *req;
+};
+
 struct link_util {
 	struct link_util	*next;
 	const char		*id;
 	int			maxattr;
 	int			(*parse_opt)(struct link_util *, int, char **,
-					     struct nlmsghdr *);
+					     struct iplink_parse_args *);
 	void			(*print_opt)(struct link_util *, FILE *,
 					     struct rtattr *[]);
 	void			(*print_xstats)(struct link_util *, FILE *,
@@ -132,8 +143,7 @@ struct link_util {
 
 struct link_util *get_link_kind(const char *kind);
 
-int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **dev);
+int iplink_parse(int argc, char **argv, struct iplink_parse_args *pa);
 
 /* iplink_bridge.c */
 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
diff --git a/ip/iplink.c b/ip/iplink.c
index e53d890..837e2b0 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -10,6 +10,7 @@
  *
  */
 
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -577,9 +578,12 @@ static void has_dev(const char *dev, int dev_index)
 		exit(nodev(dev));
 }
 
-int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **dev)
+int iplink_parse(int argc, char **argv, struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	const char **dev = &pa->dev;
+	const char **name = &pa->name;
+	const char **type = &pa->type;
 	char *link = NULL;
 	int ret, len;
 	char abuf[32];
@@ -597,6 +601,8 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
 
 	ret = argc;
 
+	memset(pa, 0, offsetof(struct iplink_parse_args, req));
+
 	while (argc > 0) {
 		if (strcmp(*argv, "up") == 0) {
 			req->i.ifi_change |= IFF_UP;
@@ -1016,32 +1022,32 @@ out:
 
 static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
 	struct iplink_req req = {
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 		.n.nlmsg_flags = NLM_F_REQUEST | flags,
 		.n.nlmsg_type = cmd,
 		.i.ifi_family = preferred_family,
 	};
+	struct iplink_parse_args pa;
 	int ret;
 
-	ret = iplink_parse(argc, argv, &req, &name, &type, &dev);
+	pa.req = &req;
+
+	ret = iplink_parse(argc, argv, &pa);
 	if (ret < 0)
 		return ret;
 
-	if (type) {
+	if (pa.type) {
 		struct link_util *lu;
 		struct rtattr *linkinfo;
-		char *ulinep = strchr(type, '_');
+		char *ulinep = strchr(pa.type, '_');
 		int iflatype;
 
 		linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
-		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
-			 strlen(type));
+		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, pa.type,
+			  strlen(pa.type));
 
-		lu = get_link_kind(type);
+		lu = get_link_kind(pa.type);
 		if (ulinep && !strcmp(ulinep, "_slave"))
 			iflatype = IFLA_INFO_SLAVE_DATA;
 		else
@@ -1056,9 +1062,13 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 			data = addattr_nest(&req.n, sizeof(req), iflatype);
 
 			if (lu->parse_opt &&
-			    lu->parse_opt(lu, argc, argv, &req.n))
+			    lu->parse_opt(lu, argc, argv, &pa))
 				return -1;
 
+			/* Must not assume that anything except pa.req is valid
+			 * after calling ->parse_opt() as one might reuse pa
+			 * with iplink_parse(). See link_veth.c as an example.
+			 */
 			addattr_nest_end(&req.n, data);
 		} else if (argc) {
 			if (matches(*argv, "help") == 0)
diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c
index f906e7f..bf03a6e 100644
--- a/ip/iplink_bond.c
+++ b/ip/iplink_bond.c
@@ -157,8 +157,10 @@ static void explain(void)
 }
 
 static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u8 mode, use_carrier, primary_reselect, fail_over_mac;
 	__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
 	__u8 lacp_rate, ad_select, tlb_dynamic_lb;
diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c
index 67219c6..d7e2a1e 100644
--- a/ip/iplink_bond_slave.c
+++ b/ip/iplink_bond_slave.c
@@ -120,8 +120,10 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t
 }
 
 static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
-				struct nlmsghdr *n)
+				struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 queue_id;
 
 	while (argc > 0) {
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 3008e44..9a8560a 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -80,8 +80,10 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
 }
 
 static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u32 val;
 
 	while (argc > 0) {
diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c
index 3fbfb87..31fde1c 100644
--- a/ip/iplink_bridge_slave.c
+++ b/ip/iplink_bridge_slave.c
@@ -292,8 +292,10 @@ static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
 }
 
 static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
-				  struct nlmsghdr *n)
+				  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u8 state;
 	__u16 priority;
 	__u32 cost;
diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index 587413d..36ef917 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -110,8 +110,10 @@ static void print_ctrlmode(FILE *f, __u32 cm)
 }
 
 static int can_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	struct can_bittiming bt = {}, dbt = {};
 	struct can_ctrlmode cm = {0, 0};
 
diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c
index 1fcdd83..4b2bf29 100644
--- a/ip/iplink_geneve.c
+++ b/ip/iplink_geneve.c
@@ -55,8 +55,10 @@ static void check_duparg(__u64 *attrs, int type, const char *key,
 }
 
 static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix daddr;
 	__u32 vni = 0;
 	__u32 label = 0;
diff --git a/ip/iplink_hsr.c b/ip/iplink_hsr.c
index c673ccf..d020676 100644
--- a/ip/iplink_hsr.c
+++ b/ip/iplink_hsr.c
@@ -44,8 +44,10 @@ static void usage(void)
 }
 
 static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int ifindex;
 	unsigned char multicast_spec;
 	unsigned char protocol_version;
diff --git a/ip/iplink_ipoib.c b/ip/iplink_ipoib.c
index e69bda0..f95c79c 100644
--- a/ip/iplink_ipoib.c
+++ b/ip/iplink_ipoib.c
@@ -42,8 +42,10 @@ static int mode_arg(void)
 }
 
 static int ipoib_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 pkey, mode, umcast;
 
 	while (argc > 0) {
diff --git a/ip/iplink_ipvlan.c b/ip/iplink_ipvlan.c
index 8889808..2b8a3cc 100644
--- a/ip/iplink_ipvlan.c
+++ b/ip/iplink_ipvlan.c
@@ -30,8 +30,10 @@ static void ipvlan_explain(FILE *f)
 }
 
 static int ipvlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 flags = 0;
 	bool mflag_given = false;
 
diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c
index b966a61..6f97415 100644
--- a/ip/iplink_macvlan.c
+++ b/ip/iplink_macvlan.c
@@ -63,8 +63,10 @@ static int flag_arg(const char *arg)
 }
 
 static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			     struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u32 mode = 0;
 	__u16 flags = 0;
 	__u32 mac_mode = 0;
diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c
index 74f4614..6c0c12d 100644
--- a/ip/iplink_vlan.c
+++ b/ip/iplink_vlan.c
@@ -82,8 +82,10 @@ static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n,
 }
 
 static int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	struct ifla_vlan_flags flags = { 0 };
 	__u16 id, proto;
 
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index e9dd0df..b943ed9 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -30,8 +30,11 @@ static void explain(void)
 }
 
 static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
+
 	while (argc > 0) {
 		if (matches(*argv, "table") == 0) {
 			__u32 table;
diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
index 43c80e7..a234e34 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -31,11 +31,10 @@ static void usage(void)
 }
 
 static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -45,7 +44,7 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 		return -1;
 	}
 
-	ifm = NLMSG_DATA(n);
+	ifm = &req->i;
 	memcpy(&ifm_save, ifm, sizeof(*ifm));
 	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
@@ -55,12 +54,11 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
-	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &dev);
+	err = iplink_parse(argc - 1, argv + 1, pa);
 	if (err < 0)
 		return err;
 
-	if (type)
+	if (pa->type)
 		duparg("type", argv[err]);
 
 	peer_ifm = RTA_DATA(data);
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index be9f35e..f76a2c4 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -72,8 +72,10 @@ static void check_duparg(__u64 *attrs, int type, const char *key,
 }
 
 static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr;
 	__u32 vni = 0;
 	__u8 learning = 1;
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
index c0b45f5..144141f 100644
--- a/ip/ipmacsec.c
+++ b/ip/ipmacsec.c
@@ -1132,8 +1132,10 @@ static void usage(FILE *f)
 }
 
 static int macsec_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int ret;
 	__u8 encoding_sa = 0xff;
 	__u32 window = -1;
diff --git a/ip/link_gre.c b/ip/link_gre.c
index 6654525..f7b194f 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -64,8 +64,10 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -91,7 +93,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
index a92854d..fb3e259 100644
--- a/ip/link_gre6.c
+++ b/ip/link_gre6.c
@@ -75,8 +75,10 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -102,7 +104,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
index edd7632..6d9361c 100644
--- a/ip/link_ip6tnl.c
+++ b/ip/link_ip6tnl.c
@@ -75,8 +75,10 @@ static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
-			       struct nlmsghdr *n)
+			       struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr;
 	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
 	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
@@ -95,7 +97,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
index 0dc0db0..6df4dca 100644
--- a/ip/link_iptnl.c
+++ b/ip/link_iptnl.c
@@ -72,8 +72,10 @@ static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
-			      struct nlmsghdr *n)
+			      struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr, ip6rdprefix, ip6rdrelayprefix;
 	__u8 pmtudisc = 1;
 	__u8 tos = 0;
@@ -95,7 +97,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&ip6rdrelayprefix);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_veth.c b/ip/link_veth.c
index bd8f36e..00d5cf7 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -29,11 +29,10 @@ static void usage(void)
 }
 
 static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -43,7 +42,7 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 		return -1;
 	}
 
-	ifm = NLMSG_DATA(n);
+	ifm = &req->i;
 	memcpy(&ifm_save, ifm, sizeof(*ifm));
 	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
@@ -53,12 +52,11 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
-	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &dev);
+	err = iplink_parse(argc - 1, argv + 1, pa);
 	if (err < 0)
 		return err;
 
-	if (type)
+	if (pa->type)
 		duparg("type", argv[err]);
 
 	peer_ifm = RTA_DATA(data);
diff --git a/ip/link_vti.c b/ip/link_vti.c
index 47c3b7f..10508e6 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -45,8 +45,10 @@ static void vti_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
@@ -57,7 +59,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
index 48c67b0..91c8521 100644
--- a/ip/link_vti6.c
+++ b/ip/link_vti6.c
@@ -47,8 +47,10 @@ static void vti6_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
@@ -59,7 +61,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
-- 
1.7.10.4

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

* Re: [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible
  2018-02-20 21:37 ` [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
@ 2018-02-20 23:04   ` Stephen Hemminger
  2018-02-21  6:35     ` Serhey Popovych
  0 siblings, 1 reply; 13+ messages in thread
From: Stephen Hemminger @ 2018-02-20 23:04 UTC (permalink / raw)
  To: Serhey Popovych; +Cc: netdev, dsahern

On Tue, 20 Feb 2018 23:37:25 +0200
Serhey Popovych <serhe.popovych@gmail.com> wrote:

> Both of them accept network device name as argument, but have different
> meaning:
> 
>   dev  - is a device by it's name,
>   name - name for specific device device.
> 
> The only case where they treated separately is network device rename
> case where need to specify both ifindex and new name. In rest of the
> cases we can assume that dev == name.

I would rather keep name as only being a valid argument for set command.
And reject use of:

   ip li show name eth0

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

* Re: [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine
  2018-02-20 21:37 ` [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine Serhey Popovych
@ 2018-02-21  5:13   ` David Ahern
  0 siblings, 0 replies; 13+ messages in thread
From: David Ahern @ 2018-02-21  5:13 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/20/18 2:37 PM, Serhey Popovych wrote:

> diff --git a/ip/ipneigh.c b/ip/ipneigh.c
> index 0735424..9c9cd23 100644
> --- a/ip/ipneigh.c
> +++ b/ip/ipneigh.c
> @@ -178,11 +178,13 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
>  
>  	ll_init_map(&rth);
>  
> -	if (dev && (req.ndm.ndm_ifindex = ll_name_to_index(dev)) == 0) {
> -		fprintf(stderr, "Cannot find device \"%s\"\n", dev);
> -		return -1;
> +	if (dev) {
> +		req.ndm.ndm_ifindex = ll_name_to_index(dev);
> +		if (!req.ndm.ndm_ifindex)
> +			return nodev(dev);
>  	}
>  
> +
>  	if (rtnl_talk(&rth, &req.n, NULL) < 0)
>  		exit(2);
>  

Remove the extra newline

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

* Re: [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found
  2018-02-20 21:37 ` [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found Serhey Popovych
@ 2018-02-21  5:15   ` David Ahern
  2018-02-21  7:14     ` Serhey Popovych
  0 siblings, 1 reply; 13+ messages in thread
From: David Ahern @ 2018-02-21  5:15 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/20/18 2:37 PM, Serhey Popovych wrote:
> Distinguish cases when "dev" parameter isn't given from cases where no
> network device corresponding to "dev" is found.
> 
> Do not check for index validity in xdp_parse(): caller should take care
> of this because has more information (e.g. when "dev" is given or not
> found) for this.
> 
> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
> ---
>  ip/iplink.c     |   16 +++++++++++++---
>  ip/iplink_xdp.c |    7 +------
>  2 files changed, 14 insertions(+), 9 deletions(-)
> 

don't really see any benefit from this one.

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

* Re: [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible
  2018-02-20 23:04   ` Stephen Hemminger
@ 2018-02-21  6:35     ` Serhey Popovych
  0 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-21  6:35 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, dsahern


[-- Attachment #1.1: Type: text/plain, Size: 998 bytes --]

Stephen Hemminger wrote:
> On Tue, 20 Feb 2018 23:37:25 +0200
> Serhey Popovych <serhe.popovych@gmail.com> wrote:
> 
>> Both of them accept network device name as argument, but have different
>> meaning:
>>
>>   dev  - is a device by it's name,
>>   name - name for specific device device.
>>
>> The only case where they treated separately is network device rename
>> case where need to specify both ifindex and new name. In rest of the
>> cases we can assume that dev == name.
> 
> I would rather keep name as only being a valid argument for set command.
> And reject use of:
> 
>    ip li show name eth0
> 

But ip-link(8) man page is full of examples where "name" is used instead
of "dev". I suppose there are lot of configuration we can broke when
explicitly disabling "name" as an alternative to "dev".

Especially on the first lines in man page we have:

ip link add [ link DEVICE ] [ name ] NAME
...

and there is no reference to "dev".

What do you think?


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

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

* Re: [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found
  2018-02-21  5:15   ` David Ahern
@ 2018-02-21  7:14     ` Serhey Popovych
  0 siblings, 0 replies; 13+ messages in thread
From: Serhey Popovych @ 2018-02-21  7:14 UTC (permalink / raw)
  To: David Ahern, netdev


[-- Attachment #1.1: Type: text/plain, Size: 1010 bytes --]

David Ahern wrote:
> On 2/20/18 2:37 PM, Serhey Popovych wrote:
>> Distinguish cases when "dev" parameter isn't given from cases where no
>> network device corresponding to "dev" is found.
>>
>> Do not check for index validity in xdp_parse(): caller should take care
>> of this because has more information (e.g. when "dev" is given or not
>> found) for this.
>>
>> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
>> ---
>>  ip/iplink.c     |   16 +++++++++++++---
>>  ip/iplink_xdp.c |    7 +------
>>  2 files changed, 14 insertions(+), 9 deletions(-)
>>
> 
> don't really see any benefit from this one.

This clearly shows to user what is wrong with it's command line: either
dev/name is missing while parsing VF/XDP or it specifies non existent
network device (or at least ll_name_to_index() can't resolve it).

Moving ifindex check from xdp_parse() to the caller is done to
consolidate all dev/name parsing and validating code in single place:
iplink_parse().

> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

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

end of thread, other threads:[~2018-02-21  7:14 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-20 21:37 [PATCH iproute2-next v2 0/7] iplink: Improve iplink_parse() Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 1/7] utils: Introduce and use nodev() helper routine Serhey Popovych
2018-02-21  5:13   ` David Ahern
2018-02-20 21:37 ` [PATCH iproute2-next v2 2/7] iplink: Correctly report error when network device isn't found Serhey Popovych
2018-02-21  5:15   ` David Ahern
2018-02-21  7:14     ` Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 3/7] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
2018-02-20 23:04   ` Stephen Hemminger
2018-02-21  6:35     ` Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 4/7] iplink: Follow documented behaviour when "index" is given Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 5/7] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 6/7] iplink: Move data structures to block of their users Serhey Popovych
2018-02-20 21:37 ` [PATCH iproute2-next v2 7/7] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych

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.