aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@web.de>2014-06-07 12:26:28 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-11 02:50:47 -0400
commit07f8ac4a1e26e8283542cdaf658a6e2a12fd6980 (patch)
tree767bc394b56374b576feb4da5ff38808428c0857
parentdc4eb53a996a78bfb8ea07b47423ff5a3aadc362 (diff)
bridge: add export of multicast database adjacent to net_dev
With this new, exported function br_multicast_list_adjacent(net_dev) a list of IPv4/6 addresses is returned. This list contains all multicast addresses sensed by the bridge multicast snooping feature on all bridge ports of the bridge interface of net_dev, excluding addresses from the specified net_device itself. Adding bridge support to the batman-adv multicast optimization requires batman-adv knowing about the existence of bridged-in multicast listeners to be able to reliably serve them with multicast packets. Signed-off-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_bridge.h18
-rw-r--r--net/bridge/br_multicast.c58
-rw-r--r--net/bridge/br_private.h12
3 files changed, 76 insertions, 12 deletions
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 1085ffeef956..44d6eb0eb852 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -16,9 +16,27 @@
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <uapi/linux/if_bridge.h> 17#include <uapi/linux/if_bridge.h>
18 18
19struct br_ip {
20 union {
21 __be32 ip4;
22#if IS_ENABLED(CONFIG_IPV6)
23 struct in6_addr ip6;
24#endif
25 } u;
26 __be16 proto;
27 __u16 vid;
28};
29
30struct br_ip_list {
31 struct list_head list;
32 struct br_ip addr;
33};
34
19extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); 35extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
20 36
21typedef int br_should_route_hook_t(struct sk_buff *skb); 37typedef int br_should_route_hook_t(struct sk_buff *skb);
22extern br_should_route_hook_t __rcu *br_should_route_hook; 38extern br_should_route_hook_t __rcu *br_should_route_hook;
39int br_multicast_list_adjacent(struct net_device *dev,
40 struct list_head *br_ip_list);
23 41
24#endif 42#endif
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b3f17c9b4d06..772476b7c4b7 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/export.h>
14#include <linux/if_ether.h> 15#include <linux/if_ether.h>
15#include <linux/igmp.h> 16#include <linux/igmp.h>
16#include <linux/jhash.h> 17#include <linux/jhash.h>
@@ -2141,3 +2142,60 @@ unlock:
2141 2142
2142 return err; 2143 return err;
2143} 2144}
2145
2146/**
2147 * br_multicast_list_adjacent - Returns snooped multicast addresses
2148 * @dev: The bridge port adjacent to which to retrieve addresses
2149 * @br_ip_list: The list to store found, snooped multicast IP addresses in
2150 *
2151 * Creates a list of IP addresses (struct br_ip_list) sensed by the multicast
2152 * snooping feature on all bridge ports of dev's bridge device, excluding
2153 * the addresses from dev itself.
2154 *
2155 * Returns the number of items added to br_ip_list.
2156 *
2157 * Notes:
2158 * - br_ip_list needs to be initialized by caller
2159 * - br_ip_list might contain duplicates in the end
2160 * (needs to be taken care of by caller)
2161 * - br_ip_list needs to be freed by caller
2162 */
2163int br_multicast_list_adjacent(struct net_device *dev,
2164 struct list_head *br_ip_list)
2165{
2166 struct net_bridge *br;
2167 struct net_bridge_port *port;
2168 struct net_bridge_port_group *group;
2169 struct br_ip_list *entry;
2170 int count = 0;
2171
2172 rcu_read_lock();
2173 if (!br_ip_list || !br_port_exists(dev))
2174 goto unlock;
2175
2176 port = br_port_get_rcu(dev);
2177 if (!port || !port->br)
2178 goto unlock;
2179
2180 br = port->br;
2181
2182 list_for_each_entry_rcu(port, &br->port_list, list) {
2183 if (!port->dev || port->dev == dev)
2184 continue;
2185
2186 hlist_for_each_entry_rcu(group, &port->mglist, mglist) {
2187 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
2188 if (!entry)
2189 goto unlock;
2190
2191 entry->addr = group->addr;
2192 list_add(&entry->list, br_ip_list);
2193 count++;
2194 }
2195 }
2196
2197unlock:
2198 rcu_read_unlock();
2199 return count;
2200}
2201EXPORT_SYMBOL_GPL(br_multicast_list_adjacent);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 97c5e46dde72..50e2ab021484 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -54,18 +54,6 @@ struct mac_addr
54 unsigned char addr[ETH_ALEN]; 54 unsigned char addr[ETH_ALEN];
55}; 55};
56 56
57struct br_ip
58{
59 union {
60 __be32 ip4;
61#if IS_ENABLED(CONFIG_IPV6)
62 struct in6_addr ip6;
63#endif
64 } u;
65 __be16 proto;
66 __u16 vid;
67};
68
69#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 57#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
70/* our own querier */ 58/* our own querier */
71struct bridge_mcast_own_query { 59struct bridge_mcast_own_query {