All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse()
@ 2018-02-22 13:01 Serhey Popovych
  2018-02-22 13:01 ` [PATCH iproute2-next v3 1/8] utils: Introduce and use nodev() helper routine Serhey Popovych
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:01 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.

v3
  Move vxlan/veth ifinfomsg save/restore to separate patch to
  make clear change that perform most of request buffer setups
  and checks in iplink_parse().

  Update commit message descriptions and extra new line from
  "utils: Introduce and use nodev() helper routine" patch.

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

Thanks,
Serhii

Serhey Popovych (8):
  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
  veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg
  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        |   41 +++-------
 ip/iplink_vxlan.c        |   11 ++-
 ip/iplink_xdp.c          |    7 +-
 ip/ipmacsec.c            |    4 +-
 ip/ipmroute.c            |    7 +-
 ip/ipneigh.c             |   14 ++--
 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           |   41 +++-------
 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, 404 insertions(+), 423 deletions(-)

-- 
1.7.10.4

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

* [PATCH iproute2-next v3 1/8] utils: Introduce and use nodev() helper routine
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
@ 2018-02-22 13:01 ` Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found Serhey Popovych
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:01 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          |   14 +++++++-------
 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, 97 insertions(+), 164 deletions(-)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index b4f6e8b..205b4fa 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -311,11 +311,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;
 	}
 
@@ -391,8 +388,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) {
@@ -467,10 +464,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 69c08ec..579d57e 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -485,11 +485,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 8c08baf..f38dc67 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -287,11 +287,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);
 	}
 
 	new_json_obj(json);
@@ -360,16 +357,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 9f4a7a2..19a36b8 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -554,11 +554,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);
 	}
 
 	new_json_obj(json);
diff --git a/include/utils.h b/include/utils.h
index 6bc77e7..e4389ee 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 d01d703..087fa68 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..74864ae 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -178,9 +178,10 @@ 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)
@@ -423,10 +424,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 24aeddd..2b8e4e8 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 c7701fd..c5bb0bf 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;
@@ -529,10 +527,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;
@@ -695,10 +691,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 78b80e6..c1d2df0 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;
 	}
 
@@ -378,10 +376,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] 25+ messages in thread

* [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
  2018-02-22 13:01 ` [PATCH iproute2-next v3 1/8] utils: Introduce and use nodev() helper routine Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-23 23:41   ` David Ahern
  2018-02-22 13:02 ` [PATCH iproute2-next v3 3/8] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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] 25+ messages in thread

* [PATCH iproute2-next v3 3/8] iplink: Use "dev" and "name" parameters interchangeable when possible
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
  2018-02-22 13:01 ` [PATCH iproute2-next v3 1/8] utils: Introduce and use nodev() helper routine Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 4/8] iplink: Follow documented behaviour when "index" is given Serhey Popovych
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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.

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] 25+ messages in thread

* [PATCH iproute2-next v3 4/8] iplink: Follow documented behaviour when "index" is given
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
                   ` (2 preceding siblings ...)
  2018-02-22 13:02 ` [PATCH iproute2-next v3 3/8] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg Serhey Popovych
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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] 25+ messages in thread

