All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] batman-adv: routeable multicast preparations
@ 2019-05-07  3:48 T_X
  2019-05-07  3:48 ` [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section T_X
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: T_X @ 2019-05-07  3:48 UTC (permalink / raw)
  To: b.a.t.m.a.n

This patchset provides some code restructuring in preparation for the
support of routeable multicast addresses.

The first one adds a slightly cleaner separation of fetching and
updating. And by that allows shortening the newly introduced spin-lock.

The second one swaps the kernel MAC multicast list with the equivalent
IPv4 and IPv6 ones: This allows an easier filtering later.

Finally patch 3 is a first application of such filtering and allows
omitting some redundant address additions to the TT. Later, the same
will be necessary for routeable multicast addresses.

---

Changelog v2: 

* rebased to master
* removed already applied patch
  ("batman-adv: mcast: fix multicast tt/tvlv worker locking")
* split patchset in two with the intention to ease reviewing
  (no code changes, just omitted the last two patches)

* kerneldoc: alignment for batadv_mcast_mla_flags_update()
  [PATCH 2/6] / [PATCH v2 1/3]
* fixed compile issues due to a duplicated member in struct batadv_priv_mcast
  [PATCH 2/6] / [PATCH v2 1/3]
* kerneldoc: added missing @flags for batadv_mcast_mla_flags_update()
  [PATCH 2/6] / [PATCH v2 1/3]
* kerneldoc: @flags -> @tvlv_flags in struct batadv_mcast_mla_flags
  [PATCH 2/6] / [PATCH v2 1/3]



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section
  2019-05-07  3:48 [PATCH v2 0/3] batman-adv: routeable multicast preparations T_X
@ 2019-05-07  3:48 ` T_X
  2019-05-07  3:48 ` [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead T_X
  2019-05-07  3:48 ` [PATCH v2 3/3] batman-adv: mcast: avoid redundant multicast TT entries with bridges T_X
  2 siblings, 0 replies; 5+ messages in thread
From: T_X @ 2019-05-07  3:48 UTC (permalink / raw)
  To: b.a.t.m.a.n

From: Linus Lüssing <linus.luessing@c0d3.blue>

It is not necessary to hold the mla_lock spinlock during the whole
multicast tt/tvlv worker callback. Just holding it during the checks and
updates of the bat_priv stored multicast flags and mla_list is enough.

Therefore this patch splits batadv_mcast_mla_tvlv_update() in two:
batadv_mcast_mla_flags_get() at the beginning of the worker to gather
and calculate the new multicast flags, which does not need any locking
as it neither reads from nor writes to bat_priv->mcast.

And batadv_mcast_mla_flags_update() at the end of the worker which
commits the newly calculated flags and lists to bat_priv->mcast and
therefore needs the lock.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
 net/batman-adv/multicast.c      | 274 ++++++++++++++++----------------
 net/batman-adv/soft-interface.c |   5 -
 net/batman-adv/types.h          |  38 +++--
 3 files changed, 165 insertions(+), 152 deletions(-)

diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index ec54e236..af0e2ce8 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -71,6 +71,80 @@ static void batadv_mcast_start_timer(struct batadv_priv *bat_priv)
 			   msecs_to_jiffies(BATADV_MCAST_WORK_PERIOD));
 }
 
+/**
+ * batadv_mcast_has_bridge() - check whether the soft-iface is bridged
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Checks whether there is a bridge on top of our soft interface.
+ *
+ * Return: true if there is a bridge, false otherwise.
+ */
+static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
+{
+	struct net_device *upper = bat_priv->soft_iface;
+
+	rcu_read_lock();
+	do {
+		upper = netdev_master_upper_dev_get_rcu(upper);
+	} while (upper && !(upper->priv_flags & IFF_EBRIDGE));
+	rcu_read_unlock();
+
+	return upper;
+}
+
+/**
+ * batadv_mcast_mla_flags_get() - get the new multicast flags
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Return: A set of flags for the current/next TVLV, querier and
+ * bridge state.
+ */
+static struct batadv_mcast_mla_flags
+batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
+{
+	struct net_device *dev = bat_priv->soft_iface;
+	struct batadv_mcast_querier_state *qr4, *qr6;
+	struct batadv_mcast_mla_flags mla_flags;
+
+	memset(&mla_flags, 0, sizeof(mla_flags));
+	mla_flags.enabled = 1;
+
+	if (!batadv_mcast_has_bridge(bat_priv))
+		return mla_flags;
+
+	mla_flags.bridged = 1;
+	qr4 = &mla_flags.querier_ipv4;
+	qr6 = &mla_flags.querier_ipv6;
+
+	if (!IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING))
+		pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n");
+
+	qr4->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
+	qr4->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
+
+	qr6->exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6);
+	qr6->shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6);
+
+	mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES;
+
+	/* 1) If no querier exists at all, then multicast listeners on
+	 *    our local TT clients behind the bridge will keep silent.
+	 * 2) If the selected querier is on one of our local TT clients,
+	 *    behind the bridge, then this querier might shadow multicast
+	 *    listeners on our local TT clients, behind this bridge.
+	 *
+	 * In both cases, we will signalize other batman nodes that
+	 * we need all multicast traffic of the according protocol.
+	 */
+	if (!qr4->exists || qr4->shadowing)
+		mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV4;
+
+	if (!qr6->exists || qr6->shadowing)
+		mla_flags.tvlv_flags |= BATADV_MCAST_WANT_ALL_IPV6;
+
+	return mla_flags;
+}
+
 /**
  * batadv_mcast_get_bridge() - get the bridge on top of the softif if it exists
  * @soft_iface: netdev struct of the mesh interface
@@ -127,9 +201,9 @@ static bool batadv_mcast_addr_is_ipv6(const u8 *addr)
 
 /**
  * batadv_mcast_mla_softif_get() - get softif multicast listeners
- * @bat_priv: the bat priv with all the soft interface information
  * @dev: the device to collect multicast addresses from
  * @mcast_list: a list to put found addresses into
+ * @flags: flags indicating the new multicast state
  *
  * Collects multicast addresses of multicast listeners residing
  * on this kernel on the given soft interface, dev, in
@@ -144,12 +218,13 @@ static bool batadv_mcast_addr_is_ipv6(const u8 *addr)
  * Return: -ENOMEM on memory allocation error or the number of
  * items added to the mcast_list otherwise.
  */
-static int batadv_mcast_mla_softif_get(struct batadv_priv *bat_priv,
-				       struct net_device *dev,
-				       struct hlist_head *mcast_list)
+static int
+batadv_mcast_mla_softif_get(struct net_device *dev,
+			    struct hlist_head *mcast_list,
+			    struct batadv_mcast_mla_flags *flags)
 {
-	bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4;
-	bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6;
+	bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
+	bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
 	struct net_device *bridge = batadv_mcast_get_bridge(dev);
 	struct netdev_hw_addr *mc_list_entry;
 	struct batadv_hw_addr *new;
@@ -227,9 +302,9 @@ static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src)
 
 /**
  * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners
- * @bat_priv: the bat priv with all the soft interface information
  * @dev: a bridge slave whose bridge to collect multicast addresses from
  * @mcast_list: a list to put found addresses into
+ * @flags: flags indicating the new multicast state
  *
  * Collects multicast addresses of multicast listeners residing
  * on foreign, non-mesh devices which we gave access to our mesh via
@@ -239,13 +314,13 @@ static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src)
  * Return: -ENOMEM on memory allocation error or the number of
  * items added to the mcast_list otherwise.
  */
-static int batadv_mcast_mla_bridge_get(struct batadv_priv *bat_priv,
-				       struct net_device *dev,
-				       struct hlist_head *mcast_list)
+static int batadv_mcast_mla_bridge_get(struct net_device *dev,
+				       struct hlist_head *mcast_list,
+				       struct batadv_mcast_mla_flags *flags)
 {
 	struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
-	bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4;
-	bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6;
+	bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
+	bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
 	struct br_ip_list *br_ip_entry, *tmp;
 	struct batadv_hw_addr *new;
 	u8 mcast_addr[ETH_ALEN];
@@ -369,27 +444,6 @@ static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
 	}
 }
 
-/**
- * batadv_mcast_has_bridge() - check whether the soft-iface is bridged
- * @bat_priv: the bat priv with all the soft interface information
- *
- * Checks whether there is a bridge on top of our soft interface.
- *
- * Return: true if there is a bridge, false otherwise.
- */
-static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
-{
-	struct net_device *upper = bat_priv->soft_iface;
-
-	rcu_read_lock();
-	do {
-		upper = netdev_master_upper_dev_get_rcu(upper);
-	} while (upper && !(upper->priv_flags & IFF_EBRIDGE));
-	rcu_read_unlock();
-
-	return upper;
-}
-
 /**
  * batadv_mcast_querier_log() - debug output regarding the querier status on
  *  link
@@ -424,7 +478,7 @@ batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
 		batadv_info(bat_priv->soft_iface,
 			    "%s Querier disappeared - multicast optimizations disabled\n",
 			    str_proto);
-	else if (!bat_priv->mcast.bridged && !new_state->exists)
+	else if (!bat_priv->mcast.mla_flags.bridged && !new_state->exists)
 		batadv_info(bat_priv->soft_iface,
 			    "No %s Querier present - multicast optimizations disabled\n",
 			    str_proto);
@@ -446,9 +500,7 @@ batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
  * batadv_mcast_bridge_log() - debug output for topology changes in bridged
  *  setups
  * @bat_priv: the bat priv with all the soft interface information
- * @bridged: a flag about whether the soft interface is currently bridged or not
- * @querier_ipv4: (maybe) new status of a potential, selected IGMP querier
- * @querier_ipv6: (maybe) new status of a potential, selected MLD querier
+ * @new_flags: flags indicating the new multicast state
  *
  * If no bridges are ever used on this node, then this function does nothing.
  *
@@ -461,38 +513,40 @@ batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
  * multicast flags this node is going to set.
  */
 static void
