Skip to content

Commit

Permalink
Merge branch 'net-bridge-convert-bool-options-to-bits'
Browse files Browse the repository at this point in the history
Nikolay Aleksandrov says:

====================
net: bridge: convert bool options to bits

A lot of boolean bridge options have been added around the net_bridge
structure resulting in holes and more importantly different cache lines
that need to be fetched in the fast path. This set moves all of those
to bits in a bitfield which resides in a hot cache line thus reducing
the size of net_bridge, the number of holes and the number of cache
lines needed for the fast path.
The set is also sent in preparation for new boolean options to avoid
spreading them in the structure and making new holes.
One nice side-effect is that we avoid potential race conditions by using
the bitops since some of the options were bits being directly set in
parallel risking hard to debug issues (has_ipv6_addr).

Before:
 size: 1184, holes: 8, sum holes: 30
After:
 size: 1160, holes: 3, sum holes: 7

Patch 01 is a trivial style fix
Patch 02 adds the new options bitfield and converts the vlan boolean
         options to bits
Patches 03-08 convert the rest of the boolean options to bits
Patch 09 re-arranges a few fields in net_bridge to further reduce size

v2: patch 09: remove the comment about offload_fwd_mark in net_bridge and
    leave it where it is now, thanks to Ido for spotting it
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 26, 2018
2 parents 37ac5db + 35750b0 commit 30b0594
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 116 deletions.
16 changes: 16 additions & 0 deletions net/bridge/br.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,22 @@ static struct notifier_block br_switchdev_notifier = {
.notifier_call = br_switchdev_event,
};

void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)
{
bool cur = !!br_opt_get(br, opt);

br_debug(br, "toggle option: %d state: %d -> %d\n",
opt, cur, on);

if (cur == on)
return;

if (on)
set_bit(opt, &br->options);
else
clear_bit(opt, &br->options);
}

static void __net_exit br_net_exit(struct net *net)
{
struct net_device *dev;
Expand Down
13 changes: 8 additions & 5 deletions net/bridge/br_arp_nd_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
}
}

br->neigh_suppress_enabled = neigh_suppress;
br_opt_toggle(br, BROPT_NEIGH_SUPPRESS_ENABLED, neigh_suppress);
}

#if IS_ENABLED(CONFIG_INET)
Expand Down Expand Up @@ -155,7 +155,7 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
ipv4_is_multicast(tip))
return;

if (br->neigh_suppress_enabled) {
if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
if (p && (p->flags & BR_NEIGH_SUPPRESS))
return;
if (ipv4_is_zeronet(sip) || sip == tip) {
Expand All @@ -175,7 +175,8 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
return;
}

if (br->neigh_suppress_enabled && br_is_local_ip(vlandev, tip)) {
if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&
br_is_local_ip(vlandev, tip)) {
/* its our local ip, so don't proxy reply
* and don't forward to neigh suppress ports
*/
Expand Down Expand Up @@ -213,7 +214,8 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
/* If we have replied or as long as we know the
* mac, indicate to arp replied
*/
if (replied || br->neigh_suppress_enabled)
if (replied ||
br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))
BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
}

Expand Down Expand Up @@ -460,7 +462,8 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
* mac, indicate to NEIGH_SUPPRESS ports that we
* have replied
*/
if (replied || br->neigh_suppress_enabled)
if (replied ||
br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))
BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
}
neigh_release(n);
Expand Down
6 changes: 3 additions & 3 deletions net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
if (IS_ENABLED(CONFIG_INET) &&
(eth->h_proto == htons(ETH_P_ARP) ||
eth->h_proto == htons(ETH_P_RARP)) &&
br->neigh_suppress_enabled) {
br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
br_do_proxy_suppress_arp(skb, br, vid, NULL);
} else if (IS_ENABLED(CONFIG_IPV6) &&
skb->protocol == htons(ETH_P_IPV6) &&
br->neigh_suppress_enabled &&
br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&
pskb_may_pull(skb, sizeof(struct ipv6hdr) +
sizeof(struct nd_msg)) &&
ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
Expand Down Expand Up @@ -228,7 +228,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
dev->mtu = new_mtu;

/* this flag will be cleared if the MTU was automatically adjusted */
br->mtu_set_by_user = true;
br_opt_toggle(br, BROPT_MTU_SET_BY_USER, true);
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
/* remember the MTU in the rtable for PMTU */
dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
Expand Down
4 changes: 2 additions & 2 deletions net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,14 +508,14 @@ void br_mtu_auto_adjust(struct net_bridge *br)
ASSERT_RTNL();

/* if the bridge MTU was manually configured don't mess with it */
if (br->mtu_set_by_user)
if (br_opt_get(br, BROPT_MTU_SET_BY_USER))
return;

/* change to the minimum MTU and clear the flag which was set by
* the bridge ndo_change_mtu callback
*/
dev_set_mtu(br->dev, br_mtu_min(br));
br->mtu_set_by_user = false;
br_opt_toggle(br, BROPT_MTU_SET_BY_USER, false);
}

