* [PATCH net-next 0/2] net: bridge: add an option to disabe linklocal learning @ 2018-11-22 4:29 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: Nikolay Aleksandrov, andrew, roopa, bridge, davem Hi, This set adds a new bridge option which can control learning from link-local packets, by default learning is on to be consistent and avoid breaking users expectations. If the new no_linklocal_learn option is enabled then the bridge will stop learning from link-local packets. In order to save space for future boolean options, patch 01 adds a new bool option API that uses a bitmask to control boolean options. The bridge is by far the largest netlink attr user and we keep adding simple boolean options which waste nl attr ids and space. We're not directly mapping these to the in-kernel bridge flags because some might require more complex configuration changes (e.g. if we were to add the per port vlan stats now, it'd require multiple checks before changing value). Any new bool option needs to be handled by both br_boolopt_toggle and get in order to be able to retrieve its state later. All such options are automatically exported via netlink. The behaviour of setting such options is consistent with netlink option handling when a missing option is being set (silently ignored), e.g. when a newer iproute2 is used on older kernel. Thanks, Nik Nikolay Aleksandrov (2): net: bridge: add support for user-controlled bool options net: bridge: add no_linklocal_learn bool option include/uapi/linux/if_bridge.h | 21 ++++++++++ include/uapi/linux/if_link.h | 1 + net/bridge/br.c | 72 ++++++++++++++++++++++++++++++++++ net/bridge/br_input.c | 4 +- net/bridge/br_netlink.c | 17 +++++++- net/bridge/br_private.h | 7 ++++ net/bridge/br_sysfs_br.c | 22 +++++++++++ net/core/rtnetlink.c | 2 +- 8 files changed, 143 insertions(+), 3 deletions(-) -- 2.17.2 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [Bridge] [PATCH net-next 0/2] net: bridge: add an option to disabe linklocal learning @ 2018-11-22 4:29 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: Nikolay Aleksandrov, andrew, roopa, bridge, davem Hi, This set adds a new bridge option which can control learning from link-local packets, by default learning is on to be consistent and avoid breaking users expectations. If the new no_linklocal_learn option is enabled then the bridge will stop learning from link-local packets. In order to save space for future boolean options, patch 01 adds a new bool option API that uses a bitmask to control boolean options. The bridge is by far the largest netlink attr user and we keep adding simple boolean options which waste nl attr ids and space. We're not directly mapping these to the in-kernel bridge flags because some might require more complex configuration changes (e.g. if we were to add the per port vlan stats now, it'd require multiple checks before changing value). Any new bool option needs to be handled by both br_boolopt_toggle and get in order to be able to retrieve its state later. All such options are automatically exported via netlink. The behaviour of setting such options is consistent with netlink option handling when a missing option is being set (silently ignored), e.g. when a newer iproute2 is used on older kernel. Thanks, Nik Nikolay Aleksandrov (2): net: bridge: add support for user-controlled bool options net: bridge: add no_linklocal_learn bool option include/uapi/linux/if_bridge.h | 21 ++++++++++ include/uapi/linux/if_link.h | 1 + net/bridge/br.c | 72 ++++++++++++++++++++++++++++++++++ net/bridge/br_input.c | 4 +- net/bridge/br_netlink.c | 17 +++++++- net/bridge/br_private.h | 7 ++++ net/bridge/br_sysfs_br.c | 22 +++++++++++ net/core/rtnetlink.c | 2 +- 8 files changed, 143 insertions(+), 3 deletions(-) -- 2.17.2 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 4:29 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: roopa, andrew, davem, bridge, Nikolay Aleksandrov We have been adding many new bridge options, a big number of which are boolean but still take up netlink attribute ids and waste space in the skb. Recently we discussed learning from link-local packets[1] and decided yet another new boolean option will be needed, thus introducing this API to save some bridge nl space. The API supports changing the value of multiple boolean options at once via the br_boolopt_multi struct which has an optmask (which options to set, bit per opt) and optval (options' new values). Future boolean options will only be added to the br_boolopt_id enum and then will have to be handled in br_boolopt_toggle/get. The API will automatically add the ability to change and export them via netlink, sysfs can use the single boolopt function versions to do the same. The behaviour with failing/succeeding is the same as with normal netlink option changing. If an option requires mapping to internal kernel flag or needs special configuration to be enabled then it should be handled in br_boolopt_toggle. It should also be able to retrieve an option's current state via br_boolopt_get. [1] https://www.spinics.net/lists/netdev/msg532698.html Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- include/uapi/linux/if_bridge.h | 18 +++++++++ include/uapi/linux/if_link.h | 1 + net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ net/bridge/br_netlink.c | 17 ++++++++- net/bridge/br_private.h | 6 +++ net/core/rtnetlink.c | 2 +- 6 files changed, 110 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index e41eda3c71f1..6dc02c03bdf8 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -292,4 +292,22 @@ struct br_mcast_stats { __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; __u64 mcast_packets[BR_MCAST_DIR_SIZE]; }; + +/* bridge boolean options + * IMPORTANT: if adding a new option do not forget to handle + * it in br_boolopt_toggle/get and bridge sysfs + */ +enum br_boolopt_id { + BR_BOOLOPT_MAX +}; + +/* struct br_boolopt_multi - change multiple bridge boolean options + * + * @optval: new option values (bit per option) + * @optmask: options to change (bit per option) + */ +struct br_boolopt_multi { + __u32 optval; + __u32 optmask; +}; #endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index f42c069d81db..d6533828123a 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -288,6 +288,7 @@ enum { IFLA_BR_MCAST_IGMP_VERSION, IFLA_BR_MCAST_MLD_VERSION, IFLA_BR_VLAN_STATS_PER_PORT, + IFLA_BR_MULTI_BOOLOPT, __IFLA_BR_MAX, }; diff --git a/net/bridge/br.c b/net/bridge/br.c index 360ad66c21e9..290b0adbf6d6 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -175,6 +175,74 @@ static struct notifier_block br_switchdev_notifier = { .notifier_call = br_switchdev_event, }; +/* br_boolopt_toggle - change user-controlled boolean option + * + * @br: bridge device + * @opt: id of the option to change + * @on: new option value + * + * Changes the value of the respective boolean option to @on taking care of + * any internal option value mapping and configuration. + */ +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) +{ + int err = -ENOENT; + + switch (opt) { + default: + break; + } + + return err; +} + +int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) +{ + int optval = 0; + + switch (opt) { + default: + break; + } + + return optval; +} + +int br_boolopt_multi_toggle(struct net_bridge *br, + struct br_boolopt_multi *bm) +{ + unsigned long bitmap = bm->optmask; + int err = 0; + int opt_id; + + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { + bool on = !!(bm->optval & BIT(opt_id)); + + err = br_boolopt_toggle(br, opt_id, on); + if (err) { + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", + opt_id, br_boolopt_get(br, opt_id), on, err); + break; + } + } + + return err; +} + +void br_boolopt_multi_get(const struct net_bridge *br, + struct br_boolopt_multi *bm) +{ + u32 optval = 0; + int opt_id; + + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) + optval |= (br_boolopt_get(br, opt_id) << opt_id); + + bm->optval = optval; + bm->optmask = 0; +} + +/* private bridge options, controlled by the kernel */ void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on) { bool cur = !!br_opt_get(br, opt); diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 3345f1984542..11325dc2e90a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1035,6 +1035,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = { [IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, [IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 }, [IFLA_BR_VLAN_STATS_PER_PORT] = { .type = NLA_U8 }, + [IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_EXACT_LEN, + .len = sizeof(struct br_boolopt_multi) }, }; static int br_changelink(struct net_device *brdev, struct nlattr *tb[], @@ -1296,6 +1298,15 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], } #endif + if (data[IFLA_BR_MULTI_BOOLOPT]) { + struct br_boolopt_multi *bm; + + bm = nla_data(data[IFLA_BR_MULTI_BOOLOPT]); + err = br_boolopt_multi_toggle(br, bm); + if (err) + return err; + } + return 0; } @@ -1374,6 +1385,7 @@ static size_t br_get_size(const struct net_device *brdev) nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_IP6TABLES */ nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_ARPTABLES */ #endif + nla_total_size(sizeof(struct br_boolopt_multi)) + /* IFLA_BR_MULTI_BOOLOPT */ 0; } @@ -1387,6 +1399,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) u32 stp_enabled = br->stp_enabled; u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]; u8 vlan_enabled = br_vlan_enabled(br->dev); + struct br_boolopt_multi bm; u64 clockval; clockval = br_timer_value(&br->hello_timer); @@ -1403,6 +1416,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) if (nla_put_u64_64bit(skb, IFLA_BR_GC_TIMER, clockval, IFLA_BR_PAD)) return -EMSGSIZE; + br_boolopt_multi_get(br, &bm); if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) || nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) || nla_put_u32(skb, IFLA_BR_MAX_AGE, age_time) || @@ -1420,7 +1434,8 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE, br->topology_change) || nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE_DETECTED, br->topology_change_detected) || - nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr)) + nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr) || + nla_put(skb, IFLA_BR_MULTI_BOOLOPT, sizeof(bm), &bm)) return -EMSGSIZE; #ifdef CONFIG_BRIDGE_VLAN_FILTERING diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index bc2653738fc3..0f051730ed4f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -507,6 +507,12 @@ static inline int br_opt_get(const struct net_bridge *br, return test_bit(opt, &br->options); } +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on); +int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt); +int br_boolopt_multi_toggle(struct net_bridge *br, + struct br_boolopt_multi *bm); +void br_boolopt_multi_get(const struct net_bridge *br, + struct br_boolopt_multi *bm); void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on); /* br_device.c */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 86f2d9cbdae3..a498bb41c9aa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -59,7 +59,7 @@ #include <net/rtnetlink.h> #include <net/net_namespace.h> -#define RTNL_MAX_TYPE 49 +#define RTNL_MAX_TYPE 50 #define RTNL_SLAVE_MAX_TYPE 36 struct rtnl_link { -- 2.17.2 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 4:29 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: Nikolay Aleksandrov, andrew, roopa, bridge, davem We have been adding many new bridge options, a big number of which are boolean but still take up netlink attribute ids and waste space in the skb. Recently we discussed learning from link-local packets[1] and decided yet another new boolean option will be needed, thus introducing this API to save some bridge nl space. The API supports changing the value of multiple boolean options at once via the br_boolopt_multi struct which has an optmask (which options to set, bit per opt) and optval (options' new values). Future boolean options will only be added to the br_boolopt_id enum and then will have to be handled in br_boolopt_toggle/get. The API will automatically add the ability to change and export them via netlink, sysfs can use the single boolopt function versions to do the same. The behaviour with failing/succeeding is the same as with normal netlink option changing. If an option requires mapping to internal kernel flag or needs special configuration to be enabled then it should be handled in br_boolopt_toggle. It should also be able to retrieve an option's current state via br_boolopt_get. [1] https://www.spinics.net/lists/netdev/msg532698.html Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- include/uapi/linux/if_bridge.h | 18 +++++++++ include/uapi/linux/if_link.h | 1 + net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ net/bridge/br_netlink.c | 17 ++++++++- net/bridge/br_private.h | 6 +++ net/core/rtnetlink.c | 2 +- 6 files changed, 110 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index e41eda3c71f1..6dc02c03bdf8 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -292,4 +292,22 @@ struct br_mcast_stats { __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; __u64 mcast_packets[BR_MCAST_DIR_SIZE]; }; + +/* bridge boolean options + * IMPORTANT: if adding a new option do not forget to handle + * it in br_boolopt_toggle/get and bridge sysfs + */ +enum br_boolopt_id { + BR_BOOLOPT_MAX +}; + +/* struct br_boolopt_multi - change multiple bridge boolean options + * + * @optval: new option values (bit per option) + * @optmask: options to change (bit per option) + */ +struct br_boolopt_multi { + __u32 optval; + __u32 optmask; +}; #endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index f42c069d81db..d6533828123a 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -288,6 +288,7 @@ enum { IFLA_BR_MCAST_IGMP_VERSION, IFLA_BR_MCAST_MLD_VERSION, IFLA_BR_VLAN_STATS_PER_PORT, + IFLA_BR_MULTI_BOOLOPT, __IFLA_BR_MAX, }; diff --git a/net/bridge/br.c b/net/bridge/br.c index 360ad66c21e9..290b0adbf6d6 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -175,6 +175,74 @@ static struct notifier_block br_switchdev_notifier = { .notifier_call = br_switchdev_event, }; +/* br_boolopt_toggle - change user-controlled boolean option + * + * @br: bridge device + * @opt: id of the option to change + * @on: new option value + * + * Changes the value of the respective boolean option to @on taking care of + * any internal option value mapping and configuration. + */ +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) +{ + int err = -ENOENT; + + switch (opt) { + default: + break; + } + + return err; +} + +int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) +{ + int optval = 0; + + switch (opt) { + default: + break; + } + + return optval; +} + +int br_boolopt_multi_toggle(struct net_bridge *br, + struct br_boolopt_multi *bm) +{ + unsigned long bitmap = bm->optmask; + int err = 0; + int opt_id; + + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { + bool on = !!(bm->optval & BIT(opt_id)); + + err = br_boolopt_toggle(br, opt_id, on); + if (err) { + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", + opt_id, br_boolopt_get(br, opt_id), on, err); + break; + } + } + + return err; +} + +void br_boolopt_multi_get(const struct net_bridge *br, + struct br_boolopt_multi *bm) +{ + u32 optval = 0; + int opt_id; + + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) + optval |= (br_boolopt_get(br, opt_id) << opt_id); + + bm->optval = optval; + bm->optmask = 0; +} + +/* private bridge options, controlled by the kernel */ void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on) { bool cur = !!br_opt_get(br, opt); diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 3345f1984542..11325dc2e90a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1035,6 +1035,8 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = { [IFLA_BR_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, [IFLA_BR_MCAST_MLD_VERSION] = { .type = NLA_U8 }, [IFLA_BR_VLAN_STATS_PER_PORT] = { .type = NLA_U8 }, + [IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_EXACT_LEN, + .len = sizeof(struct br_boolopt_multi) }, }; static int br_changelink(struct net_device *brdev, struct nlattr *tb[], @@ -1296,6 +1298,15 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], } #endif + if (data[IFLA_BR_MULTI_BOOLOPT]) { + struct br_boolopt_multi *bm; + + bm = nla_data(data[IFLA_BR_MULTI_BOOLOPT]); + err = br_boolopt_multi_toggle(br, bm); + if (err) + return err; + } + return 0; } @@ -1374,6 +1385,7 @@ static size_t br_get_size(const struct net_device *brdev) nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_IP6TABLES */ nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_ARPTABLES */ #endif + nla_total_size(sizeof(struct br_boolopt_multi)) + /* IFLA_BR_MULTI_BOOLOPT */ 0; } @@ -1387,6 +1399,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) u32 stp_enabled = br->stp_enabled; u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]; u8 vlan_enabled = br_vlan_enabled(br->dev); + struct br_boolopt_multi bm; u64 clockval; clockval = br_timer_value(&br->hello_timer); @@ -1403,6 +1416,7 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) if (nla_put_u64_64bit(skb, IFLA_BR_GC_TIMER, clockval, IFLA_BR_PAD)) return -EMSGSIZE; + br_boolopt_multi_get(br, &bm); if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) || nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) || nla_put_u32(skb, IFLA_BR_MAX_AGE, age_time) || @@ -1420,7 +1434,8 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE, br->topology_change) || nla_put_u8(skb, IFLA_BR_TOPOLOGY_CHANGE_DETECTED, br->topology_change_detected) || - nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr)) + nla_put(skb, IFLA_BR_GROUP_ADDR, ETH_ALEN, br->group_addr) || + nla_put(skb, IFLA_BR_MULTI_BOOLOPT, sizeof(bm), &bm)) return -EMSGSIZE; #ifdef CONFIG_BRIDGE_VLAN_FILTERING diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index bc2653738fc3..0f051730ed4f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -507,6 +507,12 @@ static inline int br_opt_get(const struct net_bridge *br, return test_bit(opt, &br->options); } +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on); +int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt); +int br_boolopt_multi_toggle(struct net_bridge *br, + struct br_boolopt_multi *bm); +void br_boolopt_multi_get(const struct net_bridge *br, + struct br_boolopt_multi *bm); void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on); /* br_device.c */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 86f2d9cbdae3..a498bb41c9aa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -59,7 +59,7 @@ #include <net/rtnetlink.h> #include <net/net_namespace.h> -#define RTNL_MAX_TYPE 49 +#define RTNL_MAX_TYPE 50 #define RTNL_SLAVE_MAX_TYPE 36 struct rtnl_link { -- 2.17.2 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 15:35 ` Andrew Lunn -1 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:35 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: > We have been adding many new bridge options, a big number of which are > boolean but still take up netlink attribute ids and waste space in the skb. > Recently we discussed learning from link-local packets[1] and decided > yet another new boolean option will be needed, thus introducing this API > to save some bridge nl space. > The API supports changing the value of multiple boolean options at once > via the br_boolopt_multi struct which has an optmask (which options to > set, bit per opt) and optval (options' new values). Future boolean > options will only be added to the br_boolopt_id enum and then will have > to be handled in br_boolopt_toggle/get. The API will automatically > add the ability to change and export them via netlink, sysfs can use the > single boolopt function versions to do the same. The behaviour with > failing/succeeding is the same as with normal netlink option changing. > > If an option requires mapping to internal kernel flag or needs special > configuration to be enabled then it should be handled in > br_boolopt_toggle. It should also be able to retrieve an option's current > state via br_boolopt_get. > > [1] https://www.spinics.net/lists/netdev/msg532698.html > > Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > --- > include/uapi/linux/if_bridge.h | 18 +++++++++ > include/uapi/linux/if_link.h | 1 + > net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ > net/bridge/br_netlink.c | 17 ++++++++- > net/bridge/br_private.h | 6 +++ > net/core/rtnetlink.c | 2 +- > 6 files changed, 110 insertions(+), 2 deletions(-) > > diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h > index e41eda3c71f1..6dc02c03bdf8 100644 > --- a/include/uapi/linux/if_bridge.h > +++ b/include/uapi/linux/if_bridge.h > @@ -292,4 +292,22 @@ struct br_mcast_stats { > __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; > __u64 mcast_packets[BR_MCAST_DIR_SIZE]; > }; > + > +/* bridge boolean options > + * IMPORTANT: if adding a new option do not forget to handle > + * it in br_boolopt_toggle/get and bridge sysfs > + */ > +enum br_boolopt_id { > + BR_BOOLOPT_MAX > +}; > + > +/* struct br_boolopt_multi - change multiple bridge boolean options > + * > + * @optval: new option values (bit per option) > + * @optmask: options to change (bit per option) > + */ > +struct br_boolopt_multi { > + __u32 optval; > + __u32 optmask; > +}; Hi Nikolay Thanks for handling this. How many boolean options do we already have? What it the likelihood a u32 is going to be too small, in a couple of years time? I recently went through the pain of converting the u32 for representing link modes in the phylib API to a linux bitmap. I'm just wondering if in the long run, using a linux bitmap right from the beginning would be better? > +int br_boolopt_multi_toggle(struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + unsigned long bitmap = bm->optmask; > + int err = 0; > + int opt_id; > + > + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > + bool on = !!(bm->optval & BIT(opt_id)); > + > + err = br_boolopt_toggle(br, opt_id, on); > + if (err) { > + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > + opt_id, br_boolopt_get(br, opt_id), on, err); Would it be possible to return that to userspace using the extended error infrastructure? Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 15:35 ` Andrew Lunn 0 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:35 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, bridge, davem On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: > We have been adding many new bridge options, a big number of which are > boolean but still take up netlink attribute ids and waste space in the skb. > Recently we discussed learning from link-local packets[1] and decided > yet another new boolean option will be needed, thus introducing this API > to save some bridge nl space. > The API supports changing the value of multiple boolean options at once > via the br_boolopt_multi struct which has an optmask (which options to > set, bit per opt) and optval (options' new values). Future boolean > options will only be added to the br_boolopt_id enum and then will have > to be handled in br_boolopt_toggle/get. The API will automatically > add the ability to change and export them via netlink, sysfs can use the > single boolopt function versions to do the same. The behaviour with > failing/succeeding is the same as with normal netlink option changing. > > If an option requires mapping to internal kernel flag or needs special > configuration to be enabled then it should be handled in > br_boolopt_toggle. It should also be able to retrieve an option's current > state via br_boolopt_get. > > [1] https://www.spinics.net/lists/netdev/msg532698.html > > Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > --- > include/uapi/linux/if_bridge.h | 18 +++++++++ > include/uapi/linux/if_link.h | 1 + > net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ > net/bridge/br_netlink.c | 17 ++++++++- > net/bridge/br_private.h | 6 +++ > net/core/rtnetlink.c | 2 +- > 6 files changed, 110 insertions(+), 2 deletions(-) > > diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h > index e41eda3c71f1..6dc02c03bdf8 100644 > --- a/include/uapi/linux/if_bridge.h > +++ b/include/uapi/linux/if_bridge.h > @@ -292,4 +292,22 @@ struct br_mcast_stats { > __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; > __u64 mcast_packets[BR_MCAST_DIR_SIZE]; > }; > + > +/* bridge boolean options > + * IMPORTANT: if adding a new option do not forget to handle > + * it in br_boolopt_toggle/get and bridge sysfs > + */ > +enum br_boolopt_id { > + BR_BOOLOPT_MAX > +}; > + > +/* struct br_boolopt_multi - change multiple bridge boolean options > + * > + * @optval: new option values (bit per option) > + * @optmask: options to change (bit per option) > + */ > +struct br_boolopt_multi { > + __u32 optval; > + __u32 optmask; > +}; Hi Nikolay Thanks for handling this. How many boolean options do we already have? What it the likelihood a u32 is going to be too small, in a couple of years time? I recently went through the pain of converting the u32 for representing link modes in the phylib API to a linux bitmap. I'm just wondering if in the long run, using a linux bitmap right from the beginning would be better? > +int br_boolopt_multi_toggle(struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + unsigned long bitmap = bm->optmask; > + int err = 0; > + int opt_id; > + > + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > + bool on = !!(bm->optval & BIT(opt_id)); > + > + err = br_boolopt_toggle(br, opt_id, on); > + if (err) { > + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > + opt_id, br_boolopt_get(br, opt_id), on, err); Would it be possible to return that to userspace using the extended error infrastructure? Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 15:35 ` [Bridge] " Andrew Lunn @ 2018-11-22 16:01 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:01 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge On 22/11/2018 17:35, Andrew Lunn wrote: > On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: >> We have been adding many new bridge options, a big number of which are >> boolean but still take up netlink attribute ids and waste space in the skb. >> Recently we discussed learning from link-local packets[1] and decided >> yet another new boolean option will be needed, thus introducing this API >> to save some bridge nl space. >> The API supports changing the value of multiple boolean options at once >> via the br_boolopt_multi struct which has an optmask (which options to >> set, bit per opt) and optval (options' new values). Future boolean >> options will only be added to the br_boolopt_id enum and then will have >> to be handled in br_boolopt_toggle/get. The API will automatically >> add the ability to change and export them via netlink, sysfs can use the >> single boolopt function versions to do the same. The behaviour with >> failing/succeeding is the same as with normal netlink option changing. >> >> If an option requires mapping to internal kernel flag or needs special >> configuration to be enabled then it should be handled in >> br_boolopt_toggle. It should also be able to retrieve an option's current >> state via br_boolopt_get. >> >> [1] https://www.spinics.net/lists/netdev/msg532698.html >> >> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> >> --- >> include/uapi/linux/if_bridge.h | 18 +++++++++ >> include/uapi/linux/if_link.h | 1 + >> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ >> net/bridge/br_netlink.c | 17 ++++++++- >> net/bridge/br_private.h | 6 +++ >> net/core/rtnetlink.c | 2 +- >> 6 files changed, 110 insertions(+), 2 deletions(-) >> >> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h >> index e41eda3c71f1..6dc02c03bdf8 100644 >> --- a/include/uapi/linux/if_bridge.h >> +++ b/include/uapi/linux/if_bridge.h >> @@ -292,4 +292,22 @@ struct br_mcast_stats { >> __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; >> __u64 mcast_packets[BR_MCAST_DIR_SIZE]; >> }; >> + >> +/* bridge boolean options >> + * IMPORTANT: if adding a new option do not forget to handle >> + * it in br_boolopt_toggle/get and bridge sysfs >> + */ >> +enum br_boolopt_id { >> + BR_BOOLOPT_MAX >> +}; >> + >> +/* struct br_boolopt_multi - change multiple bridge boolean options >> + * >> + * @optval: new option values (bit per option) >> + * @optmask: options to change (bit per option) >> + */ >> +struct br_boolopt_multi { >> + __u32 optval; >> + __u32 optmask; >> +}; > > Hi Nikolay > > Thanks for handling this. > > How many boolean options do we already have? What it the likelihood a > u32 is going to be too small, in a couple of years time? > It would mean doubling the number of current options and this is only for boolean options so I think we're safe. > I recently went through the pain of converting the u32 for > representing link modes in the phylib API to a linux bitmap. I'm just > wondering if in the long run, using a linux bitmap right from the > beginning would be better? > >> +int br_boolopt_multi_toggle(struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + unsigned long bitmap = bm->optmask; >> + int err = 0; >> + int opt_id; >> + >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >> + bool on = !!(bm->optval & BIT(opt_id)); >> + >> + err = br_boolopt_toggle(br, opt_id, on); >> + if (err) { >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >> + opt_id, br_boolopt_get(br, opt_id), on, err); > > Would it be possible to return that to userspace using the extended > error infrastructure? > No, it doesn't support dynamic messages AFAIK. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 16:01 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:01 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, bridge, davem On 22/11/2018 17:35, Andrew Lunn wrote: > On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: >> We have been adding many new bridge options, a big number of which are >> boolean but still take up netlink attribute ids and waste space in the skb. >> Recently we discussed learning from link-local packets[1] and decided >> yet another new boolean option will be needed, thus introducing this API >> to save some bridge nl space. >> The API supports changing the value of multiple boolean options at once >> via the br_boolopt_multi struct which has an optmask (which options to >> set, bit per opt) and optval (options' new values). Future boolean >> options will only be added to the br_boolopt_id enum and then will have >> to be handled in br_boolopt_toggle/get. The API will automatically >> add the ability to change and export them via netlink, sysfs can use the >> single boolopt function versions to do the same. The behaviour with >> failing/succeeding is the same as with normal netlink option changing. >> >> If an option requires mapping to internal kernel flag or needs special >> configuration to be enabled then it should be handled in >> br_boolopt_toggle. It should also be able to retrieve an option's current >> state via br_boolopt_get. >> >> [1] https://www.spinics.net/lists/netdev/msg532698.html >> >> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> >> --- >> include/uapi/linux/if_bridge.h | 18 +++++++++ >> include/uapi/linux/if_link.h | 1 + >> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ >> net/bridge/br_netlink.c | 17 ++++++++- >> net/bridge/br_private.h | 6 +++ >> net/core/rtnetlink.c | 2 +- >> 6 files changed, 110 insertions(+), 2 deletions(-) >> >> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h >> index e41eda3c71f1..6dc02c03bdf8 100644 >> --- a/include/uapi/linux/if_bridge.h >> +++ b/include/uapi/linux/if_bridge.h >> @@ -292,4 +292,22 @@ struct br_mcast_stats { >> __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; >> __u64 mcast_packets[BR_MCAST_DIR_SIZE]; >> }; >> + >> +/* bridge boolean options >> + * IMPORTANT: if adding a new option do not forget to handle >> + * it in br_boolopt_toggle/get and bridge sysfs >> + */ >> +enum br_boolopt_id { >> + BR_BOOLOPT_MAX >> +}; >> + >> +/* struct br_boolopt_multi - change multiple bridge boolean options >> + * >> + * @optval: new option values (bit per option) >> + * @optmask: options to change (bit per option) >> + */ >> +struct br_boolopt_multi { >> + __u32 optval; >> + __u32 optmask; >> +}; > > Hi Nikolay > > Thanks for handling this. > > How many boolean options do we already have? What it the likelihood a > u32 is going to be too small, in a couple of years time? > It would mean doubling the number of current options and this is only for boolean options so I think we're safe. > I recently went through the pain of converting the u32 for > representing link modes in the phylib API to a linux bitmap. I'm just > wondering if in the long run, using a linux bitmap right from the > beginning would be better? > >> +int br_boolopt_multi_toggle(struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + unsigned long bitmap = bm->optmask; >> + int err = 0; >> + int opt_id; >> + >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >> + bool on = !!(bm->optval & BIT(opt_id)); >> + >> + err = br_boolopt_toggle(br, opt_id, on); >> + if (err) { >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >> + opt_id, br_boolopt_get(br, opt_id), on, err); > > Would it be possible to return that to userspace using the extended > error infrastructure? > No, it doesn't support dynamic messages AFAIK. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 16:01 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 19:37 ` Stephen Hemminger -1 siblings, 0 replies; 26+ messages in thread From: Stephen Hemminger @ 2018-11-22 19:37 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: Andrew Lunn, netdev, roopa, davem, bridge On Thu, 22 Nov 2018 18:01:29 +0200 Nikolay Aleksandrov <nikolay@cumulusnetworks.com> wrote: > On 22/11/2018 17:35, Andrew Lunn wrote: > > On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: > >> We have been adding many new bridge options, a big number of which are > >> boolean but still take up netlink attribute ids and waste space in the skb. > >> Recently we discussed learning from link-local packets[1] and decided > >> yet another new boolean option will be needed, thus introducing this API > >> to save some bridge nl space. > >> The API supports changing the value of multiple boolean options at once > >> via the br_boolopt_multi struct which has an optmask (which options to > >> set, bit per opt) and optval (options' new values). Future boolean > >> options will only be added to the br_boolopt_id enum and then will have > >> to be handled in br_boolopt_toggle/get. The API will automatically > >> add the ability to change and export them via netlink, sysfs can use the > >> single boolopt function versions to do the same. The behaviour with > >> failing/succeeding is the same as with normal netlink option changing. > >> > >> If an option requires mapping to internal kernel flag or needs special > >> configuration to be enabled then it should be handled in > >> br_boolopt_toggle. It should also be able to retrieve an option's current > >> state via br_boolopt_get. > >> > >> [1] https://www.spinics.net/lists/netdev/msg532698.html > >> > >> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > >> --- > >> include/uapi/linux/if_bridge.h | 18 +++++++++ > >> include/uapi/linux/if_link.h | 1 + > >> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ > >> net/bridge/br_netlink.c | 17 ++++++++- > >> net/bridge/br_private.h | 6 +++ > >> net/core/rtnetlink.c | 2 +- > >> 6 files changed, 110 insertions(+), 2 deletions(-) > >> > >> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h > >> index e41eda3c71f1..6dc02c03bdf8 100644 > >> --- a/include/uapi/linux/if_bridge.h > >> +++ b/include/uapi/linux/if_bridge.h > >> @@ -292,4 +292,22 @@ struct br_mcast_stats { > >> __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; > >> __u64 mcast_packets[BR_MCAST_DIR_SIZE]; > >> }; > >> + > >> +/* bridge boolean options > >> + * IMPORTANT: if adding a new option do not forget to handle > >> + * it in br_boolopt_toggle/get and bridge sysfs > >> + */ > >> +enum br_boolopt_id { > >> + BR_BOOLOPT_MAX > >> +}; > >> + > >> +/* struct br_boolopt_multi - change multiple bridge boolean options > >> + * > >> + * @optval: new option values (bit per option) > >> + * @optmask: options to change (bit per option) > >> + */ > >> +struct br_boolopt_multi { > >> + __u32 optval; > >> + __u32 optmask; > >> +}; > > > > Hi Nikolay > > > > Thanks for handling this. > > > > How many boolean options do we already have? What it the likelihood a > > u32 is going to be too small, in a couple of years time? > > > > It would mean doubling the number of current options and this is only for > boolean options so I think we're safe. > > > I recently went through the pain of converting the u32 for > > representing link modes in the phylib API to a linux bitmap. I'm just > > wondering if in the long run, using a linux bitmap right from the > > beginning would be better? > > > >> +int br_boolopt_multi_toggle(struct net_bridge *br, > >> + struct br_boolopt_multi *bm) > >> +{ > >> + unsigned long bitmap = bm->optmask; > >> + int err = 0; > >> + int opt_id; > >> + > >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > >> + bool on = !!(bm->optval & BIT(opt_id)); > >> + > >> + err = br_boolopt_toggle(br, opt_id, on); > >> + if (err) { > >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > >> + opt_id, br_boolopt_get(br, opt_id), on, err); > > > > Would it be possible to return that to userspace using the extended > > error infrastructure? > > > > No, it doesn't support dynamic messages AFAIK. > > > Andrew > > > My concern is about backwards compatibility. What about old userspace and new userspace tools with old kernels. Having multiple bits does allow handling cases where certain combos won't work. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 19:37 ` Stephen Hemminger 0 siblings, 0 replies; 26+ messages in thread From: Stephen Hemminger @ 2018-11-22 19:37 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: Andrew Lunn, roopa, bridge, davem, netdev On Thu, 22 Nov 2018 18:01:29 +0200 Nikolay Aleksandrov <nikolay@cumulusnetworks.com> wrote: > On 22/11/2018 17:35, Andrew Lunn wrote: > > On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote: > >> We have been adding many new bridge options, a big number of which are > >> boolean but still take up netlink attribute ids and waste space in the skb. > >> Recently we discussed learning from link-local packets[1] and decided > >> yet another new boolean option will be needed, thus introducing this API > >> to save some bridge nl space. > >> The API supports changing the value of multiple boolean options at once > >> via the br_boolopt_multi struct which has an optmask (which options to > >> set, bit per opt) and optval (options' new values). Future boolean > >> options will only be added to the br_boolopt_id enum and then will have > >> to be handled in br_boolopt_toggle/get. The API will automatically > >> add the ability to change and export them via netlink, sysfs can use the > >> single boolopt function versions to do the same. The behaviour with > >> failing/succeeding is the same as with normal netlink option changing. > >> > >> If an option requires mapping to internal kernel flag or needs special > >> configuration to be enabled then it should be handled in > >> br_boolopt_toggle. It should also be able to retrieve an option's current > >> state via br_boolopt_get. > >> > >> [1] https://www.spinics.net/lists/netdev/msg532698.html > >> > >> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > >> --- > >> include/uapi/linux/if_bridge.h | 18 +++++++++ > >> include/uapi/linux/if_link.h | 1 + > >> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++ > >> net/bridge/br_netlink.c | 17 ++++++++- > >> net/bridge/br_private.h | 6 +++ > >> net/core/rtnetlink.c | 2 +- > >> 6 files changed, 110 insertions(+), 2 deletions(-) > >> > >> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h > >> index e41eda3c71f1..6dc02c03bdf8 100644 > >> --- a/include/uapi/linux/if_bridge.h > >> +++ b/include/uapi/linux/if_bridge.h > >> @@ -292,4 +292,22 @@ struct br_mcast_stats { > >> __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; > >> __u64 mcast_packets[BR_MCAST_DIR_SIZE]; > >> }; > >> + > >> +/* bridge boolean options > >> + * IMPORTANT: if adding a new option do not forget to handle > >> + * it in br_boolopt_toggle/get and bridge sysfs > >> + */ > >> +enum br_boolopt_id { > >> + BR_BOOLOPT_MAX > >> +}; > >> + > >> +/* struct br_boolopt_multi - change multiple bridge boolean options > >> + * > >> + * @optval: new option values (bit per option) > >> + * @optmask: options to change (bit per option) > >> + */ > >> +struct br_boolopt_multi { > >> + __u32 optval; > >> + __u32 optmask; > >> +}; > > > > Hi Nikolay > > > > Thanks for handling this. > > > > How many boolean options do we already have? What it the likelihood a > > u32 is going to be too small, in a couple of years time? > > > > It would mean doubling the number of current options and this is only for > boolean options so I think we're safe. > > > I recently went through the pain of converting the u32 for > > representing link modes in the phylib API to a linux bitmap. I'm just > > wondering if in the long run, using a linux bitmap right from the > > beginning would be better? > > > >> +int br_boolopt_multi_toggle(struct net_bridge *br, > >> + struct br_boolopt_multi *bm) > >> +{ > >> + unsigned long bitmap = bm->optmask; > >> + int err = 0; > >> + int opt_id; > >> + > >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > >> + bool on = !!(bm->optval & BIT(opt_id)); > >> + > >> + err = br_boolopt_toggle(br, opt_id, on); > >> + if (err) { > >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > >> + opt_id, br_boolopt_get(br, opt_id), on, err); > > > > Would it be possible to return that to userspace using the extended > > error infrastructure? > > > > No, it doesn't support dynamic messages AFAIK. > > > Andrew > > > My concern is about backwards compatibility. What about old userspace and new userspace tools with old kernels. Having multiple bits does allow handling cases where certain combos won't work. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 15:49 ` Andrew Lunn -1 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:49 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge > +/* br_boolopt_toggle - change user-controlled boolean option > + * > + * @br: bridge device > + * @opt: id of the option to change > + * @on: new option value > + * > + * Changes the value of the respective boolean option to @on taking care of > + * any internal option value mapping and configuration. > + */ > +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) > +{ > + int err = -ENOENT; > + > + switch (opt) { > + default: > + break; > + } > + > + return err; > +} > + > +int br_boolopt_multi_toggle(struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + unsigned long bitmap = bm->optmask; > + int err = 0; > + int opt_id; > + > + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > + bool on = !!(bm->optval & BIT(opt_id)); > + > + err = br_boolopt_toggle(br, opt_id, on); > + if (err) { > + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > + opt_id, br_boolopt_get(br, opt_id), on, err); > + break; > + } An old kernel with a new iproute2 might partially succeed in toggling some low bits, but then silently ignore a high bit that is not supported by the kernel. As a user, i want to know the kernel does not support an option i'm trying to toggle. Can you walk all the bits in the u32 from the MSB to the LSB? That should avoid this problem. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 15:49 ` Andrew Lunn 0 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:49 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, bridge, davem > +/* br_boolopt_toggle - change user-controlled boolean option > + * > + * @br: bridge device > + * @opt: id of the option to change > + * @on: new option value > + * > + * Changes the value of the respective boolean option to @on taking care of > + * any internal option value mapping and configuration. > + */ > +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) > +{ > + int err = -ENOENT; > + > + switch (opt) { > + default: > + break; > + } > + > + return err; > +} > + > +int br_boolopt_multi_toggle(struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + unsigned long bitmap = bm->optmask; > + int err = 0; > + int opt_id; > + > + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { > + bool on = !!(bm->optval & BIT(opt_id)); > + > + err = br_boolopt_toggle(br, opt_id, on); > + if (err) { > + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", > + opt_id, br_boolopt_get(br, opt_id), on, err); > + break; > + } An old kernel with a new iproute2 might partially succeed in toggling some low bits, but then silently ignore a high bit that is not supported by the kernel. As a user, i want to know the kernel does not support an option i'm trying to toggle. Can you walk all the bits in the u32 from the MSB to the LSB? That should avoid this problem. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 15:49 ` [Bridge] " Andrew Lunn @ 2018-11-22 16:13 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:13 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge On 22/11/2018 17:49, Andrew Lunn wrote: >> +/* br_boolopt_toggle - change user-controlled boolean option >> + * >> + * @br: bridge device >> + * @opt: id of the option to change >> + * @on: new option value >> + * >> + * Changes the value of the respective boolean option to @on taking care of >> + * any internal option value mapping and configuration. >> + */ >> +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) >> +{ >> + int err = -ENOENT; >> + >> + switch (opt) { >> + default: >> + break; >> + } >> + >> + return err; >> +} >> + > > >> +int br_boolopt_multi_toggle(struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + unsigned long bitmap = bm->optmask; >> + int err = 0; >> + int opt_id; >> + >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >> + bool on = !!(bm->optval & BIT(opt_id)); >> + >> + err = br_boolopt_toggle(br, opt_id, on); >> + if (err) { >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >> + opt_id, br_boolopt_get(br, opt_id), on, err); >> + break; >> + } > > An old kernel with a new iproute2 might partially succeed in toggling > some low bits, but then silently ignore a high bit that is not > supported by the kernel. As a user, i want to know the kernel does not > support an option i'm trying to toggle. > That is already how netlink option setting works, if the option isn't supported it is silently ignored. I tried to stay as close to the current behaviour as possible. It also applies to partial option changes, some options will be changed until an error is encountered. > Can you walk all the bits in the u32 from the MSB to the LSB? That > should avoid this problem. > I did wonder about this and left it as netlink option behaviour but I can leave the walk as is and just check if the highest order set bit >= BR_BOOLOPT_MAX and err out with ENOTSUPP for example. Will reconsider for v2. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 16:13 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:13 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, bridge, davem On 22/11/2018 17:49, Andrew Lunn wrote: >> +/* br_boolopt_toggle - change user-controlled boolean option >> + * >> + * @br: bridge device >> + * @opt: id of the option to change >> + * @on: new option value >> + * >> + * Changes the value of the respective boolean option to @on taking care of >> + * any internal option value mapping and configuration. >> + */ >> +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) >> +{ >> + int err = -ENOENT; >> + >> + switch (opt) { >> + default: >> + break; >> + } >> + >> + return err; >> +} >> + > > >> +int br_boolopt_multi_toggle(struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + unsigned long bitmap = bm->optmask; >> + int err = 0; >> + int opt_id; >> + >> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >> + bool on = !!(bm->optval & BIT(opt_id)); >> + >> + err = br_boolopt_toggle(br, opt_id, on); >> + if (err) { >> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >> + opt_id, br_boolopt_get(br, opt_id), on, err); >> + break; >> + } > > An old kernel with a new iproute2 might partially succeed in toggling > some low bits, but then silently ignore a high bit that is not > supported by the kernel. As a user, i want to know the kernel does not > support an option i'm trying to toggle. > That is already how netlink option setting works, if the option isn't supported it is silently ignored. I tried to stay as close to the current behaviour as possible. It also applies to partial option changes, some options will be changed until an error is encountered. > Can you walk all the bits in the u32 from the MSB to the LSB? That > should avoid this problem. > I did wonder about this and left it as netlink option behaviour but I can leave the walk as is and just check if the highest order set bit >= BR_BOOLOPT_MAX and err out with ENOTSUPP for example. Will reconsider for v2. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 16:13 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-23 1:55 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-23 1:55 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge On 22/11/2018 18:13, Nikolay Aleksandrov wrote: <snip> >>> +int br_boolopt_multi_toggle(struct net_bridge *br, >>> + struct br_boolopt_multi *bm) >>> +{ >>> + unsigned long bitmap = bm->optmask; >>> + int err = 0; >>> + int opt_id; >>> + >>> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >>> + bool on = !!(bm->optval & BIT(opt_id)); >>> + >>> + err = br_boolopt_toggle(br, opt_id, on); >>> + if (err) { >>> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >>> + opt_id, br_boolopt_get(br, opt_id), on, err); >>> + break; >>> + } >> >> An old kernel with a new iproute2 might partially succeed in toggling >> some low bits, but then silently ignore a high bit that is not >> supported by the kernel. As a user, i want to know the kernel does not >> support an option i'm trying to toggle. >> > > That is already how netlink option setting works, if the option isn't supported > it is silently ignored. I tried to stay as close to the current behaviour as possible. > It also applies to partial option changes, some options will be changed until an error > is encountered. > >> Can you walk all the bits in the u32 from the MSB to the LSB? That >> should avoid this problem. >> > > I did wonder about this and left it as netlink option behaviour but > I can leave the walk as is and just check if the highest order set bit >= BR_BOOLOPT_MAX > and err out with ENOTSUPP for example. Will reconsider for v2. > Actually this doesn't improve user experience, after testing a little the problem is that we can't return to the user the exact option that failed in any understandable manner. The options are: - exact error message: (no bit/option value) so pretty much just say "Failed bool option" - pr_err: this has 2 issues, first it can't be retrieved by the caller (will be in the logs) and more importantly the best we can do is print the option bit that we don't support which really doesn't help the user at all So the example is having newer iproute2 on older kernel and trying to set non-existing option mixed with existing ones - the user has no way of determining which one failed even if we print the bit, so this is really frustrating. The current way of ignoring the missing options seems a bit more user-friendly and also with the change that we return the supported bit options in optmask (thanks for the suggestion), the user-space tool (iproute2) can determine if an option is not supported and at least give an indication when dumping it. All of this does align with how netlink currently handles options and people are used to it. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-23 1:55 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-23 1:55 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, bridge, davem On 22/11/2018 18:13, Nikolay Aleksandrov wrote: <snip> >>> +int br_boolopt_multi_toggle(struct net_bridge *br, >>> + struct br_boolopt_multi *bm) >>> +{ >>> + unsigned long bitmap = bm->optmask; >>> + int err = 0; >>> + int opt_id; >>> + >>> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { >>> + bool on = !!(bm->optval & BIT(opt_id)); >>> + >>> + err = br_boolopt_toggle(br, opt_id, on); >>> + if (err) { >>> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", >>> + opt_id, br_boolopt_get(br, opt_id), on, err); >>> + break; >>> + } >> >> An old kernel with a new iproute2 might partially succeed in toggling >> some low bits, but then silently ignore a high bit that is not >> supported by the kernel. As a user, i want to know the kernel does not >> support an option i'm trying to toggle. >> > > That is already how netlink option setting works, if the option isn't supported > it is silently ignored. I tried to stay as close to the current behaviour as possible. > It also applies to partial option changes, some options will be changed until an error > is encountered. > >> Can you walk all the bits in the u32 from the MSB to the LSB? That >> should avoid this problem. >> > > I did wonder about this and left it as netlink option behaviour but > I can leave the walk as is and just check if the highest order set bit >= BR_BOOLOPT_MAX > and err out with ENOTSUPP for example. Will reconsider for v2. > Actually this doesn't improve user experience, after testing a little the problem is that we can't return to the user the exact option that failed in any understandable manner. The options are: - exact error message: (no bit/option value) so pretty much just say "Failed bool option" - pr_err: this has 2 issues, first it can't be retrieved by the caller (will be in the logs) and more importantly the best we can do is print the option bit that we don't support which really doesn't help the user at all So the example is having newer iproute2 on older kernel and trying to set non-existing option mixed with existing ones - the user has no way of determining which one failed even if we print the bit, so this is really frustrating. The current way of ignoring the missing options seems a bit more user-friendly and also with the change that we return the supported bit options in optmask (thanks for the suggestion), the user-space tool (iproute2) can determine if an option is not supported and at least give an indication when dumping it. All of this does align with how netlink currently handles options and people are used to it. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 15:52 ` Andrew Lunn -1 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:52 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge > +void br_boolopt_multi_get(const struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + u32 optval = 0; > + int opt_id; > + > + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) > + optval |= (br_boolopt_get(br, opt_id) << opt_id); > + > + bm->optval = optval; > + bm->optmask = 0; Maybe set optmask to indicate which bits this kernel supports? Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 15:52 ` Andrew Lunn 0 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 15:52 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, bridge, davem > +void br_boolopt_multi_get(const struct net_bridge *br, > + struct br_boolopt_multi *bm) > +{ > + u32 optval = 0; > + int opt_id; > + > + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) > + optval |= (br_boolopt_get(br, opt_id) << opt_id); > + > + bm->optval = optval; > + bm->optmask = 0; Maybe set optmask to indicate which bits this kernel supports? Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options 2018-11-22 15:52 ` [Bridge] " Andrew Lunn @ 2018-11-22 16:07 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:07 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge On 22/11/2018 17:52, Andrew Lunn wrote: >> +void br_boolopt_multi_get(const struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + u32 optval = 0; >> + int opt_id; >> + >> + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) >> + optval |= (br_boolopt_get(br, opt_id) << opt_id); >> + >> + bm->optval = optval; >> + bm->optmask = 0; > > Maybe set optmask to indicate which bits this kernel supports? > I like the idea, will add for v2. Thanks, Nik > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options @ 2018-11-22 16:07 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:07 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, bridge, davem On 22/11/2018 17:52, Andrew Lunn wrote: >> +void br_boolopt_multi_get(const struct net_bridge *br, >> + struct br_boolopt_multi *bm) >> +{ >> + u32 optval = 0; >> + int opt_id; >> + >> + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) >> + optval |= (br_boolopt_get(br, opt_id) << opt_id); >> + >> + bm->optval = optval; >> + bm->optmask = 0; > > Maybe set optmask to indicate which bits this kernel supports? > I like the idea, will add for v2. Thanks, Nik > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 4:29 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: roopa, andrew, davem, bridge, Nikolay Aleksandrov Use the new boolopt API to add an option which disables learning from link-local packets. The default is kept as before and learning is enabled. This is a simple map from a boolopt bit to a bridge private flag that is tested before learning. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- include/uapi/linux/if_bridge.h | 3 +++ net/bridge/br.c | 10 +++++++--- net/bridge/br_input.c | 4 +++- net/bridge/br_private.h | 1 + net/bridge/br_sysfs_br.c | 22 ++++++++++++++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 6dc02c03bdf8..773e476a8e54 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -294,10 +294,13 @@ struct br_mcast_stats { }; /* bridge boolean options + * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets + * * IMPORTANT: if adding a new option do not forget to handle * it in br_boolopt_toggle/get and bridge sysfs */ enum br_boolopt_id { + BR_BOOLOPT_NO_LL_LEARN, BR_BOOLOPT_MAX }; diff --git a/net/bridge/br.c b/net/bridge/br.c index 290b0adbf6d6..5b78a6385bd6 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -189,6 +189,10 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) int err = -ENOENT; switch (opt) { + case BR_BOOLOPT_NO_LL_LEARN: + err = 0; + br_opt_toggle(br, BROPT_NO_LL_LEARN, on); + break; default: break; } @@ -198,14 +202,14 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) { - int optval = 0; - switch (opt) { + case BR_BOOLOPT_NO_LL_LEARN: + return br_opt_get(br, BROPT_NO_LL_LEARN); default: break; } - return optval; + return 0; } int br_boolopt_multi_toggle(struct net_bridge *br, diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3ddca11f44c2..5ea7e56119c1 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -188,7 +188,9 @@ static void __br_handle_local_finish(struct sk_buff *skb) u16 vid = 0; /* check if vlan is allowed, to avoid spoofing */ - if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) + if ((p->flags & BR_LEARNING) && + !br_opt_get(p->br, BROPT_NO_LL_LEARN) && + br_should_learn(p, skb, &vid)) br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0f051730ed4f..390848acff08 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -328,6 +328,7 @@ enum net_bridge_opts { BROPT_NEIGH_SUPPRESS_ENABLED, BROPT_MTU_SET_BY_USER, BROPT_VLAN_STATS_PER_PORT, + BROPT_NO_LL_LEARN, }; struct net_bridge { diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 60182bef6341..5a03033ccd27 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, } static DEVICE_ATTR_WO(flush); +static ssize_t no_linklocal_learn_show(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(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) +{ + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); +} + +static ssize_t no_linklocal_learn_store(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); +} +static DEVICE_ATTR_RW(no_linklocal_learn); + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t multicast_router_show(struct device *d, struct device_attribute *attr, char *buf) @@ -841,6 +862,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_gc_timer.attr, &dev_attr_group_addr.attr, &dev_attr_flush.attr, + &dev_attr_no_linklocal_learn.attr, #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &dev_attr_multicast_router.attr, &dev_attr_multicast_snooping.attr, -- 2.17.2 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* [Bridge] [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option @ 2018-11-22 4:29 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 4:29 UTC (permalink / raw) To: netdev; +Cc: Nikolay Aleksandrov, andrew, roopa, bridge, davem Use the new boolopt API to add an option which disables learning from link-local packets. The default is kept as before and learning is enabled. This is a simple map from a boolopt bit to a bridge private flag that is tested before learning. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- include/uapi/linux/if_bridge.h | 3 +++ net/bridge/br.c | 10 +++++++--- net/bridge/br_input.c | 4 +++- net/bridge/br_private.h | 1 + net/bridge/br_sysfs_br.c | 22 ++++++++++++++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 6dc02c03bdf8..773e476a8e54 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -294,10 +294,13 @@ struct br_mcast_stats { }; /* bridge boolean options + * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets + * * IMPORTANT: if adding a new option do not forget to handle * it in br_boolopt_toggle/get and bridge sysfs */ enum br_boolopt_id { + BR_BOOLOPT_NO_LL_LEARN, BR_BOOLOPT_MAX }; diff --git a/net/bridge/br.c b/net/bridge/br.c index 290b0adbf6d6..5b78a6385bd6 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -189,6 +189,10 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) int err = -ENOENT; switch (opt) { + case BR_BOOLOPT_NO_LL_LEARN: + err = 0; + br_opt_toggle(br, BROPT_NO_LL_LEARN, on); + break; default: break; } @@ -198,14 +202,14 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on) int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) { - int optval = 0; - switch (opt) { + case BR_BOOLOPT_NO_LL_LEARN: + return br_opt_get(br, BROPT_NO_LL_LEARN); default: break; } - return optval; + return 0; } int br_boolopt_multi_toggle(struct net_bridge *br, diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3ddca11f44c2..5ea7e56119c1 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -188,7 +188,9 @@ static void __br_handle_local_finish(struct sk_buff *skb) u16 vid = 0; /* check if vlan is allowed, to avoid spoofing */ - if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) + if ((p->flags & BR_LEARNING) && + !br_opt_get(p->br, BROPT_NO_LL_LEARN) && + br_should_learn(p, skb, &vid)) br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0f051730ed4f..390848acff08 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -328,6 +328,7 @@ enum net_bridge_opts { BROPT_NEIGH_SUPPRESS_ENABLED, BROPT_MTU_SET_BY_USER, BROPT_VLAN_STATS_PER_PORT, + BROPT_NO_LL_LEARN, }; struct net_bridge { diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 60182bef6341..5a03033ccd27 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, } static DEVICE_ATTR_WO(flush); +static ssize_t no_linklocal_learn_show(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(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) +{ + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); +} + +static ssize_t no_linklocal_learn_store(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); +} +static DEVICE_ATTR_RW(no_linklocal_learn); + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t multicast_router_show(struct device *d, struct device_attribute *attr, char *buf) @@ -841,6 +862,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_gc_timer.attr, &dev_attr_group_addr.attr, &dev_attr_flush.attr, + &dev_attr_no_linklocal_learn.attr, #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &dev_attr_multicast_router.attr, &dev_attr_multicast_snooping.attr, -- 2.17.2 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov @ 2018-11-22 16:04 ` Andrew Lunn -1 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 16:04 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge > int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) > { > - int optval = 0; > - > switch (opt) { > + case BR_BOOLOPT_NO_LL_LEARN: > + return br_opt_get(br, BROPT_NO_LL_LEARN); > default: > break; > } > > - return optval; > + return 0; > } It seems like 1/2 of that change belongs in the previous patch. > --- a/net/bridge/br_sysfs_br.c > +++ b/net/bridge/br_sysfs_br.c > @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, > } > static DEVICE_ATTR_WO(flush); > > +static ssize_t no_linklocal_learn_show(struct device *d, > + struct device_attribute *attr, > + char *buf) > +{ > + struct net_bridge *br = to_bridge(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) > +{ > + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); > +} > + > +static ssize_t no_linklocal_learn_store(struct device *d, > + struct device_attribute *attr, > + const char *buf, size_t len) > +{ > + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); > +} > +static DEVICE_ATTR_RW(no_linklocal_learn); I thought we where trying to move away from sysfs? Do we need to add new options here? It seems like forcing people to use iproute2 for newer options is a good way to get people to convert to iproute2. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option @ 2018-11-22 16:04 ` Andrew Lunn 0 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2018-11-22 16:04 UTC (permalink / raw) To: Nikolay Aleksandrov; +Cc: netdev, roopa, bridge, davem > int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) > { > - int optval = 0; > - > switch (opt) { > + case BR_BOOLOPT_NO_LL_LEARN: > + return br_opt_get(br, BROPT_NO_LL_LEARN); > default: > break; > } > > - return optval; > + return 0; > } It seems like 1/2 of that change belongs in the previous patch. > --- a/net/bridge/br_sysfs_br.c > +++ b/net/bridge/br_sysfs_br.c > @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, > } > static DEVICE_ATTR_WO(flush); > > +static ssize_t no_linklocal_learn_show(struct device *d, > + struct device_attribute *attr, > + char *buf) > +{ > + struct net_bridge *br = to_bridge(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) > +{ > + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); > +} > + > +static ssize_t no_linklocal_learn_store(struct device *d, > + struct device_attribute *attr, > + const char *buf, size_t len) > +{ > + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); > +} > +static DEVICE_ATTR_RW(no_linklocal_learn); I thought we where trying to move away from sysfs? Do we need to add new options here? It seems like forcing people to use iproute2 for newer options is a good way to get people to convert to iproute2. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option 2018-11-22 16:04 ` [Bridge] " Andrew Lunn @ 2018-11-22 16:06 ` Nikolay Aleksandrov -1 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:06 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge On 22/11/2018 18:04, Andrew Lunn wrote: >> int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) >> { >> - int optval = 0; >> - >> switch (opt) { >> + case BR_BOOLOPT_NO_LL_LEARN: >> + return br_opt_get(br, BROPT_NO_LL_LEARN); >> default: >> break; >> } >> >> - return optval; >> + return 0; >> } > > It seems like 1/2 of that change belongs in the previous patch. > Yes, I could squash this into patch 01. >> --- a/net/bridge/br_sysfs_br.c >> +++ b/net/bridge/br_sysfs_br.c >> @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, >> } >> static DEVICE_ATTR_WO(flush); >> >> +static ssize_t no_linklocal_learn_show(struct device *d, >> + struct device_attribute *attr, >> + char *buf) >> +{ >> + struct net_bridge *br = to_bridge(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) >> +{ >> + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); >> +} >> + >> +static ssize_t no_linklocal_learn_store(struct device *d, >> + struct device_attribute *attr, >> + const char *buf, size_t len) >> +{ >> + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); >> +} >> +static DEVICE_ATTR_RW(no_linklocal_learn); > > I thought we where trying to move away from sysfs? Do we need to add > new options here? It seems like forcing people to use iproute2 for > newer options is a good way to get people to convert to iproute2. > Being consistent, all of the bridge options are exported via sysfs. If we start ignoring it now it'll be confusing. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Bridge] [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option @ 2018-11-22 16:06 ` Nikolay Aleksandrov 0 siblings, 0 replies; 26+ messages in thread From: Nikolay Aleksandrov @ 2018-11-22 16:06 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, roopa, bridge, davem On 22/11/2018 18:04, Andrew Lunn wrote: >> int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) >> { >> - int optval = 0; >> - >> switch (opt) { >> + case BR_BOOLOPT_NO_LL_LEARN: >> + return br_opt_get(br, BROPT_NO_LL_LEARN); >> default: >> break; >> } >> >> - return optval; >> + return 0; >> } > > It seems like 1/2 of that change belongs in the previous patch. > Yes, I could squash this into patch 01. >> --- a/net/bridge/br_sysfs_br.c >> +++ b/net/bridge/br_sysfs_br.c >> @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d, >> } >> static DEVICE_ATTR_WO(flush); >> >> +static ssize_t no_linklocal_learn_show(struct device *d, >> + struct device_attribute *attr, >> + char *buf) >> +{ >> + struct net_bridge *br = to_bridge(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) >> +{ >> + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val); >> +} >> + >> +static ssize_t no_linklocal_learn_store(struct device *d, >> + struct device_attribute *attr, >> + const char *buf, size_t len) >> +{ >> + return store_bridge_parm(d, buf, len, set_no_linklocal_learn); >> +} >> +static DEVICE_ATTR_RW(no_linklocal_learn); > > I thought we where trying to move away from sysfs? Do we need to add > new options here? It seems like forcing people to use iproute2 for > newer options is a good way to get people to convert to iproute2. > Being consistent, all of the bridge options are exported via sysfs. If we start ignoring it now it'll be confusing. > Andrew > ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2018-11-23 12:37 UTC | newest] Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-11-22 4:29 [PATCH net-next 0/2] net: bridge: add an option to disabe linklocal learning Nikolay Aleksandrov 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 4:29 ` [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options Nikolay Aleksandrov 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 15:35 ` Andrew Lunn 2018-11-22 15:35 ` [Bridge] " Andrew Lunn 2018-11-22 16:01 ` Nikolay Aleksandrov 2018-11-22 16:01 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 19:37 ` Stephen Hemminger 2018-11-22 19:37 ` [Bridge] " Stephen Hemminger 2018-11-22 15:49 ` Andrew Lunn 2018-11-22 15:49 ` [Bridge] " Andrew Lunn 2018-11-22 16:13 ` Nikolay Aleksandrov 2018-11-22 16:13 ` [Bridge] " Nikolay Aleksandrov 2018-11-23 1:55 ` Nikolay Aleksandrov 2018-11-23 1:55 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 15:52 ` Andrew Lunn 2018-11-22 15:52 ` [Bridge] " Andrew Lunn 2018-11-22 16:07 ` Nikolay Aleksandrov 2018-11-22 16:07 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 4:29 ` [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option Nikolay Aleksandrov 2018-11-22 4:29 ` [Bridge] " Nikolay Aleksandrov 2018-11-22 16:04 ` Andrew Lunn 2018-11-22 16:04 ` [Bridge] " Andrew Lunn 2018-11-22 16:06 ` Nikolay Aleksandrov 2018-11-22 16:06 ` [Bridge] " Nikolay Aleksandrov
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.