From patchwork Sun Feb 3 23:19:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Linus_L=C3=BCssing?= X-Patchwork-Id: 217813 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id DCE8E2C0089 for ; Mon, 4 Feb 2013 10:20:20 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753994Ab3BCXUR (ORCPT ); Sun, 3 Feb 2013 18:20:17 -0500 Received: from mout.web.de ([212.227.15.4]:64787 "EHLO mout.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753841Ab3BCXUP (ORCPT ); Sun, 3 Feb 2013 18:20:15 -0500 Received: from localhost ([93.182.149.207]) by smtp.web.de (mrweb103) with ESMTPSA (Nemesis) id 0MSai0-1URLEj1ouK-00RVCe; Mon, 04 Feb 2013 00:20:10 +0100 From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux-foundation.org Cc: Stephen Hemminger , netdev@vger.kernel.org, Simon Wunderlich , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [RFC PATCH] bridge: Add export of multicast database adjacent to net_dev Date: Mon, 4 Feb 2013 00:19:58 +0100 Message-Id: <1359933598-14438-1-git-send-email-linus.luessing@web.de> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-Provags-ID: V02:K0:8LYv4Lwmcop9fWOWiKEq8d/G4WusU/IPT2mIRVKy+BC /GA6aH18CkuCMxRWWGov4of9R219cZR2jE9iBmkzaopZQBCNst oyXLFnxhBpl/AB3dvubGB0blj528I7BKMoGQeWD0DGoJJ7alJu y/mAErUC3Q3P/2jCpxj/+XjBZxxXI0p79C6RSukLMh7ocXJpvd +quUTjXlt1jb5T+y9qGPQ== Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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. A multicast optimization currently implemented for batman-adv requires this data. Signed-off-by: Linus Lüssing --- include/linux/if_bridge.h | 17 +++++++++++++ net/bridge/br_multicast.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 11 --------- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 1085ffe..86d71a8 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -16,9 +16,26 @@ #include #include +struct br_ip { + union { + __be32 ip4; +#if IS_ENABLED(CONFIG_IPV6) + struct in6_addr ip6; +#endif + } u; + __be16 proto; +}; + +struct br_ip_list { + struct list_head list; + struct br_ip addr; +}; + extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); typedef int br_should_route_hook_t(struct sk_buff *skb); extern br_should_route_hook_t __rcu *br_should_route_hook; +extern int br_multicast_list_adjacent(struct net_device *net_dev, + struct list_head *br_ip_list); #endif diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6d6f265..773a8c2 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -1846,3 +1847,61 @@ unlock: return err; } + +/** + * br_multicast_list_adjacent - Returns snooped multicast addresses + * @dev: The bridge port adjacent to which to retrieve addresses + * @br_ip_list: The list to store found, snooped multicast IP addresses in + * + * Creates a list of IP addresses (struct br_ip_list) sensed by the multicast + * snooping feature on all bridge ports of dev's bridge device, excluding + * the addresses from dev itself. + * + * Returns the number of items added to br_ip_list. + * + * Notes: + * - br_ip_list needs to be initialized by caller + * - br_ip_list might contain duplicates in the end + * (needs to be taken care of by caller) + * - br_ip_list needs to be freed by caller + */ +int br_multicast_list_adjacent(struct net_device *dev, + struct list_head *br_ip_list) +{ + struct net_bridge *br; + struct net_bridge_port *port; + struct net_bridge_port_group *group; + struct br_ip_list *entry; + struct hlist_node *p; + int count = 0; + + rcu_read_lock(); + if (!br_ip_list || !br_port_exists(dev)) + goto unlock; + + port = br_port_get_rcu(dev); + if (!port || !port->br) + goto unlock; + + br = port->br; + + list_for_each_entry_rcu(port, &br->port_list, list) { + if (!port->dev || port->dev == dev) + continue; + + hlist_for_each_entry_rcu(group, p, &port->mglist, mglist) { + entry = kmalloc(sizeof(struct br_ip_list), GFP_ATOMIC); + if (!entry) + goto unlock; + + entry->addr = group->addr; + list_add(&entry->list, br_ip_list); + count++; + } + } + +unlock: + rcu_read_unlock(); + return count; +} +EXPORT_SYMBOL(br_multicast_list_adjacent); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 711094a..edf3fd8 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -52,17 +52,6 @@ struct mac_addr unsigned char addr[6]; }; -struct br_ip -{ - union { - __be32 ip4; -#if IS_ENABLED(CONFIG_IPV6) - struct in6_addr ip6; -#endif - } u; - __be16 proto; -}; - struct net_bridge_fdb_entry { struct hlist_node hlist;