static void br_set_gso_limits(struct net_bridge *br)
Expand Down
2 changes: 1 addition & 1 deletion net/bridge/br_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
br_do_proxy_suppress_arp(skb, br, vid, p);
} else if (IS_ENABLED(CONFIG_IPV6) &&
skb->protocol == htons(ETH_P_IPV6) &&
br->neigh_suppress_enabled &&
br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&
pskb_may_pull(skb, sizeof(struct ipv6hdr) +
sizeof(struct nd_msg)) &&
ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
Expand Down
6 changes: 3 additions & 3 deletions net/bridge/br_mdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
int i, err = 0;
int idx = 0, s_idx = cb->args[1];

if (br->multicast_disabled)
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
return 0;

mdb = rcu_dereference(br->mdb);
Expand Down Expand Up @@ -598,7 +598,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
struct net_bridge_port *p;
int ret;

if (!netif_running(br->dev) || br->multicast_disabled)
if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED))
return -EINVAL;

dev = __dev_get_by_index(net, entry->ifindex);
Expand Down Expand Up @@ -673,7 +673,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
struct br_ip ip;
int err = -EINVAL;

if (!netif_running(br->dev) || br->multicast_disabled)
if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED))
return -EINVAL;

__mdb_entry_to_br_ip(entry, &ip);
Expand Down
54 changes: 27 additions & 27 deletions net/bridge/br_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
struct br_ip ip;

if (br->multicast_disabled)
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
return NULL;

if (BR_INPUT_SKB_CB(skb)->igmp)
Expand Down Expand Up @@ -411,7 +411,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
iph->frag_off = htons(IP_DF);
iph->ttl = 1;
iph->protocol = IPPROTO_IGMP;
iph->saddr = br->multicast_query_use_ifaddr ?
iph->saddr = br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR) ?
inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;
iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);
((u8 *)&iph[1])[0] = IPOPT_RA;
Expand Down Expand Up @@ -503,11 +503,11 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
&ip6h->saddr)) {
kfree_skb(skb);
br->has_ipv6_addr = 0;
br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, false);
return NULL;
}

br->has_ipv6_addr = 1;
br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);

hopopt = (u8 *)(ip6h + 1);
Expand Down Expand Up @@ -628,7 +628,7 @@ static struct net_bridge_mdb_entry *br_multicast_get_group(
port ? port->dev->name : br->dev->name);
err = -E2BIG;
disable:
br->multicast_disabled = 1;
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, false);
goto err;
}
}
Expand Down Expand Up @@ -894,7 +894,7 @@ static void br_multicast_querier_expired(struct net_bridge *br,
struct bridge_mcast_own_query *query)
{
spin_lock(&br->multicast_lock);
if (!netif_running(br->dev) || br->multicast_disabled)
if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED))
goto out;

br_multicast_start_querier(br, query);
Expand Down Expand Up @@ -965,8 +965,9 @@ static void br_multicast_send_query(struct net_bridge *br,
struct br_ip br_group;
unsigned long time;

if (!netif_running(br->dev) || br->multicast_disabled ||
!br->multicast_querier)
if (!netif_running(br->dev) ||
!br_opt_get(br, BROPT_MULTICAST_ENABLED) ||
!br_opt_get(br, BROPT_MULTICAST_QUERIER))
return;

memset(&br_group.u, 0, sizeof(br_group.u));
Expand Down Expand Up @@ -1036,7 +1037,7 @@ static void br_mc_disabled_update(struct net_device *dev, bool value)
.orig_dev = dev,
.id = SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
.flags = SWITCHDEV_F_DEFER,
.u.mc_disabled = value,
.u.mc_disabled = !value,
};

switchdev_port_attr_set(dev, &attr);
Expand All @@ -1054,7 +1055,8 @@ int br_multicast_add_port(struct net_bridge_port *port)
timer_setup(&port->ip6_own_query.timer,
br_ip6_multicast_port_query_expired, 0);
#endif
br_mc_disabled_update(port->dev, port->br->multicast_disabled);
br_mc_disabled_update(port->dev,
br_opt_get(port->br, BROPT_MULTICAST_ENABLED));

port->mcast_stats = netdev_alloc_pcpu_stats(struct bridge_mcast_stats);
if (!port->mcast_stats)
Expand Down Expand Up @@ -1091,7 +1093,7 @@ static void __br_multicast_enable_port(struct net_bridge_port *port)
{
struct net_bridge *br = port->br;

if (br->multicast_disabled || !netif_running(br->dev))
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED) || !netif_running(br->dev))
return;