* [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
                   ` (3 preceding siblings ...)
  2018-02-22 13:02 ` [PATCH iproute2-next v3 4/8] iplink: Follow documented behaviour when "index" is given Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-26  3:28   ` David Ahern
  2018-02-22 13:02 ` [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 UTC (permalink / raw)
  To: netdev; +Cc: dsahern

Now in iplink_parse() we use ->ifi_change and ->ifi_flags fields and
plan to use ->ifi_index with upcoming change.

Saving, restoring and reinitializing individual fields is error prone:
using new field in iplink_parse() without updating callers in veth and
vxcan will overwrite main device ifinfomsg data.

Since @struct ifinfomsg is small enough with known sizeof() compiler may
inline memcpy()/memset() with few load/store instructions.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/iplink_vxcan.c |   22 ++++++++--------------
 ip/link_veth.c    |   22 ++++++++--------------
 2 files changed, 16 insertions(+), 28 deletions(-)

diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
index ebe9e56..d7e94a0 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -38,11 +38,10 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 	char *link = NULL;
 	char *type = NULL;
 	int index = 0;
+	int group;
 	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,10 +49,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;
-	ifm->ifi_flags = 0;
-	ifm->ifi_change = 0;
+	memcpy(&ifm_save, ifm, sizeof(*ifm));
+	memset(ifm, 0, sizeof(*ifm));
 
 	data = addattr_nest(n, 1024, VXCAN_INFO_PEER);
 
@@ -72,16 +69,13 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 			  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);
 
+	peer_ifm = RTA_DATA(data);
+	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..b6d37b9 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -36,11 +36,10 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 	char *link = NULL;
 	char *type = NULL;
 	int index = 0;
+	int group;
 	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,10 +47,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;
-	ifm->ifi_flags = 0;
-	ifm->ifi_change = 0;
+	memcpy(&ifm_save, ifm, sizeof(*ifm));
+	memset(ifm, 0, sizeof(*ifm));
 
 	data = addattr_nest(n, 1024, VETH_INFO_PEER);
 
@@ -70,16 +67,13 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 			  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);
 
+	peer_ifm = RTA_DATA(data);
+	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] 25+ messages in thread

* [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse()
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
                   ` (4 preceding siblings ...)
  2018-02-22 13:02 ` [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-26  3:31   ` David Ahern
  2018-02-22 13:02 ` [PATCH iproute2-next v3 7/8] iplink: Move data structures to block of their users Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
  7 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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.

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 |   13 +-----
 ip/link_veth.c    |   13 +-----
 4 files changed, 59 insertions(+), 88 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 d7e94a0..7d44e48 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -35,10 +35,7 @@ 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 group;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -57,21 +54,13 @@ 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);
-	}
-
-	if (group != -1)
-		addattr32(n, 1024, IFLA_GROUP, group);
-
 	peer_ifm = RTA_DATA(data);
 	memcpy(peer_ifm, ifm, sizeof(*ifm));
 	memcpy(ifm, &ifm_save, sizeof(*ifm));
diff --git a/ip/link_veth.c b/ip/link_veth.c
index b6d37b9..a42ea4e 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -33,10 +33,7 @@ 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 group;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -55,21 +52,13 @@ 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);
-	}
-
-	if (group != -1)
-		addattr32(n, 1024, IFLA_GROUP, group);
-
 	peer_ifm = RTA_DATA(data);
 	memcpy(peer_ifm, ifm, sizeof(*ifm));
 	memcpy(ifm, &ifm_save, sizeof(*ifm));
-- 
1.7.10.4

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

* [PATCH iproute2-next v3 7/8] iplink: Move data structures to block of their users
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
                   ` (5 preceding siblings ...)
  2018-02-22 13:02 ` [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-22 13:02 ` [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
  7 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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] 25+ messages in thread

* [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
                   ` (6 preceding siblings ...)
  2018-02-22 13:02 ` [PATCH iproute2-next v3 7/8] iplink: Move data structures to block of their users Serhey Popovych
@ 2018-02-22 13:02 ` Serhey Popovych
  2018-02-26  3:35   ` David Ahern
  2018-02-26 18:06   ` Stephen Hemminger
  7 siblings, 2 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-22 13:02 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 7d44e48..66d5a53 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));
 	memset(ifm, 0, sizeof(*ifm));
 
@@ -53,12 +52,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 a42ea4e..6a91729 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));
 	memset(ifm, 0, sizeof(*ifm));
 
@@ -51,12 +50,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] 25+ messages in thread

