diff options
author | David S. Miller <[email protected]> | 2018-07-11 23:10:20 -0700 |
---|---|---|
committer | David S. Miller <[email protected]> | 2018-07-11 23:10:20 -0700 |
commit | d90a5215c8ff7f665336d404a56f26c320b9dd73 (patch) | |
tree | 65612105eca58cee46fa24ce4f5bee81ef05984b | |
parent | 80fd2d6ca5461b2752744df2e6e387cc65e7b86c (diff) | |
parent | b5de82f3dfbebc2d1b6db72c68f119a1e0427ca8 (diff) |
Merge branch 'mlxsw-ERSPAN-Take-LACP-state-into-consideration'
Ido Schimmel says:
====================
mlxsw: ERSPAN: Take LACP state into consideration
Petr says:
When offloading mirror-to-gretap, mlxsw needs to preroute the path that
the encapsulated packet will take. That path may include a LAG device
above a front panel port. So far, mlxsw resolved the path to the first
up front panel slave of the LAG interface, but that only reflects
administrative state of the port. It neglects to consider whether the
port actually has a carrier, and what the LACP state is. This patch set
aims to address these problems.
Patch #1 publishes team_port_get_rcu().
Then in patch #2, a new function is introduced,
mlxsw_sp_port_dev_check(). That returns, for a given netdevice that is a
slave of a LAG device, whether that device is "txable", i.e. whether the
LAG master would send traffic through it. Since there's no good place to
put LAG-wide helpers, introduce a new header include/net/lag.h.
Finally in patch #3, fix the slave selection logic to take into
consideration whether a given slave has a carrier and whether it is
txable.
====================
Signed-off-by: David S. Miller <[email protected]>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 5 | ||||
-rw-r--r-- | drivers/net/team/team.c | 5 | ||||
-rw-r--r-- | include/linux/if_team.h | 18 | ||||
-rw-r--r-- | include/net/bonding.h | 13 | ||||
-rw-r--r-- | include/net/lag.h | 17 |
5 files changed, 52 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index 3d187d88cc7c..e42d640cddab 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -36,6 +36,7 @@ #include <linux/list.h> #include <net/arp.h> #include <net/gre.h> +#include <net/lag.h> #include <net/ndisc.h> #include <net/ip6_tunnel.h> @@ -254,7 +255,9 @@ mlxsw_sp_span_entry_lag(struct net_device *lag_dev) struct list_head *iter; netdev_for_each_lower_dev(lag_dev, dev, iter) - if ((dev->flags & IFF_UP) && mlxsw_sp_port_dev_check(dev)) + if (netif_carrier_ok(dev) && + net_lag_port_dev_txable(dev) && + mlxsw_sp_port_dev_check(dev)) return dev; return NULL; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 3a95eaae0c98..6a047d30e8c6 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -41,11 +41,6 @@ #define team_port_exists(dev) (dev->priv_flags & IFF_TEAM_PORT) -static struct team_port *team_port_get_rcu(const struct net_device *dev) -{ - return rcu_dereference(dev->rx_handler_data); -} - static struct team_port *team_port_get_rtnl(const struct net_device *dev) { struct team_port *port = rtnl_dereference(dev->rx_handler_data); diff --git a/include/linux/if_team.h b/include/linux/if_team.h index d95cae09dea0..ac42da56f7a2 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -74,6 +74,11 @@ struct team_port { long mode_priv[0]; }; +static inline struct team_port *team_port_get_rcu(const struct net_device *dev) +{ + return rcu_dereference(dev->rx_handler_data); +} + static inline bool team_port_enabled(struct team_port *port) { return port->index != -1; @@ -84,6 +89,19 @@ static inline bool team_port_txable(struct team_port *port) return port->linkup && team_port_enabled(port); } +static inline bool team_port_dev_txable(const struct net_device *port_dev) +{ + struct team_port *port; + bool txable; + + rcu_read_lock(); + port = team_port_get_rcu(port_dev); + txable = port ? team_port_txable(port) : false; + rcu_read_unlock(); + + return txable; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static inline void team_netpoll_send_skb(struct team_port *port, struct sk_buff *skb) diff --git a/include/net/bonding.h b/include/net/bonding.h index 808f1d167349..a2d058170ea3 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -411,6 +411,19 @@ static inline bool bond_slave_can_tx(struct slave *slave) bond_is_active_slave(slave); } +static inline bool bond_is_active_slave_dev(const struct net_device *slave_dev) +{ + struct slave *slave; + bool active; + + rcu_read_lock(); + slave = bond_slave_get_rcu(slave_dev); + active = bond_is_active_slave(slave); + rcu_read_unlock(); + + return active; +} + static inline void bond_hw_addr_copy(u8 *dst, const u8 *src, unsigned int len) { if (len == ETH_ALEN) { diff --git a/include/net/lag.h b/include/net/lag.h new file mode 100644 index 000000000000..95b880e6fdde --- /dev/null +++ b/include/net/lag.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_IF_LAG_H +#define _LINUX_IF_LAG_H + +#include <linux/netdevice.h> +#include <linux/if_team.h> +#include <net/bonding.h> + +static inline bool net_lag_port_dev_txable(const struct net_device *port_dev) +{ + if (netif_is_team_port(port_dev)) + return team_port_dev_txable(port_dev); + else + return bond_is_active_slave_dev(port_dev); +} + +#endif /* _LINUX_IF_LAG_H */ |