From 03bf0c281234028388108d0aee720954f5fe6924 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Jan 2015 23:49:36 +0100 Subject: switchdev: introduce switchdev notifier This patch introduces new notifier for purposes of exposing events which happen on switch driver side. The consumers of the event messages are mainly involved masters, namely bridge and ovs. Suggested-by: Thomas Graf Signed-off-by: Jiri Pirko Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index d162b21b14bd..22e02f4edd99 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -50,3 +52,66 @@ int netdev_switch_port_stp_update(struct net_device *dev, u8 state) return ops->ndo_switch_port_stp_update(dev, state); } EXPORT_SYMBOL(netdev_switch_port_stp_update); + +static DEFINE_MUTEX(netdev_switch_mutex); +static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain); + +/** + * register_netdev_switch_notifier - Register nofifier + * @nb: notifier_block + * + * Register switch device notifier. This should be used by code + * which needs to monitor events happening in particular device. + * Return values are same as for atomic_notifier_chain_register(). + */ +int register_netdev_switch_notifier(struct notifier_block *nb) +{ + int err; + + mutex_lock(&netdev_switch_mutex); + err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb); + mutex_unlock(&netdev_switch_mutex); + return err; +} +EXPORT_SYMBOL(register_netdev_switch_notifier); + +/** + * unregister_netdev_switch_notifier - Unregister nofifier + * @nb: notifier_block + * + * Unregister switch device notifier. + * Return values are same as for atomic_notifier_chain_unregister(). + */ +int unregister_netdev_switch_notifier(struct notifier_block *nb) +{ + int err; + + mutex_lock(&netdev_switch_mutex); + err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb); + mutex_unlock(&netdev_switch_mutex); + return err; +} +EXPORT_SYMBOL(unregister_netdev_switch_notifier); + +/** + * call_netdev_switch_notifiers - Call nofifiers + * @val: value passed unmodified to notifier function + * @dev: port device + * @info: notifier information data + * + * Call all network notifier blocks. This should be called by driver + * when it needs to propagate hardware event. + * Return values are same as for atomic_notifier_call_chain(). + */ +int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev, + struct netdev_switch_notifier_info *info) +{ + int err; + + info->dev = dev; + mutex_lock(&netdev_switch_mutex); + err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info); + mutex_unlock(&netdev_switch_mutex); + return err; +} +EXPORT_SYMBOL(call_netdev_switch_notifiers); -- cgit v1.2.3 From 8a44dbb202617aa66968ba74fdabf1b654dfe661 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Thu, 29 Jan 2015 22:40:13 -0800 Subject: swdevice: add new apis to set and del bridge port attributes This patch adds two new api's netdev_switch_port_bridge_setlink and netdev_switch_port_bridge_dellink to offload bridge port attributes to switch port (The names of the apis look odd with 'switch_port_bridge', but am more inclined to change the prefix of the api to something else. Will take any suggestions). The api's look at the NETIF_F_HW_SWITCH_OFFLOAD feature flag to pass bridge port attributes to the port device. Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller --- include/net/switchdev.h | 37 +++++++++++++++- net/switchdev/switchdev.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 1 deletion(-) (limited to 'net/switchdev/switchdev.c') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 205e63698da9..cfcdac2e5d25 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -43,7 +43,14 @@ int register_netdev_switch_notifier(struct notifier_block *nb); int unregister_netdev_switch_notifier(struct notifier_block *nb); int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev, struct netdev_switch_notifier_info *info); - +int netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags); +int netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags); +int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags); +int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags); #else static inline int netdev_switch_parent_id_get(struct net_device *dev, @@ -74,6 +81,34 @@ static inline int call_netdev_switch_notifiers(unsigned long val, struct net_dev return NOTIFY_DONE; } +static inline int netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags) +{ + return -EOPNOTSUPP; +} + +static inline int netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags) +{ + return -EOPNOTSUPP; +} + +static inline int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags) +{ + return 0; +} + +static inline int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags) +{ + return 0; +} + #endif #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 22e02f4edd99..8c1e558db118 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -115,3 +115,113 @@ int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev, return err; } EXPORT_SYMBOL(call_netdev_switch_notifiers); + +/** + * netdev_switch_port_bridge_setlink - Notify switch device port of bridge + * port attributes + * + * @dev: port device + * @nlh: netlink msg with bridge port attributes + * @flags: bridge setlink flags + * + * Notify switch device port of bridge port attributes + */ +int netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags) +{ + const struct net_device_ops *ops = dev->netdev_ops; + + if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) + return 0; + + if (!ops->ndo_bridge_setlink) + return -EOPNOTSUPP; + + return ops->ndo_bridge_setlink(dev, nlh, flags); +} +EXPORT_SYMBOL(netdev_switch_port_bridge_setlink); + +/** + * netdev_switch_port_bridge_dellink - Notify switch device port of bridge + * port attribute delete + * + * @dev: port device + * @nlh: netlink msg with bridge port attributes + * @flags: bridge setlink flags + * + * Notify switch device port of bridge port attribute delete + */ +int netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags) +{ + const struct net_device_ops *ops = dev->netdev_ops; + + if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) + return 0; + + if (!ops->ndo_bridge_dellink) + return -EOPNOTSUPP; + + return ops->ndo_bridge_dellink(dev, nlh, flags); +} +EXPORT_SYMBOL(netdev_switch_port_bridge_dellink); + +/** + * ndo_dflt_netdev_switch_port_bridge_setlink - default ndo bridge setlink + * op for master devices + * + * @dev: port device + * @nlh: netlink msg with bridge port attributes + * @flags: bridge setlink flags + * + * Notify master device slaves of bridge port attributes + */ +int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags) +{ + struct net_device *lower_dev; + struct list_head *iter; + int ret = 0, err = 0; + + if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) + return ret; + + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = netdev_switch_port_bridge_setlink(lower_dev, nlh, flags); + if (err && err != -EOPNOTSUPP) + ret = err; + } + + return ret; +} +EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_setlink); + +/** + * ndo_dflt_netdev_switch_port_bridge_dellink - default ndo bridge dellink + * op for master devices + * + * @dev: port device + * @nlh: netlink msg with bridge port attributes + * @flags: bridge dellink flags + * + * Notify master device slaves of bridge port attribute deletes + */ +int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev, + struct nlmsghdr *nlh, u16 flags) +{ + struct net_device *lower_dev; + struct list_head *iter; + int ret = 0, err = 0; + + if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD)) + return ret; + + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = netdev_switch_port_bridge_dellink(lower_dev, nlh, flags); + if (err && err != -EOPNOTSUPP) + ret = err; + } + + return ret; +} +EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_dellink); -- cgit v1.2.3