mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-26 16:41:25 +00:00
net: bridge: offload all port flags at once in br_setport
If for example this command: ip link set swp0 type bridge_slave flood off mcast_flood off learning off succeeded at configuring BR_FLOOD and BR_MCAST_FLOOD but not at BR_LEARNING, there would be no attempt to revert the partial state in any way. Arguably, if the user changes more than one flag through the same netlink command, this one _should_ be all or nothing, which means it should be passed through switchdev as all or nothing. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4c08c586ff
commit
304ae3bf1c
2 changed files with 36 additions and 73 deletions
|
@ -853,87 +853,58 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set/clear or port flags based on attribute */
|
/* Set/clear or port flags based on attribute */
|
||||||
static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
|
static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
|
||||||
int attrtype, unsigned long mask)
|
int attrtype, unsigned long mask)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!tb[attrtype])
|
if (!tb[attrtype])
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (nla_get_u8(tb[attrtype]))
|
if (nla_get_u8(tb[attrtype]))
|
||||||
flags = p->flags | mask;
|
p->flags |= mask;
|
||||||
else
|
else
|
||||||
flags = p->flags & ~mask;
|
p->flags &= ~mask;
|
||||||
|
|
||||||
err = br_switchdev_set_port_flag(p, flags, mask);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
p->flags = flags;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process bridge protocol info on port */
|
/* Process bridge protocol info on port */
|
||||||
static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
||||||
{
|
{
|
||||||
unsigned long old_flags = p->flags;
|
unsigned long old_flags, changed_mask;
|
||||||
bool br_vlan_tunnel_old = false;
|
bool br_vlan_tunnel_old;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
|
old_flags = p->flags;
|
||||||
if (err)
|
br_vlan_tunnel_old = (old_flags & BR_VLAN_TUNNEL) ? true : false;
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
|
br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
|
||||||
if (err)
|
br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
|
||||||
return err;
|
br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE,
|
||||||
|
BR_MULTICAST_FAST_LEAVE);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST,
|
||||||
|
BR_MULTICAST_TO_UNICAST);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS);
|
||||||
|
br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED);
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
|
changed_mask = old_flags ^ p->flags;
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
|
err = br_switchdev_set_port_flag(p, p->flags, changed_mask);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
p->flags = old_flags;
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false;
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
|
|
||||||
if (err)
|
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
|
if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
|
||||||
nbp_vlan_tunnel_info_flush(p);
|
nbp_vlan_tunnel_info_flush(p);
|
||||||
|
|
||||||
|
br_port_flags_change(p, changed_mask);
|
||||||
|
|
||||||
if (tb[IFLA_BRPORT_COST]) {
|
if (tb[IFLA_BRPORT_COST]) {
|
||||||
err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
|
err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -982,15 +953,6 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
||||||
p->group_fwd_mask = fwd_mask;
|
p->group_fwd_mask = fwd_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS,
|
|
||||||
BR_NEIGH_SUPPRESS);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (tb[IFLA_BRPORT_BACKUP_PORT]) {
|
if (tb[IFLA_BRPORT_BACKUP_PORT]) {
|
||||||
struct net_device *backup_dev = NULL;
|
struct net_device *backup_dev = NULL;
|
||||||
u32 backup_ifindex;
|
u32 backup_ifindex;
|
||||||
|
@ -1008,7 +970,6 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
br_port_flags_change(p, old_flags ^ p->flags);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,16 +65,18 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
|
||||||
struct switchdev_attr attr = {
|
struct switchdev_attr attr = {
|
||||||
.orig_dev = p->dev,
|
.orig_dev = p->dev,
|
||||||
.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
|
.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
|
||||||
.u.brport_flags = mask,
|
|
||||||
};
|
};
|
||||||
struct switchdev_notifier_port_attr_info info = {
|
struct switchdev_notifier_port_attr_info info = {
|
||||||
.attr = &attr,
|
.attr = &attr,
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
|
mask &= BR_PORT_FLAGS_HW_OFFLOAD;
|
||||||
|
if (!mask)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
attr.u.brport_flags = mask;
|
||||||
|
|
||||||
/* We run from atomic context here */
|
/* We run from atomic context here */
|
||||||
err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
|
err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
|
||||||
&info.info, NULL);
|
&info.info, NULL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue