[v6,3/3] batman-adv: Add debugfs table for mcast flags
Commit Message
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.
Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
debugfs.c | 21 ++++++++++++
multicast.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
multicast.h | 2 ++
3 files changed, 133 insertions(+)
Comments
> --- a/multicast.c
> +++ b/multicast.c
> @@ -995,6 +995,116 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
> }
>
> /**
> + * batadv_mcast_flags_print_header - print own mcast flags to debugfs
> table + * @bat_priv: the bat priv with all the soft interface information
> + * @seq: debugfs table seq_file struct
> + *
> + * Prints our own multicast flags including a more specific reason why
> + * they are set, that is prints the bridge and querier state too, to
> + * the debugfs table specified via @seq.
> + */
> +static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv,
> + struct seq_file *seq)
> +{
> + struct net_device *dev = bat_priv->soft_iface;
> + uint8_t flags = bat_priv->mcast.flags;
> + char ip4_querier_c, ip6_querier_c, ip4_shadowed_c, ip6_shadowed_c;
> + bool bridged = batadv_mcast_has_bridge(bat_priv);
> +
> + if (bridged) {
> + bool ip4_querier, ip6_querier, ip4_shadowed, ip6_shadowed;
> +
> + ip4_querier = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
> + ip6_querier = br_multicast_has_querier_anywhere(dev,
> + ETH_P_IPV6);
> + ip4_shadowed = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
> + ip6_shadowed = br_multicast_has_querier_adjacent(dev,
> + ETH_P_IPV6);
Isn't this info already in bat_priv->querier_ipv4/v6->exists/shadowed? Should
avoid the 80 lines workarounds you are having here, or maybe you are able to
squash that with the lines below.
> +
> + ip4_querier_c = !ip4_querier ? '+' : '-';
> + ip6_querier_c = !ip6_querier ? '+' : '-';
> + ip4_shadowed_c = ip4_shadowed ? '+' : '-';
> + ip6_shadowed_c = ip6_shadowed ? '+' : '-';
> + } else {
> + ip4_querier_c = '?';
> + ip6_querier_c = '?';
> + ip4_shadowed_c = '?';
> + ip6_shadowed_c = '?';
> + }
> +
> + seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n",
> + flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES ? 'U' : '.',
> + flags & BATADV_MCAST_WANT_ALL_IPV4 ? '4' : '.',
> + flags & BATADV_MCAST_WANT_ALL_IPV6 ? '6' : '.');
> + seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? '+' : '-');
What does the U mean? Unsnoopables? The U-flag? (just noticed that this "U-
Flag" is also used without explanation in the previous patch).
> + seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n",
> + ip4_querier_c, ip6_querier_c);
> + seq_printf(seq, "* Shadowing IGMP/MLD Querier [4/6]:\t%c/%c\n",
> + ip4_shadowed_c, ip6_shadowed_c);
> + seq_puts(seq, "-------------------------------------------\n");
> + seq_printf(seq, " %-10s %s\n", "Originator", "Flags");
> +}
> +
> +/**
> + * batadv_mcast_flags_seq_print_text - print the mcast flags of other
> nodes + * @seq: seq file to print on
> + * @offset: not used
> + *
> + * This prints a table of (primary) originators and their according
> + * multicast flags, including (in the header) our own.
> + */
> +int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
> +{
> + struct net_device *net_dev = (struct net_device *)seq->private;
> + struct batadv_priv *bat_priv = netdev_priv(net_dev);
> + struct batadv_hard_iface *primary_if;
> + struct batadv_hashtable *hash = bat_priv->orig_hash;
> + struct batadv_orig_node *orig_node;
> + struct hlist_head *head;
> + uint8_t flags;
> + uint32_t i;
> +
> + primary_if = batadv_seq_print_text_primary_if_get(seq);
> + if (!primary_if)
> + return 0;
> +
> + batadv_mcast_flags_print_header(bat_priv, seq);
> +
> + for (i = 0; i < hash->size; i++) {
> + head = &hash->table[i];
> +
> + rcu_read_lock();
> + hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
> + if (!(orig_node->capa_initialized &
> + BATADV_ORIG_CAPA_HAS_MCAST))
> + continue;
> +
> + flags = orig_node->mcast_flags;
> +
> + if (!(orig_node->capabilities &
> + BATADV_ORIG_CAPA_HAS_MCAST)) {
> + seq_printf(seq, "%pM -\n", orig_node->orig);
> + continue;
> + }
> +
> + seq_printf(seq, "%pM [%c%c%c]\n", orig_node->orig,
> + (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES ?
> + 'U' : '.'),
> + (flags & BATADV_MCAST_WANT_ALL_IPV4 ?
> + '4' : '.'),
> + (flags & BATADV_MCAST_WANT_ALL_IPV6 ?
> + '6' : '.'));
> + }
> + rcu_read_unlock();
> + }
> +
> + batadv_hardif_free_ref(primary_if);
> +
> + return 0;
> +}
> +
> +
> +/**
> * batadv_mcast_free - free the multicast optimizations structures
> * @bat_priv: the bat priv with all the soft interface information
> */
The rest looks good ... I'll need to test all that later. :)
Thanks,
Simon
@@ -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,
};
@@ -995,6 +995,116 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
}
/**
+ * batadv_mcast_flags_print_header - print own mcast flags to debugfs table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @seq: debugfs table seq_file struct
+ *
+ * Prints our own multicast flags including a more specific reason why
+ * they are set, that is prints the bridge and querier state too, to
+ * the debugfs table specified via @seq.
+ */
+static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv,
+ struct seq_file *seq)
+{
+ struct net_device *dev = bat_priv->soft_iface;
+ uint8_t flags = bat_priv->mcast.flags;
+ char ip4_querier_c, ip6_querier_c, ip4_shadowed_c, ip6_shadowed_c;
+ bool bridged = batadv_mcast_has_bridge(bat_priv);
+
+ if (bridged) {
+ bool ip4_querier, ip6_querier, ip4_shadowed, ip6_shadowed;
+
+ ip4_querier = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
+ ip6_querier = br_multicast_has_querier_anywhere(dev,
+ ETH_P_IPV6);
+ ip4_shadowed = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
+ ip6_shadowed = br_multicast_has_querier_adjacent(dev,
+ ETH_P_IPV6);
+
+ ip4_querier_c = !ip4_querier ? '+' : '-';
+ ip6_querier_c = !ip6_querier ? '+' : '-';
+ ip4_shadowed_c = ip4_shadowed ? '+' : '-';
+ ip6_shadowed_c = ip6_shadowed ? '+' : '-';
+ } else {
+ ip4_querier_c = '?';
+ ip6_querier_c = '?';
+ ip4_shadowed_c = '?';
+ ip6_shadowed_c = '?';
+ }
+
+ seq_printf(seq, "Multicast flags (own flags: [%c%c%c])\n",
+ flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES ? 'U' : '.',
+ flags & BATADV_MCAST_WANT_ALL_IPV4 ? '4' : '.',
+ flags & BATADV_MCAST_WANT_ALL_IPV6 ? '6' : '.');
+ seq_printf(seq, "* Bridged [U]\t\t\t\t%c\n", bridged ? '+' : '-');
+ seq_printf(seq, "* No IGMP/MLD Querier [4/6]:\t\t%c/%c\n",
+ ip4_querier_c, ip6_querier_c);
+ seq_printf(seq, "* Shadowing IGMP/MLD Querier [4/6]:\t%c/%c\n",
+ ip4_shadowed_c, ip6_shadowed_c);
+ seq_puts(seq, "-------------------------------------------\n");
+ seq_printf(seq, " %-10s %s\n", "Originator", "Flags");
+}
+
+/**
+ * batadv_mcast_flags_seq_print_text - print the mcast flags of other nodes
+ * @seq: seq file to print on
+ * @offset: not used
+ *
+ * This prints a table of (primary) originators and their according
+ * multicast flags, including (in the header) our own.
+ */
+int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
+{
+ struct net_device *net_dev = (struct net_device *)seq->private;
+ struct batadv_priv *bat_priv = netdev_priv(net_dev);
+ struct batadv_hard_iface *primary_if;
+ struct batadv_hashtable *hash = bat_priv->orig_hash;
+ struct batadv_orig_node *orig_node;
+ struct hlist_head *head;
+ uint8_t flags;
+ uint32_t i;
+
+ primary_if = batadv_seq_print_text_primary_if_get(seq);
+ if (!primary_if)
+ return 0;
+
+ batadv_mcast_flags_print_header(bat_priv, seq);
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+ if (!(orig_node->capa_initialized &
+ BATADV_ORIG_CAPA_HAS_MCAST))
+ continue;
+
+ flags = orig_node->mcast_flags;
+
+ if (!(orig_node->capabilities &
+ BATADV_ORIG_CAPA_HAS_MCAST)) {
+ seq_printf(seq, "%pM -\n", orig_node->orig);
+ continue;
+ }
+
+ seq_printf(seq, "%pM [%c%c%c]\n", orig_node->orig,
+ (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES ?
+ 'U' : '.'),
+ (flags & BATADV_MCAST_WANT_ALL_IPV4 ?
+ '4' : '.'),
+ (flags & BATADV_MCAST_WANT_ALL_IPV6 ?
+ '6' : '.'));
+ }
+ rcu_read_unlock();
+ }
+
+ batadv_hardif_free_ref(primary_if);
+
+ return 0;
+}
+
+
+/**
* batadv_mcast_free - free the multicast optimizations structures
* @bat_priv: the bat priv with all the soft interface information
*/
@@ -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);