*/
 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))
        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;
        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);
 
                       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);
 
                       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);
 
        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);
 }
 }
 
 
-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,
        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;
                       (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;
 
 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;
        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,
        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);
 
        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);
 
                       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;
        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);
 
        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;
 }
 
        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;
        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);
 
        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;
        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;
                       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;
                       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;
                       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;
                       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;
                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;
                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;
                       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;
        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
        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;
        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;
        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;
        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);
 
        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