-batadv_mcast_bridge_log(struct batadv_priv *bat_priv, bool bridged,
-			struct batadv_mcast_querier_state *querier_ipv4,
-			struct batadv_mcast_querier_state *querier_ipv6)
+batadv_mcast_bridge_log(struct batadv_priv *bat_priv,
+			struct batadv_mcast_mla_flags *new_flags)
 {
-	if (!bat_priv->mcast.bridged && bridged)
+	struct batadv_mcast_mla_flags *old_flags = &bat_priv->mcast.mla_flags;
+
+	if (!old_flags->bridged && new_flags->bridged)
 		batadv_dbg(BATADV_DBG_MCAST, bat_priv,
 			   "Bridge added: Setting Unsnoopables(U)-flag\n");
-	else if (bat_priv->mcast.bridged && !bridged)
+	else if (old_flags->bridged && !new_flags->bridged)
 		batadv_dbg(BATADV_DBG_MCAST, bat_priv,
 			   "Bridge removed: Unsetting Unsnoopables(U)-flag\n");
 
-	if (bridged) {
+	if (new_flags->bridged) {
 		batadv_mcast_querier_log(bat_priv, "IGMP",
-					 &bat_priv->mcast.querier_ipv4,
-					 querier_ipv4);
+					 &old_flags->querier_ipv4,
+					 &new_flags->querier_ipv4);
 		batadv_mcast_querier_log(bat_priv, "MLD",
-					 &bat_priv->mcast.querier_ipv6,
-					 querier_ipv6);
+					 &old_flags->querier_ipv6,
+					 &new_flags->querier_ipv6);
 	}
 }
 
 /**
  * batadv_mcast_flags_logs() - output debug information about mcast flag changes
  * @bat_priv: the bat priv with all the soft interface information
- * @flags: flags indicating the new multicast state
+ * @flags: TVLV flags indicating the new multicast state
  *
- * Whenever the multicast flags this nodes announces changes (@mcast_flags vs.
- * bat_priv->mcast.flags), this notifies userspace via the 'mcast' log level.
+ * Whenever the multicast TVLV flags this nodes announces change this notifies
+ * userspace via the 'mcast' log level.
  */
 static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
 {
-	u8 old_flags = bat_priv->mcast.flags;
+	bool old_enabled = bat_priv->mcast.mla_flags.enabled;
+	u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags;
 	char str_old_flags[] = "[...]";
 
 	sprintf(str_old_flags, "[%c%c%c]",
@@ -502,85 +556,39 @@ static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
 
 	batadv_dbg(BATADV_DBG_MCAST, bat_priv,
 		   "Changing multicast flags from '%s' to '[%c%c%c]'\n",
-		   bat_priv->mcast.enabled ? str_old_flags : "<undefined>",
+		   old_enabled ? str_old_flags : "<undefined>",
 		   (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.',
 		   (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.',
 		   (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.');
 }
 
 /**
- * batadv_mcast_mla_tvlv_update() - update multicast tvlv
+ * batadv_mcast_mla_flags_update() - update multicast flags
  * @bat_priv: the bat priv with all the soft interface information
+ * @flags: flags indicating the new multicast state
  *
  * Updates the own multicast tvlv with our current multicast related settings,
  * capabilities and inabilities.
- *
- * Return: false if we want all IPv4 && IPv6 multicast traffic and true
- * otherwise.
  */
-static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
+static void
+batadv_mcast_mla_flags_update(struct batadv_priv *bat_priv,
+			      struct batadv_mcast_mla_flags *flags)
 {
 	struct batadv_tvlv_mcast_data mcast_data;
-	struct batadv_mcast_querier_state querier4 = {false, false};
-	struct batadv_mcast_querier_state querier6 = {false, false};
-	struct net_device *dev = bat_priv->soft_iface;
-	bool bridged;
 
-	mcast_data.flags = BATADV_NO_FLAGS;
+	if (!memcmp(flags, &bat_priv->mcast.mla_flags, sizeof(*flags)))
+		return;
+
+	batadv_mcast_bridge_log(bat_priv, flags);
+	batadv_mcast_flags_log(bat_priv, flags->tvlv_flags);
+
+	mcast_data.flags = flags->tvlv_flags;
 	memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
 
-	bridged = batadv_mcast_has_bridge(bat_priv);
-	if (!bridged)
-		goto update;
+	batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2,
+				       &mcast_data, sizeof(mcast_data));
 
-	if (!IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING))
-		pr_warn_once("No bridge IGMP snooping compiled - multicast optimizations disabled\n");
-
-	querier4.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IP);
-	querier4.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IP);
-
-	querier6.exists = br_multicast_has_querier_anywhere(dev, ETH_P_IPV6);
-	querier6.shadowing = br_multicast_has_querier_adjacent(dev, ETH_P_IPV6);
-
-	mcast_data.flags |= BATADV_MCAST_WANT_ALL_UNSNOOPABLES;
-
-	/* 1) If no querier exists at all, then multicast listeners on
-	 *    our local TT clients behind the bridge will keep silent.
-	 * 2) If the selected querier is on one of our local TT clients,
-	 *    behind the bridge, then this querier might shadow multicast
-	 *    listeners on our local TT clients, behind this bridge.
-	 *
-	 * In both cases, we will signalize other batman nodes that
-	 * we need all multicast traffic of the according protocol.
-	 */
-	if (!querier4.exists || querier4.shadowing)
-		mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV4;
-
-	if (!querier6.exists || querier6.shadowing)
-		mcast_data.flags |= BATADV_MCAST_WANT_ALL_IPV6;
-
-update:
-	batadv_mcast_bridge_log(bat_priv, bridged, &querier4, &querier6);
-
-	bat_priv->mcast.querier_ipv4.exists = querier4.exists;
-	bat_priv->mcast.querier_ipv4.shadowing = querier4.shadowing;
-
-	bat_priv->mcast.querier_ipv6.exists = querier6.exists;
-	bat_priv->mcast.querier_ipv6.shadowing = querier6.shadowing;
-
-	bat_priv->mcast.bridged = bridged;
-
-	if (!bat_priv->mcast.enabled ||
-	    mcast_data.flags != bat_priv->mcast.flags) {
-		batadv_mcast_flags_log(bat_priv, mcast_data.flags);
-		batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 2,
-					       &mcast_data, sizeof(mcast_data));
-		bat_priv->mcast.flags = mcast_data.flags;
-		bat_priv->mcast.enabled = true;
-	}
-
-	return !(mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV4 &&
-		 mcast_data.flags & BATADV_MCAST_WANT_ALL_IPV6);
+	bat_priv->mcast.mla_flags = *flags;
 }
 
 /**
@@ -599,22 +607,24 @@ static void __batadv_mcast_mla_update(struct batadv_priv *bat_priv)
 {
 	struct net_device *soft_iface = bat_priv->soft_iface;
 	struct hlist_head mcast_list = HLIST_HEAD_INIT;
+	struct batadv_mcast_mla_flags flags;
 	int ret;
 
-	if (!batadv_mcast_mla_tvlv_update(bat_priv))
-		goto update;
+	flags = batadv_mcast_mla_flags_get(bat_priv);
 
-	ret = batadv_mcast_mla_softif_get(bat_priv, soft_iface, &mcast_list);
+	ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list, &flags);
 	if (ret < 0)
 		goto out;
 
-	ret = batadv_mcast_mla_bridge_get(bat_priv, soft_iface, &mcast_list);
+	ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list, &flags);
 	if (ret < 0)
 		goto out;
 
-update:
+	spin_lock(&bat_priv->mcast.mla_lock);
 	batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
 	batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
+	batadv_mcast_mla_flags_update(bat_priv, &flags);
+	spin_unlock(&bat_priv->mcast.mla_lock);
 
 out:
 	batadv_mcast_mla_list_free(&mcast_list);
@@ -639,10 +649,7 @@ static void batadv_mcast_mla_update(struct work_struct *work)
 	priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
 	bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);
 
-	spin_lock(&bat_priv->mcast.mla_lock);
 	__batadv_mcast_mla_update(bat_priv);
-	spin_unlock(&bat_priv->mcast.mla_lock);
-
 	batadv_mcast_start_timer(bat_priv);
 }
 
@@ -1417,15 +1424,16 @@ void batadv_mcast_init(struct batadv_priv *bat_priv)
 static void batadv_mcast_flags_print_header(struct batadv_priv *bat_priv,
 					    struct seq_file *seq)
 {
-	u8 flags = bat_priv->mcast.flags;
+	struct batadv_mcast_mla_flags *mla_flags = &bat_priv->mcast.mla_flags;
 	char querier4, querier6, shadowing4, shadowing6;
-	bool bridged = bat_priv->mcast.bridged;
+	bool bridged = mla_flags->bridged;
+	u8 flags = mla_flags->tvlv_flags;
 
 	if (bridged) {
-		querier4 = bat_priv->mcast.querier_ipv4.exists ? '.' : '4';
-		querier6 = bat_priv->mcast.querier_ipv6.exists ? '.' : '6';
-		shadowing4 = bat_priv->mcast.querier_ipv4.shadowing ? '4' : '.';
-		shadowing6 = bat_priv->mcast.querier_ipv6.shadowing ? '6' : '.';
+		querier4 = mla_flags->querier_ipv4.exists ? '.' : '4';
+		querier6 = mla_flags->querier_ipv6.exists ? '.' : '6';
+		shadowing4 = mla_flags->querier_ipv4.shadowing ? '4' : '.';
+		shadowing6 = mla_flags->querier_ipv6.shadowing ? '6' : '.';
 	} else {
 		querier4 = '?';
 		querier6 = '?';
@@ -1517,19 +1525,19 @@ int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
 int batadv_mcast_mesh_info_put(struct sk_buff *msg,
 			       struct batadv_priv *bat_priv)
 {
-	u32 flags = bat_priv->mcast.flags;
+	u32 flags = bat_priv->mcast.mla_flags.tvlv_flags;
 	u32 flags_priv = BATADV_NO_FLAGS;
 
-	if (bat_priv->mcast.bridged) {
+	if (bat_priv->mcast.mla_flags.bridged) {
 		flags_priv |= BATADV_MCAST_FLAGS_BRIDGED;
 
-		if (bat_priv->mcast.querier_ipv4.exists)
+		if (bat_priv->mcast.mla_flags.querier_ipv4.exists)
 			flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS;
-		if (bat_priv->mcast.querier_ipv6.exists)
+		if (bat_priv->mcast.mla_flags.querier_ipv6.exists)
 			flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS;
-		if (bat_priv->mcast.querier_ipv4.shadowing)
+		if (bat_priv->mcast.mla_flags.querier_ipv4.shadowing)
 			flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING;
-		if (bat_priv->mcast.querier_ipv6.shadowing)
+		if (bat_priv->mcast.mla_flags.querier_ipv6.shadowing)
 			flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING;
 	}
 
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index a7677e1d..887d9077 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -803,11 +803,6 @@ static int batadv_softif_init_late(struct net_device *dev)
 	atomic_set(&bat_priv->distributed_arp_table, 1);
 #endif
 #ifdef CONFIG_BATMAN_ADV_MCAST
-	bat_priv->mcast.querier_ipv4.exists = false;
-	bat_priv->mcast.querier_ipv4.shadowing = false;
-	bat_priv->mcast.querier_ipv6.exists = false;
-	bat_priv->mcast.querier_ipv6.shadowing = false;
-	bat_priv->mcast.flags = BATADV_NO_FLAGS;
 	atomic_set(&bat_priv->multicast_mode, 1);
 	atomic_set(&bat_priv->multicast_fanout, 16);
 	atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 74b64473..3212cfc9 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1168,6 +1168,26 @@ struct batadv_mcast_querier_state {
 	unsigned char shadowing:1;
 };
 
+/**
+ * struct batadv_mcast_mla_flags - flags for the querier, bridge and tvlv state
+ */
+struct batadv_mcast_mla_flags {
+	/** @querier_ipv4: the current state of an IGMP querier in the mesh */
+	struct batadv_mcast_querier_state querier_ipv4;
+
+	/** @querier_ipv6: the current state of an MLD querier in the mesh */
+	struct batadv_mcast_querier_state querier_ipv6;
+
+	/** @enabled: whether the multicast tvlv is currently enabled */
+	unsigned char enabled:1;
+
+	/** @bridged: whether the soft interface has a bridge on top */
+	unsigned char bridged:1;
+
+	/** @tvlv_flags: the flags we have last sent in our mcast tvlv */
+	u8 tvlv_flags;
+};
+
 /**
  * struct batadv_priv_mcast - per mesh interface mcast data
  */
