net: dsa: propagate extack to .port_vlan_add

Allow drivers to communicate their restrictions to user space directly,
instead of printing to the kernel log. Where the conversion would have
been lossy and things like VLAN ID could no longer be conveyed (due to
the lack of support for printf format specifier in netlink extack), I
chose to keep the messages in full form to the kernel log only, and
leave it up to individual driver maintainers to move more messages to
extack.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vladimir Oltean 2021-02-13 22:43:18 +02:00 committed by David S. Miller
parent dcbdf1350e
commit 31046a5fd9
20 changed files with 79 additions and 37 deletions

View File

@ -1444,7 +1444,8 @@ static int b53_vlan_prepare(struct dsa_switch *ds, int port,
}
int b53_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct b53_device *dev = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;

View File

@ -348,7 +348,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
bool tx_pause, bool rx_pause);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
int b53_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int b53_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
int b53_fdb_add(struct dsa_switch *ds, int port,

View File

@ -891,7 +891,7 @@ static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
else
vlan.flags = 0;
ret = ds->ops->port_vlan_add(ds, port_num, &vlan);
ret = ds->ops->port_vlan_add(ds, port_num, &vlan, NULL);
if (ret)
return ret;
}

View File

@ -199,7 +199,8 @@ static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;

View File

@ -341,7 +341,8 @@ static u16 hellcreek_private_vid(int port)
}
static int hellcreek_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct hellcreek *hellcreek = ds->priv;
int i;
@ -358,8 +359,10 @@ static int hellcreek_vlan_prepare(struct dsa_switch *ds, int port,
if (!dsa_is_user_port(ds, i))
continue;
if (vlan->vid == restricted_vid)
if (vlan->vid == restricted_vid) {
NL_SET_ERR_MSG_MOD(extack, "VID restricted by driver");
return -EBUSY;
}
}
return 0;
@ -445,14 +448,15 @@ static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port,
}
static int hellcreek_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
struct hellcreek *hellcreek = ds->priv;
int err;
err = hellcreek_vlan_prepare(ds, port, vlan);
err = hellcreek_vlan_prepare(ds, port, vlan, extack);
if (err)
return err;

View File

@ -1128,7 +1128,8 @@ static void gswip_port_bridge_leave(struct dsa_switch *ds, int port,
}
static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct gswip_priv *priv = ds->priv;
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
@ -1163,15 +1164,18 @@ static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
}
}
if (idx == -1)
if (idx == -1) {
NL_SET_ERR_MSG_MOD(extack, "No slot in VLAN table");
return -ENOSPC;
}
}
return 0;
}
static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct gswip_priv *priv = ds->priv;
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
@ -1179,7 +1183,7 @@ static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
int err;
err = gswip_port_vlan_prepare(ds, port, vlan);
err = gswip_port_vlan_prepare(ds, port, vlan, extack);
if (err)
return err;

View File

@ -793,7 +793,8 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
struct ksz_device *dev = ds->priv;

View File

@ -511,7 +511,8 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
u32 vlan_table[3];
@ -520,7 +521,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
err = ksz9477_get_vlan_table(dev, vlan->vid, vlan_table);
if (err) {
dev_dbg(dev->dev, "Failed to get vlan table\n");
NL_SET_ERR_MSG_MOD(extack, "Failed to get vlan table");
return err;
}
@ -535,7 +536,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
err = ksz9477_set_vlan_table(dev, vlan->vid, vlan_table);
if (err) {
dev_dbg(dev->dev, "Failed to set vlan table\n");
NL_SET_ERR_MSG_MOD(extack, "Failed to set vlan table");
return err;
}

View File

@ -1483,7 +1483,8 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
static int
mt7530_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;

View File

@ -1982,7 +1982,8 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
}
static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct mv88e6xxx_chip *chip = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;

View File

@ -789,7 +789,8 @@ static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
}
static int felix_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct ocelot *ocelot = ds->priv;
u16 flags = vlan->flags;

View File

@ -1313,7 +1313,8 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
static int
qca8k_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;

View File

@ -133,7 +133,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi);
int rtl8366_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering);
int rtl8366_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int rtl8366_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,

View File