br_multicast_enable(&port->ip4_own_query);
Expand Down Expand Up @@ -1634,7 +1636,7 @@ br_multicast_leave_group(struct net_bridge *br,
if (timer_pending(&other_query->timer))
goto out;

if (br->multicast_querier) {
if (br_opt_get(br, BROPT_MULTICAST_QUERIER)) {
__br_multicast_send_query(br, port, &mp->addr);

time = jiffies + br->multicast_last_member_count *
Expand Down Expand Up @@ -1746,7 +1748,7 @@ static void br_multicast_err_count(const struct net_bridge *br,
struct bridge_mcast_stats __percpu *stats;
struct bridge_mcast_stats *pstats;

if (!br->multicast_stats_enabled)
if (!br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED))
return;

if (p)
Expand Down Expand Up @@ -1904,7 +1906,7 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
BR_INPUT_SKB_CB(skb)->igmp = 0;
BR_INPUT_SKB_CB(skb)->mrouters_only = 0;

if (br->multicast_disabled)
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
return 0;

switch (skb->protocol) {
Expand Down Expand Up @@ -1956,8 +1958,6 @@ void br_multicast_init(struct net_bridge *br)
br->hash_max = 512;

br->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
br->multicast_querier = 0;
br->multicast_query_use_ifaddr = 0;
br->multicast_last_member_count = 2;
br->multicast_startup_query_count = 2;

Expand All @@ -1976,7 +1976,7 @@ void br_multicast_init(struct net_bridge *br)
br->ip6_other_query.delay_time = 0;
br->ip6_querier.port = NULL;
#endif
br->has_ipv6_addr = 1;
br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);

spin_lock_init(&br->multicast_lock);
timer_setup(&br->multicast_router_timer,
Expand All @@ -1998,7 +1998,7 @@ static void __br_multicast_open(struct net_bridge *br,
{
query->startup_sent = 0;

if (br->multicast_disabled)
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
return;

mod_timer(&query->timer, jiffies);
Expand Down Expand Up @@ -2173,12 +2173,12 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
int err = 0;

spin_lock_bh(&br->multicast_lock);
if (br->multicast_disabled == !val)
if (!!br_opt_get(br, BROPT_MULTICAST_ENABLED) == !!val)
goto unlock;

br_mc_disabled_update(br->dev, !val);
br->multicast_disabled = !val;
if (br->multicast_disabled)
br_mc_disabled_update(br->dev, val);
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val);
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
goto unlock;

if (!netif_running(br->dev))
Expand All @@ -2189,7 +2189,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
if (mdb->old) {
err = -EEXIST;
rollback:
br->multicast_disabled = !!val;
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, false);
goto unlock;
}

Expand All @@ -2213,7 +2213,7 @@ bool br_multicast_enabled(const struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);

return !br->multicast_disabled;
return !!br_opt_get(br, BROPT_MULTICAST_ENABLED);
}
EXPORT_SYMBOL_GPL(br_multicast_enabled);

Expand All @@ -2236,10 +2236,10 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
val = !!val;

spin_lock_bh(&br->multicast_lock);
if (br->multicast_querier == val)
if (br_opt_get(br, BROPT_MULTICAST_QUERIER) == val)
goto unlock;

br->multicast_querier = val;
br_opt_toggle(br, BROPT_MULTICAST_QUERIER, !!val);
if (!val)
goto unlock;

Expand Down Expand Up @@ -2560,7 +2560,7 @@ void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
struct bridge_mcast_stats __percpu *stats;

/* if multicast_disabled is true then igmp type can't be set */
if (!type || !br->multicast_stats_enabled)
if (!type || !br_opt_get(br, BROPT_MULTICAST_STATS_ENABLED))
return;

if (p)
Expand Down
7 changes: 4 additions & 3 deletions net/bridge/br_netfilter_hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,14 +487,15 @@ static unsigned int br_nf_pre_routing(void *priv,
br = p->br;

if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) {
if (!brnf_call_ip6tables && !br->nf_call_ip6tables)
if (!brnf_call_ip6tables &&
!br_opt_get(br, BROPT_NF_CALL_IP6TABLES))
return NF_ACCEPT;

nf_bridge_pull_encap_header_rcsum(skb);
return br_nf_pre_routing_ipv6(priv, skb, state);
}

if (!brnf_call_iptables && !br->nf_call_iptables)
if (!brnf_call_iptables && !br_opt_get(br, BROPT_NF_CALL_IPTABLES))
return NF_ACCEPT;

if (!IS_IP(skb) && !IS_VLAN_IP(skb) && !IS_PPPOE_IP(skb))
Expand Down Expand Up @@ -636,7 +637,7 @@ static unsigned int br_nf_forward_arp(void *priv,
return NF_ACCEPT;
br = p->br;

if (!brnf_call_arptables && !br->nf_call_arptables)
if (!brnf_call_arptables && !br_opt_get(br, BROPT_NF_CALL_ARPTABLES))
return NF_ACCEPT;

if (!IS_ARP(skb)) {
Expand Down
Loading

0 comments on commit 30b0594

Please sign in to comment.