@@ -1196,20 +1216,10 @@ struct batadv_priv_mcast {
 	 */
 	struct hlist_head want_all_ipv6_list;
 
-	/** @querier_ipv4: the current state of an IGMP querier in the mesh */
-	struct batadv_mcast_querier_state querier_ipv4;
-
-	/** @querier_ipv6: the current state of an MLD querier in the mesh */
-	struct batadv_mcast_querier_state querier_ipv6;
-
-	/** @flags: the flags we have last sent in our mcast tvlv */
-	u8 flags;
-
-	/** @enabled: whether the multicast tvlv is currently enabled */
-	unsigned char enabled:1;
-
-	/** @bridged: whether the soft interface has a bridge on top */
-	unsigned char bridged:1;
+	/**
+	 * @mla_flags: flags for the querier, bridge and tvlv state
+	 */
+	struct batadv_mcast_mla_flags mla_flags;
 
 	/**
 	 * @mla_lock: a lock protecting mla_list and mla_flags
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead
  2019-05-07  3:48 [PATCH v2 0/3] batman-adv: routeable multicast preparations T_X
  2019-05-07  3:48 ` [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section T_X
@ 2019-05-07  3:48 ` T_X
  2019-05-25 11:40   ` Sven Eckelmann
  2019-05-07  3:48 ` [PATCH v2 3/3] batman-adv: mcast: avoid redundant multicast TT entries with bridges T_X
  2 siblings, 1 reply; 5+ messages in thread
From: T_X @ 2019-05-07  3:48 UTC (permalink / raw)
  To: b.a.t.m.a.n

From: Linus Lüssing <linus.luessing@c0d3.blue>

Instead of collecting multicast MAC addresses from the netdev hw mc
list collect a node's multicast listeners from the IP lists and convert
those to MAC addresses.

This allows to exclude addresses of specific scope later. On a
multicast MAC address the IP destination scope is not visible anymore.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
 net/batman-adv/multicast.c | 258 +++++++++++++++++++++++++------------
 1 file changed, 173 insertions(+), 85 deletions(-)

diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index af0e2ce8..2a975bc0 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -20,6 +20,7 @@
 #include <linux/igmp.h>
 #include <linux/in.h>
 #include <linux/in6.h>
+#include <linux/inetdevice.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/jiffies.h>
@@ -171,91 +172,6 @@ static struct net_device *batadv_mcast_get_bridge(struct net_device *soft_iface)
 	return upper;
 }
 
-/**
- * batadv_mcast_addr_is_ipv4() - check if multicast MAC is IPv4
- * @addr: the MAC address to check
- *
- * Return: True, if MAC address is one reserved for IPv4 multicast, false
- * otherwise.
- */
-static bool batadv_mcast_addr_is_ipv4(const u8 *addr)
-{
-	static const u8 prefix[] = {0x01, 0x00, 0x5E};
-
-	return memcmp(prefix, addr, sizeof(prefix)) == 0;
-}
-
-/**
- * batadv_mcast_addr_is_ipv6() - check if multicast MAC is IPv6
- * @addr: the MAC address to check
- *
- * Return: True, if MAC address is one reserved for IPv6 multicast, false
- * otherwise.
- */
-static bool batadv_mcast_addr_is_ipv6(const u8 *addr)
-{
-	static const u8 prefix[] = {0x33, 0x33};
-
-	return memcmp(prefix, addr, sizeof(prefix)) == 0;
-}
-
-/**
- * batadv_mcast_mla_softif_get() - get softif multicast listeners
- * @dev: the device to collect multicast addresses from
- * @mcast_list: a list to put found addresses into
- * @flags: flags indicating the new multicast state
- *
- * Collects multicast addresses of multicast listeners residing
- * on this kernel on the given soft interface, dev, in
- * the given mcast_list. In general, multicast listeners provided by
- * your multicast receiving applications run directly on this node.
- *
- * If there is a bridge interface on top of dev, collects from that one
- * instead. Just like with IP addresses and routes, multicast listeners
- * will(/should) register to the bridge interface instead of an
- * enslaved bat0.
- *
- * Return: -ENOMEM on memory allocation error or the number of
- * items added to the mcast_list otherwise.
- */
-static int
-batadv_mcast_mla_softif_get(struct net_device *dev,
-			    struct hlist_head *mcast_list,
-			    struct batadv_mcast_mla_flags *flags)
-{
-	bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
-	bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
-	struct net_device *bridge = batadv_mcast_get_bridge(dev);
-	struct netdev_hw_addr *mc_list_entry;
-	struct batadv_hw_addr *new;
-	int ret = 0;
-
-	netif_addr_lock_bh(bridge ? bridge : dev);
-	netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) {
-		if (all_ipv4 && batadv_mcast_addr_is_ipv4(mc_list_entry->addr))
-			continue;
-
-		if (all_ipv6 && batadv_mcast_addr_is_ipv6(mc_list_entry->addr))
-			continue;
-
-		new = kmalloc(sizeof(*new), GFP_ATOMIC);
-		if (!new) {
-			ret = -ENOMEM;
-			break;
-		}
-
-		ether_addr_copy(new->addr, mc_list_entry->addr);
-		hlist_add_head(&new->list, mcast_list);
-		ret++;
-	}
-	netif_addr_unlock_bh(bridge ? bridge : dev);
-
-	if (bridge)
-		dev_put(bridge);
-
-	return ret;
-}
-
 /**
  * batadv_mcast_mla_is_duplicate() - check whether an address is in a list
  * @mcast_addr: the multicast address to check
@@ -276,6 +192,178 @@ static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr,
 	return false;
 }
 
+/**
+ * batadv_mcast_mla_softif_get_ipv4() - get softif IPv4 multicast listeners
+ * @dev: the device to collect multicast addresses from
+ * @mcast_list: a list to put found addresses into
+ * @flags: flags indicating the new multicast state
+ *
+ * Collects multicast addresses of IPv4 multicast listeners residing
+ * on this kernel on the given soft interface, dev, in
+ * the given mcast_list. In general, multicast listeners provided by
+ * your multicast receiving applications run directly on this node.
+ *
+ * Return: -ENOMEM on memory allocation error or the number of
+ * items added to the mcast_list otherwise.
+ */
+static int
+batadv_mcast_mla_softif_get_ipv4(struct net_device *dev,
+				 struct hlist_head *mcast_list,
+				 struct batadv_mcast_mla_flags *flags)
+{
+	struct batadv_hw_addr *new;
+	struct in_device *in_dev;
+	u8 mcast_addr[ETH_ALEN];
+	struct ip_mc_list *pmc;
+	int ret = 0;
+
+	if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
+		return 0;
+
+	in_dev = in_dev_get(dev);
+	if (!in_dev)
+		return 0;
+
+	rcu_read_lock();
+	for (pmc = rcu_dereference(in_dev->mc_list); pmc;
+	     pmc = rcu_dereference(pmc->next_rcu)) {
+		ip_eth_mc_map(pmc->multiaddr, mcast_addr);
+
+		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
+			continue;
+
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		ether_addr_copy(new->addr, mcast_addr);
+		hlist_add_head(&new->list, mcast_list);
+		ret++;
+	}
+	rcu_read_unlock();
+	in_dev_put(in_dev);
+
+	return ret;
+}
+
+/**
+ * batadv_mcast_mla_softif_get_ipv6() - get softif IPv6 multicast listeners
+ * @dev: the device to collect multicast addresses from
+ * @mcast_list: a list to put found addresses into
+ * @flags: flags indicating the new multicast state
+ *
+ * Collects multicast addresses of IPv6 multicast listeners residing
+ * on this kernel on the given soft interface, dev, in
+ * the given mcast_list. In general, multicast listeners provided by
+ * your multicast receiving applications run directly on this node.
+ *
+ * Return: -ENOMEM on memory allocation error or the number of
+ * items added to the mcast_list otherwise.
+ */
+#if IS_ENABLED(CONFIG_IPV6)
+static int
+batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
+				 struct hlist_head *mcast_list,
+				 struct batadv_mcast_mla_flags *flags)
+{
+	struct batadv_hw_addr *new;
+	struct inet6_dev *in6_dev;
+	u8 mcast_addr[ETH_ALEN];
+	struct ifmcaddr6 *pmc6;
+	int ret = 0;
+
+	if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
+		return 0;
+
+	in6_dev = in6_dev_get(dev);
+	if (!in6_dev)
+		return 0;
+
+	read_lock_bh(&in6_dev->lock);
+	for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
+		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
+		    IPV6_ADDR_SCOPE_LINKLOCAL)
+			continue;
+
+		ipv6_eth_mc_map(&pmc6->mca_addr, mcast_addr);
+
+		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
+			continue;
+
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		ether_addr_copy(new->addr, mcast_addr);
+		hlist_add_head(&new->list, mcast_list);
+		ret++;
+	}
+	read_unlock_bh(&in6_dev->lock);
+	in6_dev_put(in6_dev);
+
+	return ret;
+}
+#else
+static inline int
+batadv_mcast_mla_softif_get_ipv6(struct batadv_priv *bat_priv,
+				 struct net_device *dev,
+				 struct hlist_head *mcast_list)
+{
+	return 0;
+}
+#endif
+
+/**
+ * batadv_mcast_mla_softif_get() - get softif multicast listeners
+ * @dev: the device to collect multicast addresses from
+ * @mcast_list: a list to put found addresses into
+ * @flags: flags indicating the new multicast state
+ *
+ * Collects multicast addresses of multicast listeners residing
+ * on this kernel on the given soft interface, dev, in
+ * the given mcast_list. In general, multicast listeners provided by
+ * your multicast receiving applications run directly on this node.
+ *
+ * If there is a bridge interface on top of dev, collects from that one
+ * instead. Just like with IP addresses and routes, multicast listeners
+ * will(/should) register to the bridge interface instead of an
+ * enslaved bat0.
+ *
+ * Return: -ENOMEM on memory allocation error or the number of
+ * items added to the mcast_list otherwise.
+ */
+static int
+batadv_mcast_mla_softif_get(struct net_device *dev,
+			    struct hlist_head *mcast_list,
+			    struct batadv_mcast_mla_flags *flags)
+{
+	struct net_device *bridge = batadv_mcast_get_bridge(dev);
+	int ret4, ret6 = 0;
+
+	if (bridge)
+		dev = bridge;
+
+	ret4 = batadv_mcast_mla_softif_get_ipv4(dev, mcast_list, flags);
+	if (ret4 < 0)
+		goto out;
+
+	ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
+	if (ret6 < 0) {
+		ret4 = 0;
+		goto out;
+	}
+
+out:
+	if (bridge)
+		dev_put(bridge);
+
+	return ret4 + ret6;
+}
+
 /**
  * batadv_mcast_mla_br_addr_cpy() - copy a bridge multicast address
  * @dst: destination to write to - a multicast MAC address
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] batman-adv: mcast: avoid redundant multicast TT entries with bridges
  2019-05-07  3:48 [PATCH v2 0/3] batman-adv: routeable multicast preparations T_X
  2019-05-07  3:48 ` [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section T_X
  2019-05-07  3:48 ` [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead T_X
@ 2019-05-07  3:48 ` T_X
  2 siblings, 0 replies; 5+ messages in thread
From: T_X @ 2019-05-07  3:48 UTC (permalink / raw)
  To: b.a.t.m.a.n

From: Linus Lüssing <linus.luessing@c0d3.blue>

When a bridge is added on top of bat0 we set the WANT_ALL_UNSNOOPABLES
flag. Which means we sign up for all traffic for ff02::1/128 and
224.0.0.0/24.

When the node itself had IPv6 enabled or joined a group in 224.0.0.0/24
itself then so far this would result in a multicast TT entry which is
redundant to the WANT_ALL_UNSNOOPABLES.

With this patch such redundant TT entries are avoided.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
 net/batman-adv/multicast.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 2a975bc0..90571e4c 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -227,6 +227,10 @@ batadv_mcast_mla_softif_get_ipv4(struct net_device *dev,
 	rcu_read_lock();
 	for (pmc = rcu_dereference(in_dev->mc_list); pmc;
 	     pmc = rcu_dereference(pmc->next_rcu)) {
+		if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
+		    ipv4_is_local_multicast(pmc->multiaddr))
+			continue;
+
 		ip_eth_mc_map(pmc->multiaddr, mcast_addr);
 
 		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
@@ -287,6 +291,10 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
 		    IPV6_ADDR_SCOPE_LINKLOCAL)
 			continue;
 
+		if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
+		    ipv6_addr_is_ll_all_nodes(&pmc6->mca_addr))
+			continue;
+
 		ipv6_eth_mc_map(&pmc6->mca_addr, mcast_addr);
 
 		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
@@ -407,9 +415,8 @@ static int batadv_mcast_mla_bridge_get(struct net_device *dev,
 				       struct batadv_mcast_mla_flags *flags)
 {
 	struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
-	bool all_ipv4 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4;
-	bool all_ipv6 = flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6;
 	struct br_ip_list *br_ip_entry, *tmp;
+	u8 tvlv_flags = flags->tvlv_flags;
 	struct batadv_hw_addr *new;
 	u8 mcast_addr[ETH_ALEN];
 	int ret;
@@ -422,11 +429,23 @@ static int batadv_mcast_mla_bridge_get(struct net_device *dev,
 		goto out;
 
 	list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) {
-		if (all_ipv4 && br_ip_entry->addr.proto == htons(ETH_P_IP))
-			continue;
+		if (br_ip_entry->addr.proto == htons(ETH_P_IP)) {
+			if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
+				continue;
 
-		if (all_ipv6 && br_ip_entry->addr.proto == htons(ETH_P_IPV6))
-			continue;
+			if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
+			    ipv4_is_local_multicast(br_ip_entry->addr.u.ip4))
+				continue;
+		}
+
+		if (br_ip_entry->addr.proto == htons(ETH_P_IPV6)) {
+			if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
+				continue;
+
+			if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
+			    ipv6_addr_is_ll_all_nodes(&br_ip_entry->addr.u.ip6))
+				continue;
+		}
 
 		batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr);
 		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead
  2019-05-07  3:48 ` [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead T_X
@ 2019-05-25 11:40   ` Sven Eckelmann
  0 siblings, 0 replies; 5+ messages in thread
From: Sven Eckelmann @ 2019-05-25 11:40 UTC (permalink / raw)
  To: b.a.t.m.a.n


[-- Attachment #1.1: Type: text/plain, Size: 510 bytes --]

On Tuesday, 7 May 2019 05:48:23 CEST T_X wrote:
[..]
> Instead of collecting multicast MAC addresses from the netdev hw mc
> list collect a node's multicast listeners from the IP lists and convert
> those to MAC addresses.
> 
> This allows to exclude addresses of specific scope later. On a
> multicast MAC address the IP destination scope is not visible anymore.
> 
> Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>

There are various build problems. See attachment.

Kind regards,
	Sven

[-- Attachment #1.2: kbuild test robot <lkp@intel.com>: [batman:batadv/net-next 7/7] net/batman-adv/multicast.c:446:55: error: 'union <anonymous>' has no member named 'ip6'; did you mean 'ip4'? --]
[-- Type: message/rfc822, Size: 63768 bytes --]

[-- Attachment #1.2.1.1: Type: text/plain, Size: 8217 bytes --]

tree:   git://git.open-mesh.org/linux-merge batadv/net-next
head:   5e8230d96b966a3691f83e2b053798487725353e
commit: 5e8230d96b966a3691f83e2b053798487725353e [7/7] batman-adv: mcast: avoid redundant multicast TT entries with bridges
config: x86_64-randconfig-x008-201920 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        git checkout 5e8230d96b966a3691f83e2b053798487725353e
        # save the attached .config to linux build tree
        make ARCH=x86_64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   net/batman-adv/multicast.c: In function 'batadv_mcast_mla_softif_get':
   net/batman-adv/multicast.c:362:42: error: passing argument 1 of 'batadv_mcast_mla_softif_get_ipv6' from incompatible pointer type [-Werror=incompatible-pointer-types]
     ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
                                             ^~~
   net/batman-adv/multicast.c:320:1: note: expected 'struct batadv_priv *' but argument is of type 'struct net_device *'
    batadv_mcast_mla_softif_get_ipv6(struct batadv_priv *bat_priv,
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   net/batman-adv/multicast.c:362:47: error: passing argument 2 of 'batadv_mcast_mla_softif_get_ipv6' from incompatible pointer type [-Werror=incompatible-pointer-types]
     ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
                                                  ^~~~~~~~~~
   net/batman-adv/multicast.c:320:1: note: expected 'struct net_device *' but argument is of type 'struct hlist_head *'
    batadv_mcast_mla_softif_get_ipv6(struct batadv_priv *bat_priv,
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   net/batman-adv/multicast.c:362:59: error: passing argument 3 of 'batadv_mcast_mla_softif_get_ipv6' from incompatible pointer type [-Werror=incompatible-pointer-types]
     ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
                                                              ^~~~~
   net/batman-adv/multicast.c:320:1: note: expected 'struct hlist_head *' but argument is of type 'struct batadv_mcast_mla_flags *'
    batadv_mcast_mla_softif_get_ipv6(struct batadv_priv *bat_priv,
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   net/batman-adv/multicast.c: In function 'batadv_mcast_mla_bridge_get':
>> net/batman-adv/multicast.c:446:55: error: 'union <anonymous>' has no member named 'ip6'; did you mean 'ip4'?
           ipv6_addr_is_ll_all_nodes(&br_ip_entry->addr.u.ip6))
                                                          ^~~
                                                          ip4
   cc1: some warnings being treated as errors

vim +446 net/batman-adv/multicast.c

   327	
   328	/**
   329	 * batadv_mcast_mla_softif_get() - get softif multicast listeners
   330	 * @dev: the device to collect multicast addresses from
   331	 * @mcast_list: a list to put found addresses into
   332	 * @flags: flags indicating the new multicast state
   333	 *
   334	 * Collects multicast addresses of multicast listeners residing
   335	 * on this kernel on the given soft interface, dev, in
   336	 * the given mcast_list. In general, multicast listeners provided by
   337	 * your multicast receiving applications run directly on this node.
   338	 *
   339	 * If there is a bridge interface on top of dev, collects from that one
   340	 * instead. Just like with IP addresses and routes, multicast listeners
   341	 * will(/should) register to the bridge interface instead of an
   342	 * enslaved bat0.
   343	 *
   344	 * Return: -ENOMEM on memory allocation error or the number of
   345	 * items added to the mcast_list otherwise.
   346	 */
   347	static int
   348	batadv_mcast_mla_softif_get(struct net_device *dev,
   349				    struct hlist_head *mcast_list,
   350				    struct batadv_mcast_mla_flags *flags)
   351	{
   352		struct net_device *bridge = batadv_mcast_get_bridge(dev);
   353		int ret4, ret6 = 0;
   354	
   355		if (bridge)
   356			dev = bridge;
   357	
   358		ret4 = batadv_mcast_mla_softif_get_ipv4(dev, mcast_list, flags);
   359		if (ret4 < 0)
   360			goto out;
   361	
 > 362		ret6 = batadv_mcast_mla_softif_get_ipv6(dev, mcast_list, flags);
   363		if (ret6 < 0) {
   364			ret4 = 0;
   365			goto out;
   366		}
   367	
   368	out:
   369		if (bridge)
   370			dev_put(bridge);
   371	
   372		return ret4 + ret6;
   373	}
   374	
   375	/**
   376	 * batadv_mcast_mla_br_addr_cpy() - copy a bridge multicast address
   377	 * @dst: destination to write to - a multicast MAC address
   378	 * @src: source to read from - a multicast IP address
   379	 *
   380	 * Converts a given multicast IPv4/IPv6 address from a bridge
   381	 * to its matching multicast MAC address and copies it into the given
   382	 * destination buffer.
   383	 *
   384	 * Caller needs to make sure the destination buffer can hold
   385	 * at least ETH_ALEN bytes.
   386	 */
   387	static void batadv_mcast_mla_br_addr_cpy(char *dst, const struct br_ip *src)
   388	{
   389		if (src->proto == htons(ETH_P_IP))
   390			ip_eth_mc_map(src->u.ip4, dst);
   391	#if IS_ENABLED(CONFIG_IPV6)
   392		else if (src->proto == htons(ETH_P_IPV6))
   393			ipv6_eth_mc_map(&src->u.ip6, dst);
   394	#endif
   395		else
   396			eth_zero_addr(dst);
   397	}
   398	
   399	/**
   400	 * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners
   401	 * @dev: a bridge slave whose bridge to collect multicast addresses from
   402	 * @mcast_list: a list to put found addresses into
   403	 * @flags: flags indicating the new multicast state
   404	 *
   405	 * Collects multicast addresses of multicast listeners residing
   406	 * on foreign, non-mesh devices which we gave access to our mesh via
   407	 * a bridge on top of the given soft interface, dev, in the given
   408	 * mcast_list.
   409	 *
   410	 * Return: -ENOMEM on memory allocation error or the number of
   411	 * items added to the mcast_list otherwise.
   412	 */
   413	static int batadv_mcast_mla_bridge_get(struct net_device *dev,
   414					       struct hlist_head *mcast_list,
   415					       struct batadv_mcast_mla_flags *flags)
   416	{
   417		struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
   418		struct br_ip_list *br_ip_entry, *tmp;
   419		u8 tvlv_flags = flags->tvlv_flags;
   420		struct batadv_hw_addr *new;
   421		u8 mcast_addr[ETH_ALEN];
   422		int ret;
   423	
   424		/* we don't need to detect these devices/listeners, the IGMP/MLD
   425		 * snooping code of the Linux bridge already does that for us
   426		 */
   427		ret = br_multicast_list_adjacent(dev, &bridge_mcast_list);
   428		if (ret < 0)
   429			goto out;
   430	
   431		list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) {
   432			if (br_ip_entry->addr.proto == htons(ETH_P_IP)) {
   433				if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
   434					continue;
   435	
   436				if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
   437				    ipv4_is_local_multicast(br_ip_entry->addr.u.ip4))
   438					continue;
   439			}
   440	
   441			if (br_ip_entry->addr.proto == htons(ETH_P_IPV6)) {
   442				if (tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
   443					continue;
   444	
   445				if (tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
 > 446				    ipv6_addr_is_ll_all_nodes(&br_ip_entry->addr.u.ip6))
   447					continue;
   448			}
   449	
   450			batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr);
   451			if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
   452				continue;
   453	
   454			new = kmalloc(sizeof(*new), GFP_ATOMIC);
   455			if (!new) {
   456				ret = -ENOMEM;
   457				break;
   458			}
   459	
   460			ether_addr_copy(new->addr, mcast_addr);
   461			hlist_add_head(&new->list, mcast_list);
   462		}
   463	
   464	out:
   465		list_for_each_entry_safe(br_ip_entry, tmp, &bridge_mcast_list, list) {
   466			list_del(&br_ip_entry->list);
   467			kfree(br_ip_entry);
   468		}
   469	
   470		return ret;
   471	}
   472	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #1.2.1.2: .config.gz --]
[-- Type: application/gzip, Size: 39600 bytes --]

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-05-25 11:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-07  3:48 [PATCH v2 0/3] batman-adv: routeable multicast preparations T_X
2019-05-07  3:48 ` [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section T_X
2019-05-07  3:48 ` [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead T_X
2019-05-25 11:40   ` Sven Eckelmann
2019-05-07  3:48 ` [PATCH v2 3/3] batman-adv: mcast: avoid redundant multicast TT entries with bridges T_X

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.