From: sfeldma@gmail.com
To: netdev@vger.kernel.org
Cc: jiri@resnulli.us, roopa@cumulusnetworks.com, linux@roeck-us.net,
f.fainelli@gmail.com, sridhar.samudrala@intel.com,
ronen.arad@intel.com
Subject: [PATCH net-next v2 01/26] switchdev: introduce get/set attrs ops
Date: Wed, 1 Apr 2015 03:07:37 -0700 [thread overview]
Message-ID: <1427882882-2533-2-git-send-email-sfeldma@gmail.com> (raw)
In-Reply-To: <1427882882-2533-1-git-send-email-sfeldma@gmail.com>
From: Scott Feldman <sfeldma@gmail.com>
Add two new swdev ops for get/set switch port attributes. Most swdev
interactions on a port are gets or sets on port attributes, so rather than
adding ops for each attribute, let's define clean get/set ops for all
attributes, and then we can have clear, consistent rules on how attributes
propagate on stacked devs.
Add the basic algorithms for get/set attr ops. Use the same recusive algo to
walk lower devs we've used for STP updates, for example. For get, compare attr
value for each lower dev and only return success if attr values match across
all lower devs. For sets, set the same attr value for all lower devs. If
something goes wrong on one of the lower devs, revert all back to previous attr
value.
If lower dev recusion isn't desired, allow a flag SWDEV_F_NO_RECURSE to
indicate get/set only work on port (lowest) device.
On set, allow a flag SWDEV_F_NO_RECOVER to turn off automatic err recovery.
Signed-off-by: Scott Feldman <sfeldma@gmail.com>
---
include/net/switchdev.h | 34 +++++++++++++++
net/switchdev/switchdev.c | 102 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 136 insertions(+)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index d2e69ee..b5a7d06 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -14,6 +14,18 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
+#define SWDEV_F_NO_RECURSE BIT(0)
+#define SWDEV_F_NO_RECOVER BIT(1)
+
+enum swdev_attr_id {
+ SWDEV_ATTR_UNDEFINED,
+};
+
+struct swdev_attr {
+ enum swdev_attr_id id;
+ u32 flags;
+};
+
struct fib_info;
/**
@@ -23,6 +35,10 @@ struct fib_info;
* is part of. If driver implements this, it indicates that it
* represents a port of a switch chip.
*
+ * @swdev_port_attr_get: Get a port attribute (see swdev_attr).
+ *
+ * @swdev_port_attr_set: Set a port attribute (see swdev_attr).
+ *
* @swdev_port_stp_update: Called to notify switch device port of bridge
* port STP state change.
*
@@ -33,6 +49,10 @@ struct fib_info;
struct swdev_ops {
int (*swdev_parent_id_get)(struct net_device *dev,
struct netdev_phys_item_id *psid);
+ int (*swdev_port_attr_get)(struct net_device *dev,
+ struct swdev_attr *attr);
+ int (*swdev_port_attr_set)(struct net_device *dev,
+ struct swdev_attr *attr);
int (*swdev_port_stp_update)(struct net_device *dev, u8 state);
int (*swdev_fib_ipv4_add)(struct net_device *dev, __be32 dst,
int dst_len, struct fib_info *fi,
@@ -68,6 +88,8 @@ netdev_switch_notifier_info_to_dev(const struct netdev_switch_notifier_info *inf
int netdev_switch_parent_id_get(struct net_device *dev,
struct netdev_phys_item_id *psid);
+int swdev_port_attr_get(struct net_device *dev, struct swdev_attr *attr);
+int swdev_port_attr_set(struct net_device *dev, struct swdev_attr *attr);
int netdev_switch_port_stp_update(struct net_device *dev, u8 state);
int register_netdev_switch_notifier(struct notifier_block *nb);
int unregister_netdev_switch_notifier(struct notifier_block *nb);
@@ -95,6 +117,18 @@ static inline int netdev_switch_parent_id_get(struct net_device *dev,
return -EOPNOTSUPP;
}
+static inline int swdev_port_attr_get(struct net_device *dev,
+ enum swdev_attr *attr)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int swdev_port_attr_set(struct net_device *dev,
+ enum swdev_attr *attr)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int netdev_switch_port_stp_update(struct net_device *dev,
u8 state)
{
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 46568b8..e41cf72 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -37,6 +37,108 @@ int netdev_switch_parent_id_get(struct net_device *dev,
EXPORT_SYMBOL_GPL(netdev_switch_parent_id_get);
/**
+ * swdev_port_attr_get - Get port attribute
+ *
+ * @dev: port device
+ * @attr: attribute to get
+ */
+int swdev_port_attr_get(struct net_device *dev, struct swdev_attr *attr)
+{
+ const struct swdev_ops *ops = dev->swdev_ops;
+ struct net_device *lower_dev;
+ struct list_head *iter;
+ struct swdev_attr first = {
+ .id = SWDEV_ATTR_UNDEFINED
+ };
+ int err = -EOPNOTSUPP;
+
+ if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
+ return err;
+
+ if (ops && ops->swdev_port_attr_get)
+ return ops->swdev_port_attr_get(dev, attr);
+
+ if (attr->flags & SWDEV_F_NO_RECURSE)
+ return err;
+
+ /* Switch device port(s) may be stacked under
+ * bond/team/vlan dev, so recurse down to get attr on
+ * each port. Return -ENODATA if attr values don't
+ * compare across ports.
+ */
+
+ netdev_for_each_lower_dev(dev, lower_dev, iter) {
+ err = swdev_port_attr_get(lower_dev, attr);
+ if (err)
+ break;
+ if (first.id == SWDEV_ATTR_UNDEFINED)
+ first = *attr;
+ else if (memcmp(&first, attr, sizeof(*attr)))
+ return -ENODATA;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(swdev_port_attr_get);
+
+static int __swdev_port_attr_set(struct net_device *dev,
+ struct swdev_attr *attr)
+{
+ const struct swdev_ops *ops = dev->swdev_ops;
+ struct net_device *lower_dev;
+ struct list_head *iter;
+ int err = -EOPNOTSUPP;
+
+ if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
+ return err;
+
+ if (ops && ops->swdev_port_attr_set)
+ return ops->swdev_port_attr_set(dev, attr);
+
+ if (attr->flags & SWDEV_F_NO_RECURSE)
+ return err;
+
+ /* Switch device port(s) may be stacked under
+ * bond/team/vlan dev, so recurse down to set attr on
+ * each port.
+ */
+
+ netdev_for_each_lower_dev(dev, lower_dev, iter) {
+ err = __swdev_port_attr_set(lower_dev, attr);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+/**
+ * swdev_port_attr_set - Set port attribute
+ *
+ * @dev: port device
+ * @attr: attribute to set
+ */
+int swdev_port_attr_set(struct net_device *dev, struct swdev_attr *attr)
+{
+ struct swdev_attr prev = *attr;
+ int err, get_err, revert_err;
+
+ get_err = swdev_port_attr_get(dev, &prev);
+
+ err = __swdev_port_attr_set(dev, attr);
+ if (err && !get_err && !(attr->flags & SWDEV_F_NO_RECOVER)) {
+ /* Some err on set: revert to previous value */
+ revert_err = __swdev_port_attr_set(dev, &prev);
+ if (revert_err)
+ netdev_err(dev, "Reverting swdev port attr %d failed\n",
+ attr->id);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(swdev_port_attr_set);
+
+/**
* netdev_switch_port_stp_update - Notify switch device port of STP
* state change
* @dev: port device
--
1.7.10.4
next prev parent reply other threads:[~2015-04-01 10:06 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-01 10:07 [PATCH net-next v2 00/26] switchdev: spring cleanup sfeldma
2015-04-01 10:07 ` sfeldma [this message]
2015-04-01 12:19 ` [PATCH net-next v2 01/26] switchdev: introduce get/set attrs ops Jamal Hadi Salim
2015-04-01 18:08 ` David Miller
2015-04-02 7:43 ` Scott Feldman
2015-04-02 16:05 ` David Miller
2015-04-02 17:38 ` Scott Feldman
2015-04-02 17:54 ` David Miller
2015-04-02 18:43 ` Andrew Lunn
2015-04-01 10:07 ` [PATCH net-next v2 02/26] switchdev: convert parent_id_get to swdev attr get sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 03/26] switchdev: convert STP update to swdev attr set sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 04/26] switchdev: add bridge port flags attr sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 05/26] rocker: use swdev get/set attr for bridge port flags sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 06/26] switchdev: introduce swdev add/del obj ops sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 07/26] switchdev: add port vlan obj sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 08/26] rocker: use swdev add/del obj for bridge port vlans sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 09/26] switchdev: add new swdev bridge setlink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 10/26] rocker: cut over to new swdev_port_bridge_setlink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 11/26] bonding: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 12/26] team: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 13/26] switchdev: remove old netdev_switch_port_bridge_setlink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 14/26] switchdev: add new swdev_port_bridge_dellink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 15/26] rocker: cut over to " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 16/26] bonding: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 17/26] team: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 18/26] switchdev: remove unused netdev_switch_port_bridge_dellink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 19/26] switchdev: add new swdev_port_bridge_getlink sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 20/26] rocker: cut over to " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 21/26] bonding: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 22/26] team: " sfeldma
2015-04-01 10:07 ` [PATCH net-next v2 23/26] switchdev: rename netdev_switch_fib_* to swdev_fib_* sfeldma
2015-04-01 10:08 ` [PATCH net-next v2 24/26] switchdev: rename netdev_switch_notifier_* to swdev_notifier_* sfeldma
2015-04-01 10:08 ` [PATCH net-next v2 25/26] switchdev: convert swdev_fib_ipv4_add/del over to swdev_port_obj_add/del sfeldma
2015-04-01 11:47 ` Jiri Pirko
2015-04-01 15:05 ` roopa
2015-04-01 16:05 ` Jiri Pirko
2015-04-03 18:00 ` Florian Fainelli
2015-04-06 21:56 ` Scott Feldman
2015-04-01 10:08 ` [PATCH net-next v2 26/26] switchdev: bring documentation up-to-date sfeldma
2015-04-01 11:40 ` [PATCH net-next v2 00/26] switchdev: spring cleanup Jiri Pirko
2015-04-01 18:02 ` Scott Feldman
2015-04-02 6:06 ` Jiri Pirko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1427882882-2533-2-git-send-email-sfeldma@gmail.com \
--to=sfeldma@gmail.com \
--cc=f.fainelli@gmail.com \
--cc=jiri@resnulli.us \
--cc=linux@roeck-us.net \
--cc=netdev@vger.kernel.org \
--cc=ronen.arad@intel.com \
--cc=roopa@cumulusnetworks.com \
--cc=sridhar.samudrala@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).