batman-adv: Add multicast optimization support for bridged setups
PATCH v5 1/2 batman-adv: Add multicast optimization support for bridged setups
So far, the recently added multicast optimizations did not support a configuration where a bridge is on top of the soft-interface (e.g. bat0).
Now the Linux bridge code is able to provide us with the missing bits:
Multicast Listeners: The bridge hands us a list of multicast listeners it has detected behind the bridge which we will announce through the mesh via the translation table, allowing other nodes to direct multicast packets to these clients behind the bridge even with enabled multicast optimizations.
Queriers: The bridge informs us whether there is a selected IGMP or MLD querier behind the bridge or if there is no querier at all. In these cases we need all according IPv4 or IPv6 multicast traffic directed to us.
These two parts together allow us to serve all multicast listeners with IPv6 link-local multicast packets even when bridges are involved and our multicast optimizations enabled.
---
Changes in v5:
* none
Changes in v4:
* none
Changes in v3:
* Removed "RFC" tag in title again: The stubs and new export are upstream in net-next and therefore going to be included in 3.17
* Added some debug output:
* Two warning messages:
-> Old kernel version or no bridge IGMP/MLD snooping compiled
* New batman-adv log-level "mcast":
-> Logging mcast flag changes (a third debugging facility, a new table for debugfs for a global
mcast flag overview will be added in a separate patch later as discussed with Simon)
Changes in v2:
* fetching local (= on this same kernel) multicast listeners from the bridge instead of the bat0 interface if a bridge is present
- just like ip addresses and routes should be used from br0, the same goes for multicast listeners
* beautification of batadv_mcast_mla_br_addr_cpy(), now using already present functions from the kernel instead of own, hackish approach
* changed names of some goto-labels (not using "skip" anymore)
* using new, third bridge multicast export (because this export is not upstream yet, I've added the "RFC" in the title):
br_multicast_has_querier_anywhere()
* adding compat stubs for two bridge multicast exports, to make batman-adv compile- and usable even if a 3.16 kernel was compiled without bridge code - the stubs are supposed to be upstream in the bridge code in 3.17 (therefore just 'compat')
* updated kerneldocs for batadv_mcast_mla_bridge_get() and batadv_mcast_mla_softif_get()
* The two sentences in the commit message starting with "Queriers: ..." were slightly modified to include the third bridge multicast export
compat.c | 39 ++++++++++++ compat.h | 32 ++++++++++ main.h | 6 +- multicast.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 251 insertions(+), 19 deletions(-)
compat.c +39 -0
@@ -109,3 +109,42 @@ void batadv_free_rcu_tvlv_handler(struct rcu_head *rcu) }#endif /* < KERNEL_VERSION(3, 0, 0) */ + +#if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,16 ,0 ) + +int br_multicast_list_adjacent (struct net_device *dev, +struct list_head *br_ip_list) +{ +return 0 ; +} + +bool br_multicast_has_querier_adjacent (struct net_device *dev,int proto) +{ +return false; +} + +#endif /* < KERNEL_VERSION(3, 16, 0) */ + +#if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,17 ,0 ) + +bool br_multicast_has_querier_anywhere (struct net_device *dev,int proto) +{ +pr_warn_once ("Old kernel detected (< 3.17) - multicast optimizations disabled\n" ); + +return false; +} + +#if !(IS_ENABLED (CONFIG_BRIDGE ) &&IS_ENABLED (CONFIG_BRIDGE_IGMP_SNOOPING )) +int br_multicast_list_adjacent (struct net_device *dev, +struct list_head *br_ip_list) +{ +return 0 ; +} + +bool br_multicast_has_querier_adjacent (struct net_device *dev,int proto) +{ +return false; +} +#endif + +#endif /* < KERNEL_VERSION(3, 17, 0) */
compat.h +32 -0
@@ -240,6 +240,12 @@ static inline void skb_reset_mac_len(struct sk_buff *skb)#endif /* < KERNEL_VERSION(3, 0, 0) */ +#if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,1 ,0 ) + +#define IS_ENABLED (x) defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + +#endif /* < KERNEL_VERSION(3, 1, 0) */ +#if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,3 ,0 )#define batadv_interface_add_vid (x, y, z) \
@@ -444,6 +450,32 @@ static int __batadv_interface_kill_vid(struct net_device *dev, __be16 proto,\#define pskb_copy_for_clone pskb_copy +int br_multicast_list_adjacent (struct net_device *dev, +struct list_head *br_ip_list); +bool br_multicast_has_querier_adjacent (struct net_device *dev,int proto); + +struct br_ip { +union { +__be32 ip4; +#if IS_ENABLED (CONFIG_IPV6 ) +struct in6_addr ip6; +#endif + } u; +__be16 proto; +__u16 vid; +}; + +struct br_ip_list { +struct list_head list; +struct br_ip addr; +}; +#endif /* < KERNEL_VERSION(3, 16, 0) */ +#if LINUX_VERSION_CODE <KERNEL_VERSION (3 ,17 ,0 ) + +bool br_multicast_has_querier_anywhere (struct net_device *dev,int proto); + +#endif /* < KERNEL_VERSION(3, 17, 0) */ +#endif /* _NET_BATMAN_ADV_COMPAT_H_ */
main.h +5 -1
@@ -169,6 +169,7 @@ enum batadv_uev_type {#include <linux/netdevice.h> /* netdevice */ #include <linux/etherdevice.h> /* ethernet address classification */ #include <linux/if_ether.h> /* ethernet header */ +#include <linux/if_bridge.h> /* bridge / multicast-snooping communication */ #include <linux/poll.h> /* poll_table */ #include <linux/kthread.h> /* kernel threads */ #include <linux/pkt_sched.h> /* schedule types */
@@ -177,6 +178,7 @@ enum batadv_uev_type {#include <linux/slab.h> #include <net/sock.h> /* struct sock */ #include <net/addrconf.h> /* ipv6 address stuff */ +#include <net/ip.h> #include <linux/ip.h> #include <net/rtnetlink.h> #include <linux/jiffies.h>
@@ -223,6 +225,7 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);* @BATADV_DBG_BLA: bridge loop avoidance messages * @BATADV_DBG_DAT: ARP snooping and DAT related messages * @BATADV_DBG_NC: network coding related messages +* @BATADV_DBG_MCAST: multicast related messages * @BATADV_DBG_ALL: the union of all the above log levels */ enum batadv_dbg_level {
@@ -232,7 +235,8 @@ enum batadv_dbg_level {BATADV_DBG_BLA =BIT (3 ),BATADV_DBG_DAT =BIT (4 ),BATADV_DBG_NC =BIT (5 ), - BATADV_DBG_ALL = 63, +BATADV_DBG_MCAST =BIT (6 ), + BATADV_DBG_ALL = 127, };#ifdef CONFIG_BATMAN_ADV_DEBUG
multicast.c +175 -18
256 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v5 2/2 batman-adv: Add debugfs table for mcast flags
This patch adds a debugfs table with originators and their according multicast flags to help users figure out why multicast optimizations might be enabled or disabled for them.
---
Changes in v5:
* s/dat_cache/mcast_flags/ in kerneldoc (copy&paste error)
Changes in v4:
* initial {ad,e}dition of this patch
debugfs.c | 21 +++++++++++++++++++ multicast.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h | 2 ++ 3 files changed, 88 insertions(+)
debugfs.c +21 -0
@@ -30,6 +30,7 @@#include "bridge_loop_avoidance.h" #include "distributed-arp-table.h" #include "network-coding.h" +#include "multicast.h" static struct dentry *batadv_debugfs;
@@ -332,6 +333,20 @@ static int batadv_nc_nodes_open(struct inode *inode, struct file *file) }#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +/** +* batadv_mcast_flags_open - Prepare file handler for reads from mcast_flags +* @inode: inode which was opened +* @file: file handle to be initialized +*/ +static int batadv_mcast_flags_open (struct inode *inode,struct file *file) +{ +struct net_device *net_dev = (struct net_device *)inode->i_private; + +return single_open (file, batadv_mcast_flags_seq_print_text, net_dev); +} +#endif +#define BATADV_DEBUGINFO (_name, _mode, _open) \ struct batadv_debuginfo batadv_debuginfo_##_name = { \ .attr = { .name = __stringify(_name), \
@@ -372,6 +387,9 @@ static BATADV_DEBUGINFO(transtable_local, S_IRUGO,#ifdef CONFIG_BATMAN_ADV_NC static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);#endif +#ifdef CONFIG_BATMAN_ADV_MCAST +static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open); +#endif static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { &batadv_debuginfo_originators,
@@ -388,6 +406,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {#ifdef CONFIG_BATMAN_ADV_NC &batadv_debuginfo_nc_nodes,#endif +#ifdef CONFIG_BATMAN_ADV_MCAST + &batadv_debuginfo_mcast_flags, +#endif NULL, };
multicast.c +65 -0
71 lines not on this page · raw message
multicast.h +2 -0
@@ -42,6 +42,8 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,void batadv_mcast_init (struct batadv_priv *bat_priv); +int batadv_mcast_flags_seq_print_text (struct seq_file *seq,void *offset); +void batadv_mcast_free (struct batadv_priv *bat_priv);void batadv_mcast_purge_orig (struct batadv_orig_node *orig_node);
Signature · 1 line
1.7.10.4
Re: [B.A.T.M.A.N.] [PATCHv5 2/2] batman-adv: Add debugfs table for mcast flags
debugfs.c static int batadv_nc_nodes_open(struct inode *inode, struct file *file) · line 338
Quoted 3 lines · On Tuesday 15 July 2014 04:38:18 Linus Lüssing wrote:
debugfs.c +3
-0+#ifdef CONFIG_BATMAN_ADV_MCAST +/** +* batadv_mcast_flags_open - Prepare file handler for reads from mcast_flags
No upper case please.
multicast.c void batadv_mcast_init(struct batadv_priv *bat_priv) · line 917
Quoted 5 lines
multicast.c +5
-0+rcu_read_lock (); +hlist_for_each_entry_rcu (orig_node, head, hash_entry) { +if (!(orig_node->capa_initialized & +BATADV_ORIG_CAPA_HAS_MCAST )) +continue ;
Why not printing '-' in this case as well ?
Cheers,
Marek
Re: [B.A.T.M.A.N.] [PATCHv5 2/2] batman-adv: Add debugfs table for mcast flags
Hi Marek,
Quoted 6 lines · Marek Lindner
debugfs.c static int batadv_nc_nodes_open(struct inode *inode, struct file *file) · line 338
Quoted 3 lines · On Tuesday 15 July 2014 04:38:18 Linus Lüssing wrote:
debugfs.c +3
-0+#ifdef CONFIG_BATMAN_ADV_MCAST +/** +* batadv_mcast_flags_open - Prepare file handler for reads from mcast_flags No upper case please.
k, right
Quoted 9 lines
multicast.c void batadv_mcast_init(struct batadv_priv *bat_priv) · line 917
Quoted 7 lines
multicast.c +5
-0+rcu_read_lock (); +hlist_for_each_entry_rcu (orig_node, head, hash_entry) { +if (!(orig_node->capa_initialized & +BATADV_ORIG_CAPA_HAS_MCAST )) +continue ;Why not printing '-' in this case as well ?
Hm, my intention was to only list primary originators. Which the capa_initialized can provide.
Every other, secondary interface originator is ignored in the calculations, too, since these will never provide (and don't need to) provide a TVLV anyways.
Does this make sense?
Quoted 3 lines
Cheers,
Marek
Cheers, Linus
Re: [B.A.T.M.A.N.] [PATCHv5 2/2] batman-adv: Add debugfs table for mcast flags
In reply to Marek LindnerQuoted 8 lines · Marek Lindner
multicast.c void batadv_mcast_init(struct batadv_priv *bat_priv) · line 917
Quoted 5 lines · On Tuesday 15 July 2014 04:38:18 Linus Lüssing wrote:
multicast.c +5
-0+rcu_read_lock (); +hlist_for_each_entry_rcu (orig_node, head, hash_entry) { +if (!(orig_node->capa_initialized & +BATADV_ORIG_CAPA_HAS_MCAST )) +continue ;Why not printing '-' in this case as well ?
Had been giving a reason on IRC already, but maybe it's better to write it here again so that the reason doesn't get lost:
The idea was, to only have one entry per batman-adv node. Not per originator. Secondary interface originators aren't considered in the multicast logic anyways, so they might be confusing for the user when doing manual checking and counting.
In other words, '-' is supposed to mean that this is an outdated node not supporting multicast optimizations and not having the according TVLV and that people should consider upgrading it.
Cheers, Linus
Quoted 7 lines · On Tuesday 15 July 2014 04:38:17 Linus Lüssing wrote:
/**
+ *batadv_mcast_get_bridge- get the bridge on top of the softif if it exists
+ * @soft_iface: netdev struct of the mesh interface
+ *
+ * Returns either a bridge interface on top of our soft interface or
+ * NULL if no such bridge exists.
+ */
The kernel doc should mention that the bridge object's refcount is increased (if found).
Quoted 16 lines
multicast.c +14
-0+update:if (!bat_priv->mcast.enabled || mcast_data.flags != bat_priv->mcast.flags) { +if (!bat_priv->mcast.enabled) +sprintf (str_flags_old,"<undefined>" ); +else +sprintf (str_flags_old,"[%c%c%c]" , + (bat_priv->mcast.flags & +BATADV_MCAST_WANT_ALL_UNSNOOPABLES ? +'U' :'.' ), + (bat_priv->mcast.flags & +BATADV_MCAST_WANT_ALL_IPV4 ?'4' :'.' ), + (bat_priv->mcast.flags & +BATADV_MCAST_WANT_ALL_IPV6 ?'6' :'.' )); + + sprintf(str_flags_new, "[%c%c%c]",
multicast.c static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) · line 363
Quoted 10 lines
multicast.c +10
-0+ (mcast_data.flags & +BATADV_MCAST_WANT_ALL_UNSNOOPABLES ?'U' :'.' ), + (mcast_data.flags & +BATADV_MCAST_WANT_ALL_IPV4 ?'4' :'.' ), + (mcast_data.flags & + BATADV_MCAST_WANT_ALL_IPV6 ? '6' : '.')); + +batadv_dbg (BATADV_DBG_MCAST , bat_priv, +"Changing multicast flags from '%s' to '%s'\n" , + str_flags_old, str_flags_new);
IMHO the debug log should be more verbose about why a given flag was enabled or disabled. As it is now, one can't learn anything from this log that isn't already part of the mcast table. If you think that is too big of a change you can also move this chunk into a separate patch.
Cheers,
Marek