All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops
@ 2020-07-20  3:49 Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 1/4] net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops Florian Fainelli
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Florian Fainelli @ 2020-07-20  3:49 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
	Jakub Kicinski, Jiri Pirko, Eric Dumazet, Taehee Yoo, Cong Wang,
	Maxim Mikityanskiy, Richard Cochran, Michal Kubecek, open list,
	olteanv

Hi David, Jakub,

This patch series addresses the overloading of a DSA CPU/management
interface's netdev_ops for the purpose of providing useful information
from the switch side.

Up until now we had duplicated the existing netdev_ops structure and
added specific function pointers to return information of interest. Here
we have a more controlled way of doing this by involving the specific
netdev_ops function pointers that we want to be patched, which is easier
for auditing code in the future. As a byproduct we can now maintain
netdev_ops pointer comparisons which would be failing before (no known
in tree problems because of that though).

Let me know if this approach looks reasonable to you and we might do the
same with our ethtool_ops overloading as well.

Thanks!

Changes in v2:

- use static inline int vs. static int inline (Kbuild robot)
- fixed typos in patch 4 (Andrew)
- avoid using macros (Andrew)

Florian Fainelli (4):
  net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops
  net: dsa: Add wrappers for overloaded ndo_ops
  net: Call into DSA netdevice_ops wrappers
  net: dsa: Setup dsa_netdev_ops

 include/net/dsa.h    | 71 +++++++++++++++++++++++++++++++++++++++++++-
 net/core/dev.c       |  5 ++++
 net/core/dev_ioctl.c | 29 +++++++++++++-----
 net/dsa/master.c     | 52 ++++++++------------------------
 4 files changed, 110 insertions(+), 47 deletions(-)

-- 
2.25.1


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

* [PATCH net-next v2 1/4] net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops
  2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
@ 2020-07-20  3:49 ` Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 2/4] net: dsa: Add wrappers for overloaded ndo_ops Florian Fainelli
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2020-07-20  3:49 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
	Jakub Kicinski, Jiri Pirko, Eric Dumazet, Taehee Yoo, Cong Wang,
	Maxim Mikityanskiy, Richard Cochran, Michal Kubecek, open list,
	olteanv

In preparation for adding another layer of call into a DSA stacked ops
singleton, wrap the ndo_do_ioctl() call into dev_do_ioctl().

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/core/dev_ioctl.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 547b587c1950..a213c703c90a 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -225,6 +225,22 @@ static int net_hwtstamp_validate(struct ifreq *ifr)
 	return 0;
 }
 
+static int dev_do_ioctl(struct net_device *dev,
+			struct ifreq *ifr, unsigned int cmd)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+	int err = -EOPNOTSUPP;
+
+	if (ops->ndo_do_ioctl) {
+		if (netif_device_present(dev))
+			err = ops->ndo_do_ioctl(dev, ifr, cmd);
+		else
+			err = -ENODEV;
+	}
+
+	return err;
+}
+
 /*
  *	Perform the SIOCxIFxxx calls, inside rtnl_lock()
  */
@@ -323,13 +339,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
 		    cmd == SIOCSHWTSTAMP ||
 		    cmd == SIOCGHWTSTAMP ||
 		    cmd == SIOCWANDEV) {
-			err = -EOPNOTSUPP;
-			if (ops->ndo_do_ioctl) {
-				if (netif_device_present(dev))
-					err = ops->ndo_do_ioctl(dev, ifr, cmd);
-				else
-					err = -ENODEV;
-			}
+			err = dev_do_ioctl(dev, ifr, cmd);
 		} else
 			err = -EINVAL;
 
-- 
2.25.1


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

* [PATCH net-next v2 2/4] net: dsa: Add wrappers for overloaded ndo_ops
  2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 1/4] net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops Florian Fainelli
@ 2020-07-20  3:49 ` Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 3/4] net: Call into DSA netdevice_ops wrappers Florian Fainelli
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2020-07-20  3:49 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
	Jakub Kicinski, Jiri Pirko, Eric Dumazet, Taehee Yoo, Cong Wang,
	Maxim Mikityanskiy, Richard Cochran, Michal Kubecek, open list,
	olteanv