* Re: [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found
  2018-02-22 13:02 ` [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found Serhey Popovych
@ 2018-02-23 23:41   ` David Ahern
  2018-02-25 12:07     ` Serhey Popovych
  0 siblings, 1 reply; 25+ messages in thread
From: David Ahern @ 2018-02-23 23:41 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/22/18 6:02 AM, Serhey Popovych wrote:
> @@ -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);
> +

I think this is actually the wrong direction. seems to me argv should be
passed to xdp_parse rather than the generic, drv, offload bool's. That
function can then the check on which option it is and has the knowledge
about whether a device is needed or not.


>  			NEXT_ARG();
>  			if (xdp_parse(&argc, &argv, req, dev_index,
>  				      generic, drv, offload))

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

* Re: [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found
  2018-02-23 23:41   ` David Ahern
@ 2018-02-25 12:07     ` Serhey Popovych
  0 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-25 12:07 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> @@ -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);
>> +
> 
> I think this is actually the wrong direction. seems to me argv should be
> passed to xdp_parse rather than the generic, drv, offload bool's. That
> function can then the check on which option it is and has the knowledge
> about whether a device is needed or not.

Okay, I probably will prepare another change instead that accounts your
suggestions. Will add it to v4 later.

> 
> 
>>  			NEXT_ARG();
>>  			if (xdp_parse(&argc, &argv, req, dev_index,
>>  				      generic, drv, offload))



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

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

* Re: [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg
  2018-02-22 13:02 ` [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg Serhey Popovych
@ 2018-02-26  3:28   ` David Ahern
  2018-02-26 15:48     ` Serhey Popovych
  2018-02-26 15:57     ` Serhey Popovych
  0 siblings, 2 replies; 25+ messages in thread
From: David Ahern @ 2018-02-26  3:28 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/22/18 6:02 AM, Serhey Popovych wrote:
> Now in iplink_parse() we use ->ifi_change and ->ifi_flags fields and
> plan to use ->ifi_index with upcoming change.
> 
> Saving, restoring and reinitializing individual fields is error prone:
> using new field in iplink_parse() without updating callers in veth and
> vxcan will overwrite main device ifinfomsg data.
> 
> Since @struct ifinfomsg is small enough with known sizeof() compiler may
> inline memcpy()/memset() with few load/store instructions.
> 
> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
> ---
>  ip/iplink_vxcan.c |   22 ++++++++--------------
>  ip/link_veth.c    |   22 ++++++++--------------
>  2 files changed, 16 insertions(+), 28 deletions(-)

I don't agree that this change has any benefit. Only the flags and
change field are wanted; there is no need to save the entire struct,

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

* Re: [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse()
  2018-02-22 13:02 ` [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
@ 2018-02-26  3:31   ` David Ahern
  2018-02-26 15:51     ` Serhey Popovych
  0 siblings, 1 reply; 25+ messages in thread
From: David Ahern @ 2018-02-26  3:31 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/22/18 6:02 AM, Serhey Popovych wrote:
> 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.
> 
> 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 |   13 +-----
>  ip/link_veth.c    |   13 +-----
>  4 files changed, 59 insertions(+), 88 deletions(-)
> 

IMO veth and vxcan should not be re-using iplink_parse since they only
want a subset of the parsing.

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-22 13:02 ` [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
@ 2018-02-26  3:35   ` David Ahern
  2018-02-26 15:44     ` Serhey Popovych
  2018-02-26 16:07     ` Serhey Popovych
  2018-02-26 18:06   ` Stephen Hemminger
  1 sibling, 2 replies; 25+ messages in thread
From: David Ahern @ 2018-02-26  3:35 UTC (permalink / raw)
  To: Serhey Popovych, netdev

On 2/22/18 6:02 AM, Serhey Popovych wrote:
> 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(-)
> 

Seems like a lot of churn for no benefit.

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26  3:35   ` David Ahern
@ 2018-02-26 15:44     ` Serhey Popovych
  2018-02-26 16:07     ` Serhey Popovych
  1 sibling, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 15:44 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> 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(-)
>>
> 
> Seems like a lot of churn for no benefit.
> 

I plan to extend iplink_get() to be used in tunnels and replace
lot of duplicated code. Since iplink_get() needs interface name
and there is no easy way to get it from netlink buffer provided via
@struct nlmsghdr n, I do all this stuff.

Same applies to name_is_vrf() and ipvrf_get_table(): they do nearly
the same things and can be consolidated. They also use interface
name.

On the other hand at same point I want to start RFC to submit
IFLA_IFNAME by default for all netlink commands instead of
ll_name_to_index() in userspace and giving index to kernel: it
is subject to race, interface might disappear, another interface
could be created before we send netlink message with ifindex.

Kernel knowns better how to translate name to network device and
does this with proper synchronization (RTNL).

> 



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

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

* Re: [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg
  2018-02-26  3:28   ` David Ahern
@ 2018-02-26 15:48     ` Serhey Popovych
  2018-02-26 15:57     ` Serhey Popovych
  1 sibling, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 15:48 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> Now in iplink_parse() we use ->ifi_change and ->ifi_flags fields and
>> plan to use ->ifi_index with upcoming change.
>>
>> Saving, restoring and reinitializing individual fields is error prone:
>> using new field in iplink_parse() without updating callers in veth and
>> vxcan will overwrite main device ifinfomsg data.
>>
>> Since @struct ifinfomsg is small enough with known sizeof() compiler may
>> inline memcpy()/memset() with few load/store instructions.
>>
>> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
>> ---
>>  ip/iplink_vxcan.c |   22 ++++++++--------------
>>  ip/link_veth.c    |   22 ++++++++--------------
>>  2 files changed, 16 insertions(+), 28 deletions(-)
> 
> I don't agree that this change has any benefit. Only the flags and
> change field are wanted; there is no need to save the entire struct,
> 

Struct is small enough, only ifi_change and ifi_flags being used right
now, but next patch also changes ifi_index. Remaining values are fit in
single u32 (ifi_family, ifi_type and pad). So we copy only one extra u32
at the moment. Later if something gets changed and iplink_parse() starts
using ifi_family, ifi_type, ifi_pad... we do not need to modify vxcan
and veth modules.


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

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

* Re: [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse()
  2018-02-26  3:31   ` David Ahern
@ 2018-02-26 15:51     ` Serhey Popovych
  0 siblings, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 15:51 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> 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.
>>
>> 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 |   13 +-----
>>  ip/link_veth.c    |   13 +-----
>>  4 files changed, 59 insertions(+), 88 deletions(-)
>>
> 
> IMO veth and vxcan should not be re-using iplink_parse since they only
> want a subset of the parsing.
> 

In kernel we call rtnl_create_link() and rtnl_configure_link() to
configure peer device from VETH_INFO_PEER. Also we use ifla_policy
from net/core/rtnetlink.c with lots of parameters. Agree not all of them
needed/used for veth, but at the moment dropping iplink_parse() from
vxcan and veth in iproute2 without corresponding change may restrict
functionality.


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

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

* Re: [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg
  2018-02-26  3:28   ` David Ahern
  2018-02-26 15:48     ` Serhey Popovych
@ 2018-02-26 15:57     ` Serhey Popovych
  1 sibling, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 15:57 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> Now in iplink_parse() we use ->ifi_change and ->ifi_flags fields and
>> plan to use ->ifi_index with upcoming change.
>>
>> Saving, restoring and reinitializing individual fields is error prone:
>> using new field in iplink_parse() without updating callers in veth and
>> vxcan will overwrite main device ifinfomsg data.
>>
>> Since @struct ifinfomsg is small enough with known sizeof() compiler may
>> inline memcpy()/memset() with few load/store instructions.
>>
>> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
>> ---
>>  ip/iplink_vxcan.c |   22 ++++++++--------------
>>  ip/link_veth.c    |   22 ++++++++--------------
>>  2 files changed, 16 insertions(+), 28 deletions(-)
> 
> I don't agree that this change has any benefit. Only the flags and
> change field are wanted; there is no need to save the entire struct,
> 

At the v0 (before submitted) I think so and just add ifi_index
save/restore in addition to ifi_change and ifi_flags. But when
look that memcpy() at 64-bit inlined to just two load/store
instructions I decided to send memcpy()/memset() variant.

If saving/restoring just ifi_index in addition to ifi_change and
ifi_flags instead of full @struct ifinfomsg is preferred I will
get rid of this change and add ifi_index to corresponding patch
within series.


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

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26  3:35   ` David Ahern
  2018-02-26 15:44     ` Serhey Popovych
@ 2018-02-26 16:07     ` Serhey Popovych
  1 sibling, 0 replies; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 16:07 UTC (permalink / raw)
  To: David Ahern, netdev


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

David Ahern wrote:
> On 2/22/18 6:02 AM, Serhey Popovych wrote:
>> 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(-)
>>
> 
> Seems like a lot of churn for no benefit.

Real benefit at the moment: reduce number of parameters in function
iplink_parse() that has trend to grow. Someone needs something in
->parse_opt() that is in netlink buffer. How to provide this best?

In my opinion is to add field to struct rather than argument to a function.

> 
> 


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

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-22 13:02 ` [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
  2018-02-26  3:35   ` David Ahern
@ 2018-02-26 18:06   ` Stephen Hemminger
  2018-02-26 18:20     ` Serhey Popovych
  1 sibling, 1 reply; 25+ messages in thread
From: Stephen Hemminger @ 2018-02-26 18:06 UTC (permalink / raw)
  To: Serhey Popovych; +Cc: netdev, dsahern

On Thu, 22 Feb 2018 15:02:06 +0200
Serhey Popovych <serhe.popovych@gmail.com> wrote:

> +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;
> +};
> +

No control block please.
If you have too many arguments, then that means you need to do
some refactoring.

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26 18:06   ` Stephen Hemminger
@ 2018-02-26 18:20     ` Serhey Popovych
  2018-02-26 18:27       ` David Ahern
  0 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 18:20 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, dsahern


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

Stephen Hemminger wrote:
> On Thu, 22 Feb 2018 15:02:06 +0200
> Serhey Popovych <serhe.popovych@gmail.com> wrote:
> 
>> +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;
>> +};
>> +
> 
> No control block please.
Accepted.

> If you have too many arguments, then that means you need to do
> some refactoring.

So using structure as single argument to a function isn't an option?

> 



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

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26 18:20     ` Serhey Popovych
@ 2018-02-26 18:27       ` David Ahern
  2018-02-26 18:38         ` Serhey Popovych
  0 siblings, 1 reply; 25+ messages in thread
From: David Ahern @ 2018-02-26 18:27 UTC (permalink / raw)
  To: Serhey Popovych, Stephen Hemminger; +Cc: netdev

On 2/26/18 11:20 AM, Serhey Popovych wrote:
> Stephen Hemminger wrote:
>> On Thu, 22 Feb 2018 15:02:06 +0200
>> Serhey Popovych <serhe.popovych@gmail.com> wrote:
>>
>>> +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;
>>> +};
>>> +
>>
>> No control block please.
> Accepted.
> 
>> If you have too many arguments, then that means you need to do
>> some refactoring.
> 
> So using structure as single argument to a function isn't an option?
> 
>>
> 
> 

As I mentioned before, iplink_parse should not be used by vxcan or veth
as they only want a subset of the parsing. Once you take those users
out, iplink_parse becomes local to iplink.c with a single user. In which
case I suspect the compiler will always inline the function so no
refactoring on the number of arguments is needed.

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26 18:27       ` David Ahern
@ 2018-02-26 18:38         ` Serhey Popovych
  2018-02-26 20:09           ` Serhey Popovych
  0 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 18:38 UTC (permalink / raw)
  To: David Ahern, Stephen Hemminger; +Cc: netdev


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

David Ahern wrote:
> On 2/26/18 11:20 AM, Serhey Popovych wrote:
>> Stephen Hemminger wrote:
>>> On Thu, 22 Feb 2018 15:02:06 +0200
>>> Serhey Popovych <serhe.popovych@gmail.com> wrote:
>>>
>>>> +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;
>>>> +};
>>>> +
>>>
>>> No control block please.
>> Accepted.
>>
>>> If you have too many arguments, then that means you need to do
>>> some refactoring.
>>
>> So using structure as single argument to a function isn't an option?
>>
>>>
>>
>>
> 
> As I mentioned before, iplink_parse should not be used by vxcan or veth
> as they only want a subset of the parsing. Once you take those users
> out, iplink_parse becomes local to iplink.c with a single user. In which
> case I suspect the compiler will always inline the function so no
> refactoring on the number of arguments is needed.
> 
I will implement cut down function to parse vxcan and veth peer device
parameters and reuse it in iplink_parse() to avoid code duplications.

But my final goal not to refactor on number of arguments to parse,
that's side product of this series, I want to take @name, @dev and
other parameters for later use. In ->parse_opt() modules @name, @dev
and others are not available easily. It seems only way to get them is
to parse supplied netlink buffer.




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

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26 18:38         ` Serhey Popovych
@ 2018-02-26 20:09           ` Serhey Popovych
  2018-02-26 21:35             ` Stephen Hemminger
  0 siblings, 1 reply; 25+ messages in thread
From: Serhey Popovych @ 2018-02-26 20:09 UTC (permalink / raw)
  To: David Ahern, Stephen Hemminger; +Cc: netdev


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

Serhey Popovych wrote:
> David Ahern wrote:
>> On 2/26/18 11:20 AM, Serhey Popovych wrote:
>>> Stephen Hemminger wrote:
>>>> On Thu, 22 Feb 2018 15:02:06 +0200
>>>> Serhey Popovych <serhe.popovych@gmail.com> wrote:
>>>>
>>>>> +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;
>>>>> +};
>>>>> +
>>>>
>>>> No control block please.
>>> Accepted.
>>>
>>>> If you have too many arguments, then that means you need to do
>>>> some refactoring.
>>>
>>> So using structure as single argument to a function isn't an option?
>>>
>>>>
>>>
>>>
>>
>> As I mentioned before, iplink_parse should not be used by vxcan or veth
>> as they only want a subset of the parsing. Once you take those users
>> out, iplink_parse becomes local to iplink.c with a single user. In which
>> case I suspect the compiler will always inline the function so no
>> refactoring on the number of arguments is needed.
>>
> I will implement cut down function to parse vxcan and veth peer device
> parameters and reuse it in iplink_parse() to avoid code duplications.
> 
> But my final goal not to refactor on number of arguments to parse,
> that's side product of this series, I want to take @name, @dev and
> other parameters for later use. In ->parse_opt() modules @name, @dev
> and others are not available easily. It seems only way to get them is
> to parse supplied netlink buffer.
> 
> 
While looking on how to make iplink_parse_light() that will be used with
vxcan and veth I found following problems:

  1) need to copy nearly all parameters parsing code (except vf, alias,
     carrier, master, protodown, link-netnsid, addrgenmode). this will
     be mitigated by re using iplink_parse_light() in iplink_parse()

  2) how to add attributes like IFLA_GROUP? in caller? this will give
     even more code duplications.

  3) there is high risk of adding regression either via conflicting
     matches() parameter in userspace or missing kernel attribute
     previously supported.

Sorry, I do not like this approach. I do not want to broke anything,
I just want @name and @dev parameters in ->parse_opt().


  2)
> 



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

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

* Re: [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse()
  2018-02-26 20:09           ` Serhey Popovych
@ 2018-02-26 21:35             ` Stephen Hemminger
  0 siblings, 0 replies; 25+ messages in thread
From: Stephen Hemminger @ 2018-02-26 21:35 UTC (permalink / raw)
  To: Serhey Popovych; +Cc: David Ahern, netdev

[-- Attachment #1: Type: text/plain, Size: 2749 bytes --]

On Mon, 26 Feb 2018 22:09:03 +0200
Serhey Popovych <serhe.popovych@gmail.com> wrote:

> Serhey Popovych wrote:
> > David Ahern wrote:  
> >> On 2/26/18 11:20 AM, Serhey Popovych wrote:  
> >>> Stephen Hemminger wrote:  
> >>>> On Thu, 22 Feb 2018 15:02:06 +0200
> >>>> Serhey Popovych <serhe.popovych@gmail.com> wrote:
> >>>>  
> >>>>> +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;
> >>>>> +};
> >>>>> +  
> >>>>
> >>>> No control block please.  
> >>> Accepted.
> >>>  
> >>>> If you have too many arguments, then that means you need to do
> >>>> some refactoring.  
> >>>
> >>> So using structure as single argument to a function isn't an option?
> >>>  
> >>>>  
> >>>
> >>>  
> >>
> >> As I mentioned before, iplink_parse should not be used by vxcan or veth
> >> as they only want a subset of the parsing. Once you take those users
> >> out, iplink_parse becomes local to iplink.c with a single user. In which
> >> case I suspect the compiler will always inline the function so no
> >> refactoring on the number of arguments is needed.
> >>  
> > I will implement cut down function to parse vxcan and veth peer device
> > parameters and reuse it in iplink_parse() to avoid code duplications.
> > 
> > But my final goal not to refactor on number of arguments to parse,
> > that's side product of this series, I want to take @name, @dev and
> > other parameters for later use. In ->parse_opt() modules @name, @dev
> > and others are not available easily. It seems only way to get them is
> > to parse supplied netlink buffer.
> > 
> >   
> While looking on how to make iplink_parse_light() that will be used with
> vxcan and veth I found following problems:
> 
>   1) need to copy nearly all parameters parsing code (except vf, alias,
>      carrier, master, protodown, link-netnsid, addrgenmode). this will
>      be mitigated by re using iplink_parse_light() in iplink_parse()
> 
>   2) how to add attributes like IFLA_GROUP? in caller? this will give
>      even more code duplications.
> 
>   3) there is high risk of adding regression either via conflicting
>      matches() parameter in userspace or missing kernel attribute
>      previously supported.
> 
> Sorry, I do not like this approach. I do not want to broke anything,
> I just want @name and @dev parameters in ->parse_opt().
> 
> 
>   2)
> >   

If the work to use common code is bigger than the code itself
then why bother. There is no benefit.

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

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

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

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-22 13:01 [PATCH iproute2-next v3 0/8] iplink: Improve iplink_parse() Serhey Popovych
2018-02-22 13:01 ` [PATCH iproute2-next v3 1/8] utils: Introduce and use nodev() helper routine Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 2/8] iplink: Correctly report error when network device isn't found Serhey Popovych
2018-02-23 23:41   ` David Ahern
2018-02-25 12:07     ` Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 3/8] iplink: Use "dev" and "name" parameters interchangeable when possible Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 4/8] iplink: Follow documented behaviour when "index" is given Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 5/8] veth,vxcan: Save/reinitialize/restore whole @struct ifinfomsg Serhey Popovych
2018-02-26  3:28   ` David Ahern
2018-02-26 15:48     ` Serhey Popovych
2018-02-26 15:57     ` Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 6/8] iplink: Perform most of request buffer setups and checks in iplink_parse() Serhey Popovych
2018-02-26  3:31   ` David Ahern
2018-02-26 15:51     ` Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 7/8] iplink: Move data structures to block of their users Serhey Popovych
2018-02-22 13:02 ` [PATCH iproute2-next v3 8/8] iplink: Reduce number of arguments to iplink_parse() Serhey Popovych
2018-02-26  3:35   ` David Ahern
2018-02-26 15:44     ` Serhey Popovych
2018-02-26 16:07     ` Serhey Popovych
2018-02-26 18:06   ` Stephen Hemminger
2018-02-26 18:20     ` Serhey Popovych
2018-02-26 18:27       ` David Ahern
2018-02-26 18:38         ` Serhey Popovych
2018-02-26 20:09           ` Serhey Popovych
2018-02-26 21:35             ` Stephen Hemminger

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.