@ -375,7 +375,8 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
int rtl8366_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
@ -384,16 +385,20 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
u32 untag = 0;
int ret;
if (!smi->ops->is_vlan_valid(smi, vlan->vid))
if (!smi->ops->is_vlan_valid(smi, vlan->vid)) {
NL_SET_ERR_MSG_MOD(extack, "VLAN ID not valid");
return -EINVAL;
}
/* Enable VLAN in the hardware
* FIXME: what's with this 4k business?
* Just rtl8366_enable_vlan() seems inconclusive.
*/
ret = rtl8366_enable_vlan4k(smi, true);
if (ret)
if (ret) {
NL_SET_ERR_MSG_MOD(extack, "Failed to enable VLAN 4K");
return ret;
}
dev_info(smi->dev, "add VLAN %d on port %d, %s, %s\n",
vlan->vid, port, untagged ? "untagged" : "tagged",

View File

@ -2795,7 +2795,8 @@ static int sja1105_vlan_del_one(struct dsa_switch *ds, int port, u16 vid,
}
static int sja1105_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct sja1105_private *priv = ds->priv;
bool vlan_table_changed = false;
@ -2807,7 +2808,8 @@ static int sja1105_vlan_add(struct dsa_switch *ds, int port,
*/
if (priv->vlan_state != SJA1105_VLAN_FILTERING_FULL &&
vid_is_dsa_8021q(vlan->vid)) {
dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n");
NL_SET_ERR_MSG_MOD(extack,
"Range 1024-3071 reserved for dsa_8021q operation");
return -EBUSY;
}

View File

@ -643,7 +643,8 @@ struct dsa_switch_ops {
int (*port_vlan_filtering)(struct dsa_switch *ds, int port,
bool vlan_filtering);
int (*port_vlan_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int (*port_vlan_del)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
/*

View File

@ -75,6 +75,7 @@ struct dsa_notifier_vlan_info {
const struct switchdev_obj_port_vlan *vlan;
int sw_index;
int port;
struct netlink_ext_ack *extack;
};
/* DSA_NOTIFIER_MTU */
@ -192,7 +193,8 @@ int dsa_port_bridge_flags(const struct dsa_port *dp,
int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
struct netlink_ext_ack *extack);
int dsa_port_vlan_add(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int dsa_port_vlan_del(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan);
int dsa_port_link_register_of(struct dsa_port *dp);

View File

@ -535,12 +535,14 @@ int dsa_port_mdb_del(const struct dsa_port *dp,
}
int dsa_port_vlan_add(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct dsa_notifier_vlan_info info = {
.sw_index = dp->ds->index,
.port = dp->index,
.vlan = vlan,
.extack = extack,
};
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);

View File

@ -357,11 +357,14 @@ static int dsa_slave_vlan_add(struct net_device *dev,
rcu_read_lock();
err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
rcu_read_unlock();
if (err)
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Port already has a VLAN upper with this VID");
return err;
}
}
err = dsa_port_vlan_add(dp, &vlan);
err = dsa_port_vlan_add(dp, &vlan, extack);
if (err)
return err;
@ -371,7 +374,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
*/
vlan.flags &= ~BRIDGE_VLAN_INFO_PVID;
err = dsa_port_vlan_add(dp->cpu_dp, &vlan);
err = dsa_port_vlan_add(dp->cpu_dp, &vlan, extack);
if (err)
return err;
@ -1287,17 +1290,25 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
/* This API only allows programming tagged, non-PVID VIDs */
.flags = 0,
};
struct netlink_ext_ack extack = {0};
int ret;
/* User port... */
ret = dsa_port_vlan_add(dp, &vlan);
if (ret)
ret = dsa_port_vlan_add(dp, &vlan, &extack);
if (ret) {
if (extack._msg)
netdev_err(dev, "%s\n", extack._msg);
return ret;
}
/* And CPU port... */
ret = dsa_port_vlan_add(dp->cpu_dp, &vlan);
if (ret)
ret = dsa_port_vlan_add(dp->cpu_dp, &vlan, &extack);
if (ret) {
if (extack._msg)
netdev_err(dev, "CPU port %d: %s\n", dp->cpu_dp->index,
extack._msg);
return ret;
}
return vlan_vid_add(master, proto, vid);
}

View File

@ -291,7 +291,8 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_vlan_match(ds, port, info)) {
err = ds->ops->port_vlan_add(ds, port, info->vlan);
err = ds->ops->port_vlan_add(ds, port, info->vlan,
info->extack);
if (err)
return err;
}