forked from Minki/linux
net: bridge: move DSA master bridging restriction to DSA
When DSA gains support for multiple CPU ports in a LAG, it will become mandatory to monitor the changeupper events for the DSA master. In fact, there are already some restrictions to be imposed in that area, namely that a DSA master cannot be a bridge port except in some special circumstances. Centralize the restrictions at the level of the DSA layer as a preliminary step. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
0498277ee1
commit
920a33cd72
@ -568,26 +568,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
|
||||
!is_valid_ether_addr(dev->dev_addr))
|
||||
return -EINVAL;
|
||||
|
||||
/* Also don't allow bridging of net devices that are DSA masters, since
|
||||
* the bridge layer rx_handler prevents the DSA fake ethertype handler
|
||||
* to be invoked, so we don't get the chance to strip off and parse the
|
||||
* DSA switch tag protocol header (the bridge layer just returns
|
||||
* RX_HANDLER_CONSUMED, stopping RX processing for these frames).
|
||||
* The only case where that would not be an issue is when bridging can
|
||||
* already be offloaded, such as when the DSA master is itself a DSA
|
||||
* or plain switchdev port, and is bridged only with other ports from
|
||||
* the same hardware device.
|
||||
*/
|
||||
if (netdev_uses_dsa(dev)) {
|
||||
list_for_each_entry(p, &br->port_list, list) {
|
||||
if (!netdev_port_same_parent_id(dev, p->dev)) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Cannot do software bridging with a DSA master");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No bridging of bridges */
|
||||
if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
|
@ -2699,6 +2699,46 @@ dsa_slave_prechangeupper_sanity_check(struct net_device *dev,
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/* Don't allow bridging of DSA masters, since the bridge layer rx_handler
|
||||
* prevents the DSA fake ethertype handler to be invoked, so we don't get the
|
||||
* chance to strip off and parse the DSA switch tag protocol header (the bridge
|
||||
* layer just returns RX_HANDLER_CONSUMED, stopping RX processing for these
|
||||
* frames).
|
||||
* The only case where that would not be an issue is when bridging can already
|
||||
* be offloaded, such as when the DSA master is itself a DSA or plain switchdev
|
||||
* port, and is bridged only with other ports from the same hardware device.
|
||||
*/
|
||||
static int
|
||||
dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower,
|
||||
struct netdev_notifier_changeupper_info *info)
|
||||
{
|
||||
struct net_device *br = info->upper_dev;
|
||||
struct netlink_ext_ack *extack;
|
||||
struct net_device *lower;
|
||||
struct list_head *iter;
|
||||
|
||||
if (!netif_is_bridge_master(br))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (!info->linking)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
extack = netdev_notifier_info_to_extack(&info->info);
|
||||
|
||||
netdev_for_each_lower_dev(br, lower, iter) {
|
||||
if (!netdev_uses_dsa(new_lower) && !netdev_uses_dsa(lower))
|
||||
continue;
|
||||
|
||||
if (!netdev_port_same_parent_id(lower, new_lower)) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Cannot do software bridging with a DSA master");
|
||||
return notifier_from_errno(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int dsa_slave_netdevice_event(struct notifier_block *nb,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
@ -2713,6 +2753,10 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
|
||||
if (notifier_to_errno(err))
|
||||
return err;
|
||||
|
||||
err = dsa_bridge_prechangelower_sanity_check(dev, info);
|
||||
if (notifier_to_errno(err))
|
||||
return err;
|
||||
|
||||
err = dsa_slave_prechangeupper(dev, ptr);
|
||||
if (notifier_to_errno(err))
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user