Add definitions for the dsa_netdevice_ops structure which is a subset of
the net_device_ops structure for the specific operations that we care
about overlaying on top of the DSA CPU port net_device and provide
inline stubs that take core managing whether DSA code is reachable.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/net/dsa.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 6fa418ff1175..343642ca4f63 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -86,6 +86,18 @@ struct dsa_device_ops {
 	enum dsa_tag_protocol proto;
 };
 
+/* This structure defines the control interfaces that are overlayed by the
+ * DSA layer on top of the DSA CPU/management net_device instance. This is
+ * used by the core net_device layer while calling various net_device_ops
+ * function pointers.
+ */
+struct dsa_netdevice_ops {
+	int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr,
+			    int cmd);
+	int (*ndo_get_phys_port_name)(struct net_device *dev, char *name,
+				      size_t len);
+};
+
 #define DSA_TAG_DRIVER_ALIAS "dsa_tag-"
 #define MODULE_ALIAS_DSA_TAG_DRIVER(__proto)				\
 	MODULE_ALIAS(DSA_TAG_DRIVER_ALIAS __stringify(__proto##_VALUE))
@@ -217,6 +229,7 @@ struct dsa_port {
 	/*
 	 * Original copy of the master netdev net_device_ops
 	 */
+	const struct dsa_netdevice_ops *netdev_ops;
 	const struct net_device_ops *orig_ndo_ops;
 
 	bool setup;
@@ -679,6 +692,63 @@ static inline bool dsa_can_decode(const struct sk_buff *skb,
 	return false;
 }
 
+#if IS_ENABLED(CONFIG_NET_DSA)
+static inline int __dsa_netdevice_ops_check(struct net_device *dev)
+{
+	int err = -EOPNOTSUPP;
+
+	if (!dev->dsa_ptr)
+		return err;
+
+	if (!dev->dsa_ptr->netdev_ops)
+		return err;
+
+	return 0;
+}
+
+static inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr,
+				   int cmd)
+{
+	const struct dsa_netdevice_ops *ops;
+	int err;
+
+	err = __dsa_netdevice_ops_check(dev);
+	if (err)
+		return err;
+
+	ops = dev->dsa_ptr->netdev_ops;
+
+	return ops->ndo_do_ioctl(dev, ifr, cmd);
+}
+
+static inline int dsa_ndo_get_phys_port_name(struct net_device *dev,
+					     char *name, size_t len)
+{
+	const struct dsa_netdevice_ops *ops;
+	int err;
+
+	err = __dsa_netdevice_ops_check(dev);
+	if (err)
+		return err;
+
+	ops = dev->dsa_ptr->netdev_ops;
+
+	return ops->ndo_get_phys_port_name(dev, name, len);
+}
+#else
+static inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr,
+				   int cmd)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int dsa_ndo_get_phys_port_name(struct net_device *dev,
+					     char *name, size_t len)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
 void dsa_unregister_switch(struct dsa_switch *ds);
 int dsa_register_switch(struct dsa_switch *ds);
 struct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
-- 
2.25.1


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

* [PATCH net-next v2 3/4] net: Call into DSA netdevice_ops wrappers
  2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 1/4] net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 2/4] net: dsa: Add wrappers for overloaded ndo_ops Florian Fainelli
