Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bridge: Keep track of ports capable of automatic discovery.

By default, ports on the bridge are capable of automatic
discovery of nodes located behind the port. This is accomplished
via flooding of unknown traffic (BR_FLOOD) and learning the
mac addresses from these packets (BR_LEARNING).
If the above functionality is disabled by turning off these
flags, the port requires static configuration in the form
of static FDB entries to function properly.

This patch adds functionality to keep track of all ports
capable of automatic discovery. This will later be used
to control promiscuity settings.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vlad Yasevich and committed by
David S. Miller
e028e4b8 63c3a622

+36 -1
+24
net/bridge/br_if.c
··· 85 85 spin_unlock_bh(&br->lock); 86 86 } 87 87 88 + static void nbp_update_port_count(struct net_bridge *br) 89 + { 90 + struct net_bridge_port *p; 91 + u32 cnt = 0; 92 + 93 + list_for_each_entry(p, &br->port_list, list) { 94 + if (br_auto_port(p)) 95 + cnt++; 96 + } 97 + br->auto_cnt = cnt; 98 + } 99 + 88 100 static void release_nbp(struct kobject *kobj) 89 101 { 90 102 struct net_bridge_port *p ··· 157 145 br_fdb_delete_by_port(br, p, 1); 158 146 159 147 list_del_rcu(&p->list); 148 + 149 + nbp_update_port_count(br); 160 150 161 151 dev->priv_flags &= ~IFF_BRIDGE_PORT; 162 152 ··· 398 384 399 385 list_add_rcu(&p->list, &br->port_list); 400 386 387 + nbp_update_port_count(br); 388 + 401 389 netdev_update_features(br->dev); 402 390 403 391 if (br->dev->needed_headroom < dev->needed_headroom) ··· 470 454 netdev_update_features(br->dev); 471 455 472 456 return 0; 457 + } 458 + 459 + void br_port_flags_change(struct net_bridge_port *p, unsigned long mask) 460 + { 461 + struct net_bridge *br = p->br; 462 + 463 + if (mask & BR_AUTO_MASK) 464 + nbp_update_port_count(br); 473 465 }
+3
net/bridge/br_netlink.c
··· 328 328 static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) 329 329 { 330 330 int err; 331 + unsigned long old_flags = p->flags; 331 332 332 333 br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE); 333 334 br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); ··· 354 353 if (err) 355 354 return err; 356 355 } 356 + 357 + br_port_flags_change(p, old_flags ^ p->flags); 357 358 return 0; 358 359 } 359 360
+5
net/bridge/br_private.h
··· 174 174 #define BR_ADMIN_COST 0x00000010 175 175 #define BR_LEARNING 0x00000020 176 176 #define BR_FLOOD 0x00000040 177 + #define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING) 177 178 178 179 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 179 180 struct bridge_mcast_query ip4_query; ··· 198 197 struct net_port_vlans __rcu *vlan_info; 199 198 #endif 200 199 }; 200 + 201 + #define br_auto_port(p) ((p)->flags & BR_AUTO_MASK) 201 202 202 203 #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT) 203 204 ··· 293 290 struct timer_list topology_change_timer; 294 291 struct timer_list gc_timer; 295 292 struct kobject *ifobj; 293 + u32 auto_cnt; 296 294 #ifdef CONFIG_BRIDGE_VLAN_FILTERING 297 295 u8 vlan_enabled; 298 296 struct net_port_vlans __rcu *vlan_info; ··· 419 415 int br_min_mtu(const struct net_bridge *br); 420 416 netdev_features_t br_features_recompute(struct net_bridge *br, 421 417 netdev_features_t features); 418 + void br_port_flags_change(struct net_bridge_port *port, unsigned long mask); 422 419 423 420 /* br_input.c */ 424 421 int br_handle_frame_finish(struct sk_buff *skb);
+4 -1
net/bridge/br_sysfs_if.c
··· 49 49 static int store_flag(struct net_bridge_port *p, unsigned long v, 50 50 unsigned long mask) 51 51 { 52 - unsigned long flags = p->flags; 52 + unsigned long flags; 53 + 54 + flags = p->flags; 53 55 54 56 if (v) 55 57 flags |= mask; ··· 60 58 61 59 if (flags != p->flags) { 62 60 p->flags = flags; 61 + br_port_flags_change(p, mask); 63 62 br_ifinfo_notify(RTM_NEWLINK, p); 64 63 } 65 64 return 0;