diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2021-02-13 23:43:16 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-02-15 04:38:11 +0300 |
commit | 9e781401cbfcd83c4d766b4c6c5efce8348d4d13 (patch) | |
tree | f160bbe6e715476a92b6c611acfc06ba77f17aa3 /net/bridge | |
parent | 7a572964e0c454b0ead57174c964bd7a2d498455 (diff) | |
download | linux-9e781401cbfcd83c4d766b4c6c5efce8348d4d13.tar.xz |
net: bridge: propagate extack through store_bridge_parm
The bridge sysfs interface stores parameters for the STP, VLAN,
multicast etc subsystems using a predefined function prototype.
Sometimes the underlying function being called supports a netlink
extended ack message, and we ignore it.
Let's expand the store_bridge_parm function prototype to include the
extack, and just print it to console, but at least propagate it where
applicable. Where not applicable, create a shim function in the
br_sysfs_br.c file that discards the extra function argument.
This patch allows us to propagate the extack argument to
br_vlan_set_default_pvid, br_vlan_set_proto and br_vlan_filter_toggle,
and from there, further up in br_changelink from br_netlink.c.
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>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_netlink.c | 2 | ||||
-rw-r--r-- | net/bridge/br_private.h | 9 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 166 | ||||
-rw-r--r-- | net/bridge/br_vlan.c | 11 |
4 files changed, 142 insertions, 46 deletions
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index a12bbbdacb9b..3f5dc6fcc980 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1212,7 +1212,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], if (data[IFLA_BR_VLAN_FILTERING]) { u8 vlan_filter = nla_get_u8(data[IFLA_BR_VLAN_FILTERING]); - err = br_vlan_filter_toggle(br, vlan_filter); + err = br_vlan_filter_toggle(br, vlan_filter, extack); if (err) return err; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0281de20212e..a8d483325476 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1085,13 +1085,16 @@ int br_vlan_delete(struct net_bridge *br, u16 vid); void br_vlan_flush(struct net_bridge *br); struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid); void br_recalculate_fwd_mask(struct net_bridge *br); -int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); +int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack); int __br_vlan_set_proto(struct net_bridge *br, __be16 proto); -int br_vlan_set_proto(struct net_bridge *br, unsigned long val); +int br_vlan_set_proto(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack); int br_vlan_set_stats(struct net_bridge *br, unsigned long val); int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val); int br_vlan_init(struct net_bridge *br); -int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val); +int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack); int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, struct netlink_ext_ack *extack); int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 71f0f671c4ef..072e29840082 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -30,11 +30,13 @@ */ static ssize_t store_bridge_parm(struct device *d, const char *buf, size_t len, - int (*set)(struct net_bridge *, unsigned long)) + int (*set)(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack)) { struct net_bridge *br = to_bridge(d); - char *endp; + struct netlink_ext_ack extack = {0}; unsigned long val; + char *endp; int err; if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) @@ -47,9 +49,15 @@ static ssize_t store_bridge_parm(struct device *d, if (!rtnl_trylock()) return restart_syscall(); - err = (*set)(br, val); + err = (*set)(br, val, &extack); if (!err) netdev_state_change(br->dev); + if (extack._msg) { + if (err) + br_err(br, "%s\n", extack._msg); + else + br_warn(br, "%s\n", extack._msg); + } rtnl_unlock(); return err ? err : len; @@ -63,11 +71,17 @@ static ssize_t forward_delay_show(struct device *d, return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); } +static int set_forward_delay(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_set_forward_delay(br, val); +} + static ssize_t forward_delay_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_set_forward_delay); + return store_bridge_parm(d, buf, len, set_forward_delay); } static DEVICE_ATTR_RW(forward_delay); @@ -78,11 +92,17 @@ static ssize_t hello_time_show(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->hello_time)); } +static int set_hello_time(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_set_hello_time(br, val); +} + static ssize_t hello_time_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_set_hello_time); + return store_bridge_parm(d, buf, len, set_hello_time); } static DEVICE_ATTR_RW(hello_time); @@ -93,10 +113,16 @@ static ssize_t max_age_show(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->max_age)); } +static int set_max_age(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_set_max_age(br, val); +} + static ssize_t max_age_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_set_max_age); + return store_bridge_parm(d, buf, len, set_max_age); } static DEVICE_ATTR_RW(max_age); @@ -107,7 +133,8 @@ static ssize_t ageing_time_show(struct device *d, return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); } -static int set_ageing_time(struct net_bridge *br, unsigned long val) +static int set_ageing_time(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { return br_set_ageing_time(br, val); } @@ -128,9 +155,10 @@ static ssize_t stp_state_show(struct device *d, } -static int set_stp_state(struct net_bridge *br, unsigned long val) +static int set_stp_state(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { - return br_stp_set_enabled(br, val, NULL); + return br_stp_set_enabled(br, val, extack); } static ssize_t stp_state_store(struct device *d, @@ -149,7 +177,8 @@ static ssize_t group_fwd_mask_show(struct device *d, return sprintf(buf, "%#x\n", br->group_fwd_mask); } -static int set_group_fwd_mask(struct net_bridge *br, unsigned long val) +static int set_group_fwd_mask(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { if (val & BR_GROUPFWD_RESTRICTED) return -EINVAL; @@ -176,7 +205,8 @@ static ssize_t priority_show(struct device *d, struct device_attribute *attr, (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); } -static int set_priority(struct net_bridge *br, unsigned long val) +static int set_priority(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_stp_set_bridge_priority(br, (u16) val); return 0; @@ -312,7 +342,8 @@ static ssize_t group_addr_store(struct device *d, static DEVICE_ATTR_RW(group_addr); -static int set_flush(struct net_bridge *br, unsigned long val) +static int set_flush(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_fdb_flush(br); return 0; @@ -334,9 +365,10 @@ static ssize_t no_linklocal_learn_show(struct device *d, return sprintf(buf, "%d\n", br_boolopt_get(br, BR_BOOLOPT_NO_LL_LEARN)); } -static int set_no_linklocal_learn(struct net_bridge *br, unsigned long val) +static int set_no_linklocal_learn(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { - return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val, NULL); + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val, extack); } static ssize_t no_linklocal_learn_store(struct device *d, @@ -355,11 +387,17 @@ static ssize_t multicast_router_show(struct device *d, return sprintf(buf, "%d\n", br->multicast_router); } +static int set_multicast_router(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_multicast_set_router(br, val); +} + static ssize_t multicast_router_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_multicast_set_router); + return store_bridge_parm(d, buf, len, set_multicast_router); } static DEVICE_ATTR_RW(multicast_router); @@ -371,11 +409,17 @@ static ssize_t multicast_snooping_show(struct device *d, return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_ENABLED)); } +static int toggle_multicast(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_multicast_toggle(br, val); +} + static ssize_t multicast_snooping_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_multicast_toggle); + return store_bridge_parm(d, buf, len, toggle_multicast); } static DEVICE_ATTR_RW(multicast_snooping); @@ -388,7 +432,8 @@ static ssize_t multicast_query_use_ifaddr_show(struct device *d, br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR)); } -static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val) +static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_opt_toggle(br, BROPT_MULTICAST_QUERY_USE_IFADDR, !!val); return 0; @@ -411,11 +456,17 @@ static ssize_t multicast_querier_show(struct device *d, return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_QUERIER)); } +static int set_multicast_querier(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_multicast_set_querier(br, val); +} + static ssize_t multicast_querier_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_multicast_set_querier); + return store_bridge_parm(d, buf, len, set_multicast_querier); } static DEVICE_ATTR_RW(multicast_querier); @@ -425,10 +476,12 @@ static ssize_t hash_elasticity_show(struct device *d, return sprintf(buf, "%u\n", RHT_ELASTICITY); } -static int set_elasticity(struct net_bridge *br, unsigned long val) +static int set_elasticity(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { - br_warn(br, "the hash_elasticity option has been deprecated and is always %u\n", - RHT_ELASTICITY); + /* 16 is RHT_ELASTICITY */ + NL_SET_ERR_MSG_MOD(extack, + "the hash_elasticity option has been deprecated and is always 16"); return 0; } @@ -447,7 +500,8 @@ static ssize_t hash_max_show(struct device *d, struct device_attribute *attr, return sprintf(buf, "%u\n", br->hash_max); } -static int set_hash_max(struct net_bridge *br, unsigned long val) +static int set_hash_max(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->hash_max = val; return 0; @@ -469,11 +523,17 @@ static ssize_t multicast_igmp_version_show(struct device *d, return sprintf(buf, "%u\n", br->multicast_igmp_version); } +static int set_multicast_igmp_version(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_multicast_set_igmp_version(br, val); +} + static ssize_t multicast_igmp_version_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_multicast_set_igmp_version); + return store_bridge_parm(d, buf, len, set_multicast_igmp_version); } static DEVICE_ATTR_RW(multicast_igmp_version); @@ -485,7 +545,8 @@ static ssize_t multicast_last_member_count_show(struct device *d, return sprintf(buf, "%u\n", br->multicast_last_member_count); } -static int set_last_member_count(struct net_bridge *br, unsigned long val) +static int set_last_member_count(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_last_member_count = val; return 0; @@ -506,7 +567,8 @@ static ssize_t multicast_startup_query_count_show( return sprintf(buf, "%u\n", br->multicast_startup_query_count); } -static int set_startup_query_count(struct net_bridge *br, unsigned long val) +static int set_startup_query_count(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_startup_query_count = val; return 0; @@ -528,7 +590,8 @@ static ssize_t multicast_last_member_interval_show( jiffies_to_clock_t(br->multicast_last_member_interval)); } -static int set_last_member_interval(struct net_bridge *br, unsigned long val) +static int set_last_member_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_last_member_interval = clock_t_to_jiffies(val); return 0; @@ -550,7 +613,8 @@ static ssize_t multicast_membership_interval_show( jiffies_to_clock_t(br->multicast_membership_interval)); } -static int set_membership_interval(struct net_bridge *br, unsigned long val) +static int set_membership_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_membership_interval = clock_t_to_jiffies(val); return 0; @@ -573,7 +637,8 @@ static ssize_t multicast_querier_interval_show(struct device *d, jiffies_to_clock_t(br->multicast_querier_interval)); } -static int set_querier_interval(struct net_bridge *br, unsigned long val) +static int set_querier_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_querier_interval = clock_t_to_jiffies(val); return 0; @@ -596,7 +661,8 @@ static ssize_t multicast_query_interval_show(struct device *d, jiffies_to_clock_t(br->multicast_query_interval)); } -static int set_query_interval(struct net_bridge *br, unsigned long val) +static int set_query_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_query_interval = clock_t_to_jiffies(val); return 0; @@ -619,7 +685,8 @@ static ssize_t multicast_query_response_interval_show( jiffies_to_clock_t(br->multicast_query_response_interval)); } -static int set_query_response_interval(struct net_bridge *br, unsigned long val) +static int set_query_response_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_query_response_interval = clock_t_to_jiffies(val); return 0; @@ -642,7 +709,8 @@ static ssize_t multicast_startup_query_interval_show( jiffies_to_clock_t(br->multicast_startup_query_interval)); } -static int set_startup_query_interval(struct net_bridge *br, unsigned long val) +static int set_startup_query_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br->multicast_startup_query_interval = clock_t_to_jiffies(val); return 0; @@ -666,7 +734,8 @@ static ssize_t multicast_stats_enabled_show(struct device *d, br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED)); } -static int set_stats_enabled(struct net_bridge *br, unsigned long val) +static int set_stats_enabled(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_opt_toggle(br, BROPT_MULTICAST_STATS_ENABLED, !!val); return 0; @@ -691,11 +760,17 @@ static ssize_t multicast_mld_version_show(struct device *d, return sprintf(buf, "%u\n", br->multicast_mld_version); } +static int set_multicast_mld_version(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_multicast_set_mld_version(br, val); +} + static ssize_t multicast_mld_version_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_multicast_set_mld_version); + return store_bridge_parm(d, buf, len, set_multicast_mld_version); } static DEVICE_ATTR_RW(multicast_mld_version); #endif @@ -708,7 +783,8 @@ static ssize_t nf_call_iptables_show( return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_IPTABLES)); } -static int set_nf_call_iptables(struct net_bridge *br, unsigned long val) +static int set_nf_call_iptables(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_opt_toggle(br, BROPT_NF_CALL_IPTABLES, !!val); return 0; @@ -729,7 +805,8 @@ static ssize_t nf_call_ip6tables_show( return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_IP6TABLES)); } -static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val) +static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_opt_toggle(br, BROPT_NF_CALL_IP6TABLES, !!val); return 0; @@ -750,7 +827,8 @@ static ssize_t nf_call_arptables_show( return sprintf(buf, "%u\n", br_opt_get(br, BROPT_NF_CALL_ARPTABLES)); } -static int set_nf_call_arptables(struct net_bridge *br, unsigned long val) +static int set_nf_call_arptables(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { br_opt_toggle(br, BROPT_NF_CALL_ARPTABLES, !!val); return 0; @@ -821,11 +899,17 @@ static ssize_t vlan_stats_enabled_show(struct device *d, return sprintf(buf, "%u\n", br_opt_get(br, BROPT_VLAN_STATS_ENABLED)); } +static int set_vlan_stats_enabled(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_vlan_set_stats(br, val); +} + static ssize_t vlan_stats_enabled_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_vlan_set_stats); + return store_bridge_parm(d, buf, len, set_vlan_stats_enabled); } static DEVICE_ATTR_RW(vlan_stats_enabled); @@ -837,11 +921,17 @@ static ssize_t vlan_stats_per_port_show(struct device *d, return sprintf(buf, "%u\n", br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)); } +static int set_vlan_stats_per_port(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) +{ + return br_vlan_set_stats_per_port(br, val); +} + static ssize_t vlan_stats_per_port_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, br_vlan_set_stats_per_port); + return store_bridge_parm(d, buf, len, set_vlan_stats_per_port); } static DEVICE_ATTR_RW(vlan_stats_per_port); #endif diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 26e7e06b6a0d..c4a51095850a 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -806,7 +806,8 @@ void br_recalculate_fwd_mask(struct net_bridge *br) ~(1u << br->group_addr[5]); } -int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) +int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { struct switchdev_attr attr = { .orig_dev = br->dev, @@ -910,7 +911,8 @@ err_filt: return err; } -int br_vlan_set_proto(struct net_bridge *br, unsigned long val) +int br_vlan_set_proto(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { if (!eth_type_vlan(htons(val))) return -EPROTONOSUPPORT; @@ -1095,7 +1097,8 @@ err_port: goto out; } -int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) +int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { u16 pvid = val; int err = 0; @@ -1112,7 +1115,7 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) err = -EPERM; goto out; } - err = __br_vlan_set_default_pvid(br, pvid, NULL); + err = __br_vlan_set_default_pvid(br, pvid, extack); out: return err; } |