@ 2020-07-20  3:49 ` Florian Fainelli
  2020-07-20  3:49 ` [PATCH net-next v2 4/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
  2020-07-20 23:49 ` [PATCH net-next v2 0/4] " David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2020-07-20  3:49 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
	Jakub Kicinski, Jiri Pirko, Eric Dumazet, Taehee Yoo, Cong Wang,
	Maxim Mikityanskiy, Richard Cochran, Michal Kubecek, open list,
	olteanv

Make the core net_device code call into our ndo_do_ioctl() and
ndo_get_phys_port_name() functions via the wrappers defined previously

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/core/dev.c       | 5 +++++
 net/core/dev_ioctl.c | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/net/core/dev.c b/net/core/dev.c
index 062a00fdca9b..19f1abc26fcd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -98,6 +98,7 @@
 #include <net/busy_poll.h>
 #include <linux/rtnetlink.h>
 #include <linux/stat.h>
+#include <net/dsa.h>
 #include <net/dst.h>
 #include <net/dst_metadata.h>
 #include <net/pkt_sched.h>
@@ -8602,6 +8603,10 @@ int dev_get_phys_port_name(struct net_device *dev,
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int err;
 
+	err  = dsa_ndo_get_phys_port_name(dev, name, len);
+	if (err == 0 || err != -EOPNOTSUPP)
+		return err;
+
 	if (ops->ndo_get_phys_port_name) {
 		err = ops->ndo_get_phys_port_name(dev, name, len);
 		if (err != -EOPNOTSUPP)
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index a213c703c90a..b2cf9b7bb7b8 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -5,6 +5,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/net_tstamp.h>
 #include <linux/wireless.h>
+#include <net/dsa.h>
 #include <net/wext.h>
 
 /*
@@ -231,6 +232,10 @@ static int dev_do_ioctl(struct net_device *dev,
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int err = -EOPNOTSUPP;
 
+	err = dsa_ndo_do_ioctl(dev, ifr, cmd);
+	if (err == 0 || err != -EOPNOTSUPP)
+		return err;
+
 	if (ops->ndo_do_ioctl) {
 		if (netif_device_present(dev))
 			err = ops->ndo_do_ioctl(dev, ifr, cmd);
-- 
2.25.1


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

* [PATCH net-next v2 4/4] net: dsa: Setup dsa_netdev_ops
  2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
                   ` (2 preceding siblings ...)
  2020-07-20  3:49 ` [PATCH net-next v2 3/4] net: Call into DSA netdevice_ops wrappers Florian Fainelli
@ 2020-07-20  3:49 ` Florian Fainelli
  2020-07-20 23:49 ` [PATCH net-next v2 0/4] " David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Florian Fainelli @ 2020-07-20  3:49 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, David S. Miller,
	Jakub Kicinski, Jiri Pirko, Eric Dumazet, Taehee Yoo, Cong Wang,
	Maxim Mikityanskiy, Richard Cochran, Michal Kubecek, open list,
	olteanv

Now that we have all the infrastructure in place for calling into the
dsa_ptr->netdev_ops function pointers, install them when we configure
the DSA CPU/management interface and tear them down. The flow is
unchanged from before, but now we preserve equality of tests when
network device drivers do tests like dev->netdev_ops == &foo_ops which
was not the case before since we were allocating an entirely new
structure.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 include/net/dsa.h |  1 -
 net/dsa/master.c  | 52 ++++++++++++-----------------------------------
 2 files changed, 13 insertions(+), 40 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 343642ca4f63..f1b63d06d132 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -230,7 +230,6 @@ struct dsa_port {
 	 * Original copy of the master netdev net_device_ops
 	 */
 	const struct dsa_netdevice_ops *netdev_ops;
-	const struct net_device_ops *orig_ndo_ops;
 
 	bool setup;
 };
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 480a61460c23..0a90911ae31b 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -220,12 +220,17 @@ static int dsa_master_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		break;
 	}
 
-	if (cpu_dp->orig_ndo_ops && cpu_dp->orig_ndo_ops->ndo_do_ioctl)
-		err = cpu_dp->orig_ndo_ops->ndo_do_ioctl(dev, ifr, cmd);
+	if (dev->netdev_ops->ndo_do_ioctl)
+		err = dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
 
 	return err;
 }
 
+static const struct dsa_netdevice_ops dsa_netdev_ops = {
+	.ndo_do_ioctl = dsa_master_ioctl,
+	.ndo_get_phys_port_name = dsa_master_get_phys_port_name,
+};
+
 static int dsa_master_ethtool_setup(struct net_device *dev)
 {
 	struct dsa_port *cpu_dp = dev->dsa_ptr;
@@ -260,38 +265,10 @@ static void dsa_master_ethtool_teardown(struct net_device *dev)
 	cpu_dp->orig_ethtool_ops = NULL;
 }
 
-static int dsa_master_ndo_setup(struct net_device *dev)
-{
-	struct dsa_port *cpu_dp = dev->dsa_ptr;
-	struct dsa_switch *ds = cpu_dp->ds;
-	struct net_device_ops *ops;
-
-	if (dev->netdev_ops->ndo_get_phys_port_name)
-		return 0;
-
-	ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL);
-	if (!ops)
-		return -ENOMEM;
-
-	cpu_dp->orig_ndo_ops = dev->netdev_ops;
-	if (cpu_dp->orig_ndo_ops)
-		memcpy(ops, cpu_dp->orig_ndo_ops, sizeof(*ops));
-
-	ops->ndo_get_phys_port_name = dsa_master_get_phys_port_name;
-	ops->ndo_do_ioctl = dsa_master_ioctl;
-
-	dev->netdev_ops  = ops;
-
-	return 0;
-}
-
-static void dsa_master_ndo_teardown(struct net_device *dev)
+static void dsa_netdev_ops_set(struct net_device *dev,
+			       const struct dsa_netdevice_ops *ops)
 {
-	struct dsa_port *cpu_dp = dev->dsa_ptr;
-
-	if (cpu_dp->orig_ndo_ops)
-		dev->netdev_ops = cpu_dp->orig_ndo_ops;
-	cpu_dp->orig_ndo_ops = NULL;
+	dev->dsa_ptr->netdev_ops = ops;
 }
 
 static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
@@ -353,9 +330,7 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 	if (ret)
 		return ret;
 
-	ret = dsa_master_ndo_setup(dev);
-	if (ret)
-		goto out_err_ethtool_teardown;
+	dsa_netdev_ops_set(dev, &dsa_netdev_ops);
 
 	ret = sysfs_create_group(&dev->dev.kobj, &dsa_group);
 	if (ret)
@@ -364,8 +339,7 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 	return ret;
 
 out_err_ndo_teardown:
-	dsa_master_ndo_teardown(dev);
-out_err_ethtool_teardown:
+	dsa_netdev_ops_set(dev, NULL);
 	dsa_master_ethtool_teardown(dev);
 	return ret;
 }
@@ -373,7 +347,7 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 void dsa_master_teardown(struct net_device *dev)
 {
 	sysfs_remove_group(&dev->dev.kobj, &dsa_group);
-	dsa_master_ndo_teardown(dev);
+	dsa_netdev_ops_set(dev, NULL);
 	dsa_master_ethtool_teardown(dev);
 	dsa_master_reset_mtu(dev);
 
-- 
2.25.1


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

* Re: [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops
  2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
                   ` (3 preceding siblings ...)
  2020-07-20  3:49 ` [PATCH net-next v2 4/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
@ 2020-07-20 23:49 ` David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2020-07-20 23:49 UTC (permalink / raw)
  To: f.fainelli
  Cc: netdev, andrew, vivien.didelot, kuba, jiri, edumazet, ap420073,
	xiyou.wangcong, maximmi, richardcochran, mkubecek, linux-kernel,
	olteanv

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Sun, 19 Jul 2020 20:49:50 -0700

> This patch series addresses the overloading of a DSA CPU/management
> interface's netdev_ops for the purpose of providing useful information
> from the switch side.
> 
> Up until now we had duplicated the existing netdev_ops structure and
> added specific function pointers to return information of interest. Here
> we have a more controlled way of doing this by involving the specific
> netdev_ops function pointers that we want to be patched, which is easier
> for auditing code in the future. As a byproduct we can now maintain
> netdev_ops pointer comparisons which would be failing before (no known
> in tree problems because of that though).
> 
> Let me know if this approach looks reasonable to you and we might do the
> same with our ethtool_ops overloading as well.

This looks good to me, series applied.

And yes, doing something similar for ethtool_ops is probably a good idea
too.

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

end of thread, other threads:[~2020-07-21  0:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-20  3:49 [PATCH net-next v2 0/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
2020-07-20  3:49 ` [PATCH net-next v2 1/4] net: Wrap ndo_do_ioctl() to prepare for DSA stacked ops Florian Fainelli
2020-07-20  3:49 ` [PATCH net-next v2 2/4] net: dsa: Add wrappers for overloaded ndo_ops Florian Fainelli
2020-07-20  3:49 ` [PATCH net-next v2 3/4] net: Call into DSA netdevice_ops wrappers Florian Fainelli
2020-07-20  3:49 ` [PATCH net-next v2 4/4] net: dsa: Setup dsa_netdev_ops Florian Fainelli
2020-07-20 23:49 ` [PATCH net-next v2 0/4] " David Miller

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.