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 <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Roopa Prabhu 2015-01-29 22:40:13 -08:00 committed by David S. Miller
parent add511b382
commit 8a44dbb202
2 changed files with 146 additions and 1 deletions

View File

@ -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_ */

View File

@ -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);