aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2014-05-16 09:59:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-16 17:06:33 -0400
commite028e4b8dc93be7bc3ff9e0b94cb68d7f104883b (patch)
tree039b194353e0a758a643d3b8e75b797eb3a166fe /net/bridge
parent63c3a622dd020dd16959fdb1bfa79710dd702420 (diff)
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>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_if.c24
-rw-r--r--net/bridge/br_netlink.c3
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/bridge/br_sysfs_if.c5
4 files changed, 36 insertions, 1 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 5262b8617eb9..f7ef5f2b825b 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -85,6 +85,18 @@ void br_port_carrier_check(struct net_bridge_port *p)
85 spin_unlock_bh(&br->lock); 85 spin_unlock_bh(&br->lock);
86} 86}
87 87
88static 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
88static void release_nbp(struct kobject *kobj) 100static void release_nbp(struct kobject *kobj)
89{ 101{
90 struct net_bridge_port *p 102 struct net_bridge_port *p
@@ -146,6 +158,8 @@ static void del_nbp(struct net_bridge_port *p)
146 158
147 list_del_rcu(&p->list); 159 list_del_rcu(&p->list);
148 160
161 nbp_update_port_count(br);
162
149 dev->priv_flags &= ~IFF_BRIDGE_PORT; 163 dev->priv_flags &= ~IFF_BRIDGE_PORT;
150 164
151 netdev_rx_handler_unregister(dev); 165 netdev_rx_handler_unregister(dev);
@@ -384,6 +398,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
384 398
385 list_add_rcu(&p->list, &br->port_list); 399 list_add_rcu(&p->list, &br->port_list);
386 400
401 nbp_update_port_count(br);
402
387 netdev_update_features(br->dev); 403 netdev_update_features(br->dev);
388 404
389 if (br->dev->needed_headroom < dev->needed_headroom) 405 if (br->dev->needed_headroom < dev->needed_headroom)
@@ -455,3 +471,11 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
455 471
456 return 0; 472 return 0;
457} 473}
474
475void br_port_flags_change(struct net_bridge_port *p, unsigned long mask)
476{
477 struct net_bridge *br = p->br;
478
479 if (mask & BR_AUTO_MASK)
480 nbp_update_port_count(br);
481}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index e8844d975b32..26edb518b839 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -328,6 +328,7 @@ static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
328static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) 328static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
329{ 329{
330 int err; 330 int err;
331 unsigned long old_flags = p->flags;
331 332
332 br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE); 333 br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
333 br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); 334 br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
@@ -353,6 +354,8 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
353 if (err) 354 if (err)
354 return err; 355 return err;
355 } 356 }
357
358 br_port_flags_change(p, old_flags ^ p->flags);
356 return 0; 359 return 0;
357} 360}
358 361
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 06811d79f89f..5ce3191438d8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -174,6 +174,7 @@ struct net_bridge_port
174#define BR_ADMIN_COST 0x00000010 174#define BR_ADMIN_COST 0x00000010
175#define BR_LEARNING 0x00000020 175#define BR_LEARNING 0x00000020
176#define BR_FLOOD 0x00000040 176#define BR_FLOOD 0x00000040
177#define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING)
177 178
178#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 179#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
179 struct bridge_mcast_query ip4_query; 180 struct bridge_mcast_query ip4_query;
@@ -198,6 +199,8 @@ struct net_bridge_port
198#endif 199#endif
199}; 200};
200 201
202#define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
203
201#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT) 204#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
202 205
203static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) 206static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
@@ -290,6 +293,7 @@ struct net_bridge
290 struct timer_list topology_change_timer; 293 struct timer_list topology_change_timer;
291 struct timer_list gc_timer; 294 struct timer_list gc_timer;
292 struct kobject *ifobj; 295 struct kobject *ifobj;
296 u32 auto_cnt;
293#ifdef CONFIG_BRIDGE_VLAN_FILTERING 297#ifdef CONFIG_BRIDGE_VLAN_FILTERING
294 u8 vlan_enabled; 298 u8 vlan_enabled;
295 struct net_port_vlans __rcu *vlan_info; 299 struct net_port_vlans __rcu *vlan_info;
@@ -415,6 +419,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev);
415int br_min_mtu(const struct net_bridge *br); 419int br_min_mtu(const struct net_bridge *br);
416netdev_features_t br_features_recompute(struct net_bridge *br, 420netdev_features_t br_features_recompute(struct net_bridge *br,
417 netdev_features_t features); 421 netdev_features_t features);
422void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);
418 423
419/* br_input.c */ 424/* br_input.c */
420int br_handle_frame_finish(struct sk_buff *skb); 425int br_handle_frame_finish(struct sk_buff *skb);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 351af6b36ee1..e561cd59b8a6 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -49,7 +49,9 @@ static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR, \
49static int store_flag(struct net_bridge_port *p, unsigned long v, 49static int store_flag(struct net_bridge_port *p, unsigned long v,
50 unsigned long mask) 50 unsigned long mask)
51{ 51{
52 unsigned long flags = p->flags; 52 unsigned long flags;
53
54 flags = p->flags;
53 55
54 if (v) 56 if (v)
55 flags |= mask; 57 flags |= mask;
@@ -58,6 +60,7 @@ static int store_flag(struct net_bridge_port *p, unsigned long v,
58 60
59 if (flags != p->flags) { 61 if (flags != p->flags) {
60 p->flags = flags; 62 p->flags = flags;
63 br_port_flags_change(p, mask);
61 br_ifinfo_notify(RTM_NEWLINK, p); 64 br_ifinfo_notify(RTM_NEWLINK, p);
62 } 65 }
63 return 0; 66 return 0;