From patchwork Tue May 7 04:08:26 2019 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: 17906 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id A1A5681F70; Tue, 7 May 2019 06:08:34 +0200 (CEST) Received: from mail.aperture-lab.de (mail.aperture-lab.de [IPv6:2a01:4f8:171:314c::100:a1]) by open-mesh.org (Postfix) with ESMTPS id 1689780529 for ; Tue, 7 May 2019 06:08:33 +0200 (CEST) From: =?utf-8?q?Linus_L=C3=BCssing?= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202112; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=Ch+EYNdnRnfNzS7IARNw7x+dKRactKvvVdPUIq05Gfw=; b=PwhcDc06mg7O6f0FsI61GyaLrYk2K53S74S2j4Mb29vs28lma3CkK2VtrFwfStnXC/AJhQ n1SWjvObO3s2TKkybfeE+impOIKkv4JaBzKBYQJ5ykW8EEIZ3pEgtBEsWMsvgqBx6gMzQ5 Jr+07nnksbF9T/JTOlVbH0YoyeELFzmnVqh5muDKLmDQfJiH6gZWimCvHlssBDGV9c8AYy 08Vz6OHmWq6uKSfe74zbL2d/TczHXDUrlC9NxTZI9hBrV6Z7VQdwCPjCBZpWnNib2/IWz3 /5TiQgfHcoAOvzBsu21BmzxydxFmBWwSALzohYZeZvfdoDrJp1Yp5g6yE5YTxA== To: b.a.t.m.a.n@lists.open-mesh.org Subject: [PATCH v2 1/3] batman-adv: mcast: shorten multicast tt/tvlv worker spinlock section Date: Tue, 7 May 2019 06:08:26 +0200 Message-Id: <20190507040828.3927-2-linus.luessing@c0d3.blue> In-Reply-To: <20190507040828.3927-1-linus.luessing@c0d3.blue> References: <20190507040828.3927-1-linus.luessing@c0d3.blue> MIME-Version: 1.0 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202112; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=Ch+EYNdnRnfNzS7IARNw7x+dKRactKvvVdPUIq05Gfw=; b=gPToZmLRXhg3xw2fo4hXTSd+YLrB8lLEEOEorsxHBtunxjv5Qzl+zrH0zuWrmK57S8LQyJ F2eRvifk7W24tmrZJFRWlSfGINsuQEVXp4RKwe2CQJCse1dsQNJDFPnWx7CdilMcN64Sik EW5HfWFNIM99o7ir5Fw/lmUj9QguxOH2grwErs5VG5/foD3obTnirsRc4yFGg9yJy2cQxV wJDjWLyCwmOMYveMv9vXfDzgGBzw2OmtvtUrDFD+bLF+O/02zHBTgyNCfMSKvGbqrLETj1 UxJ19BmcT689QJd4Q1cyqCMyDmoB4nlsM2inkDmhWFD1ussyA6rIjtCTU87INw== ARC-Seal: i=1; s=2018; d=c0d3.blue; t=1557202112; a=rsa-sha256; cv=none; b=StpjFmVpi0L44drJGU68kSFS+1rWYW/cgy2s92hx5ffzGPhU0C7vzBtjkLA0TbXfMPeLX+ FEQdmOnCIQpNAjOfNX2S9DaxlB2fc586kuJtB6v1yUyoiDF42OZy5PAVVZv9GbJXvyVMS6 331/eR35Crnd9DXMZ4pn6Gh1nid3p9qfzMlB72RGXeQOLo+N1HaFT699ZFanbx55ZWppJ1 Wl5xRZa4EzmY3YxWZ+OgVLidD2roZThut9qk3ZXkDbZbPRqth4bJz/2Wd1tsiyXSjvINfE 5iBdIGmoVR08lLou8JWdaKttpIKR3Egj4sPT04gGnD/qpEAVv+EN6s+oc09aig== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue Authentication-Results: ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" 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 --- 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 : "", + old_enabled ? str_old_flags : "", (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 From patchwork Tue May 7 04:08:27 2019 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: 17907 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id F2773820A7; Tue, 7 May 2019 06:08:37 +0200 (CEST) Received: from mail.aperture-lab.de (mail.aperture-lab.de [IPv6:2a01:4f8:171:314c::100:a1]) by open-mesh.org (Postfix) with ESMTPS id 6C7C381F6F for ; Tue, 7 May 2019 06:08:34 +0200 (CEST) From: =?utf-8?q?Linus_L=C3=BCssing?= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202114; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=cftObI05IhcUdMYZoLRO6/4Q58r/9p28tF5Owa7vygI=; b=UxQZhOF0KRtlJwKxEFkGtwKxanRJh5MeypiEUcG7zDA6ERQDU1qJVSGetLknqvv6SU4Kdo bMP6a5SDUvd6VmdTgHLumV7+9/OkY6EOflC7lvEuCvl79DUex/YcgewRWZBDNibubbd1u+ QOHeBREkxlFZG3s+ZdmJcWWjYrxJ0DmvYmKCQgLvjXjlv3INvQ+BqrR03M7ZNK3ri6YoIP UJQrzQtjAYUBv/hEI9KiWbOXpApLKzV0gDZzNSa198jriWYSTJOfnH4XX4zlfb6OX/9mKk MChPf5q4pH+VZl1hhvi6Lwb8xP7uHqyS+Nlf0oAU5LzlFmTEs3ZtRNxojuiSjg== To: b.a.t.m.a.n@lists.open-mesh.org Subject: [PATCH v2 2/3] batman-adv: mcast: collect softif listeners from IP lists instead Date: Tue, 7 May 2019 06:08:27 +0200 Message-Id: <20190507040828.3927-3-linus.luessing@c0d3.blue> In-Reply-To: <20190507040828.3927-1-linus.luessing@c0d3.blue> References: <20190507040828.3927-1-linus.luessing@c0d3.blue> MIME-Version: 1.0 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202114; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=cftObI05IhcUdMYZoLRO6/4Q58r/9p28tF5Owa7vygI=; b=ayLeLFhKqo9Y+GVPww0fkPMpaZL3irJd1SnRdCzDd2a0tX+ppkwnOSU1TbQufl3oK/Qxos idHLjjyi6SB6+ZvsFCBndyFb1MZv2ZDkS35pgBxz+3g4TG4LwcJR/8XH5OzRHHOQi3F4K2 +LUScPxpTTNtYoxnhbUBFjSlUJZvZhW6zPBj9LKA6vMuxNFbod7zdrGESBOVMJI5JIB9zn vqNy8P6bdqIBcOOgFaU/kI+zPkIZMtMNOf6pIAF9fD2sgW40RBFhWvwfemKNvBsXOlUbWB y+WCpb0m6g4YReetGpDxsrxPtOI7+emPAiYTCvxlUqiFg1m1HUD1dr3ze/SlUA== ARC-Seal: i=1; s=2018; d=c0d3.blue; t=1557202114; a=rsa-sha256; cv=none; b=FUDKRQL31PAulwyL8j7DtV5KSo1+UAaORqlOE3FIIBX42TY83ZqvlybtTSpRDNX83EpvVs 29yKqZFFMVDN3GiwIFRO8rDlckXCQ0Iqy20LvM6IjXcp7eB8oAxCSRdKx/Tq7k03eUpqJP 4csvui9lGSf+Hx9clijijzAG3S4RfOBvvvZ1bJBbK9E9f8Flyq75n5abWv8lbuQHC0W0OU SGQJ3W5eAu0BJcO/tCMqxkQkJiHP3cNOmtwTPgfIclPo7MmMwlDhCnXE3inCq6NXwqbZGM xqicAWD27m6jGuOoOP1lv5XJ9rjq7zdDKXYARE2CwfOV8xnogZJDTpa3LrZI6Q== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue Authentication-Results: ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" 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 --- 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 #include #include +#include #include #include #include @@ -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 From patchwork Tue May 7 04:08:28 2019 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: 17908 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id A6DE681C86; Tue, 7 May 2019 06:08:44 +0200 (CEST) Received: from mail.aperture-lab.de (mail.aperture-lab.de [138.201.29.205]) by open-mesh.org (Postfix) with ESMTPS id 67D5D82081 for ; Tue, 7 May 2019 06:08:37 +0200 (CEST) From: =?utf-8?q?Linus_L=C3=BCssing?= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202115; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=TsjvNMmHIo/hwbB/G/l4etZ79ozEzx3sY49wbqumedM=; b=rU1xC8n424cKKSbvu2NTQoj3vKv06si/KugYvFQZ4Lmq7Y93wF4AULY0hCCfJp8ZHcyLGi 0Ps1Oxbs/Q8SHrgHtRe0hRrZWmoZXYFd3UFE2j2tdgrX5l5kBp6deNuFTxw0nMK9+5KT70 1oovym/V4kSTK8S930kjmY1lGWC08xjlKlVp1WDZZNpQEyqWEwKmmrkG7DFJzKXrGTc7L1 0hHx3Uk4J9voEGG+oAZjoJ9q6mLHJb3SMmaCMt/KBE20M03OOir4zBUrxhW+0CgpQeKT+q P1T2wF2UHvYvvF9m4WgPd1dyHxW0w+D8PVTBhaC1cpovnN9qee1QehbwlW4LLw== To: b.a.t.m.a.n@lists.open-mesh.org Subject: [PATCH v2 3/3] batman-adv: mcast: avoid redundant multicast TT entries with bridges Date: Tue, 7 May 2019 06:08:28 +0200 Message-Id: <20190507040828.3927-4-linus.luessing@c0d3.blue> In-Reply-To: <20190507040828.3927-1-linus.luessing@c0d3.blue> References: <20190507040828.3927-1-linus.luessing@c0d3.blue> MIME-Version: 1.0 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=c0d3.blue; s=2018; t=1557202115; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:openpgp:autocrypt; bh=TsjvNMmHIo/hwbB/G/l4etZ79ozEzx3sY49wbqumedM=; b=CzgSMl+A+dwpfardFCKR40scFjvuKQ9lzViTZDIPzf+7JIM2UuzNfHh3NiU2x9cntsd/fL ePggbXt3yVlngwpKjc74G6mVS54OGPnv2fxxhU49T+CxU1DC6ruanwFFQwC/BeZ2d6VDrI k7cgu4kV3J8dSGX6UkjqOIaOkyD/hXWzJ4wvzCmNYfcsDJoBszfFahYG55FXsbWx132clF 13Tiv7qVNvuRkpBF673robGbCrb2Q4AvBpCrOGQdbDH0xctLeZl4uyIT2d6/xlw57kghBy B0A1vA4MfcvGm2e/rqCC6UYuPbmlh0NCh87DKD1tMHxZL7zYNb0vIYNJ0kAWqA== ARC-Seal: i=1; s=2018; d=c0d3.blue; t=1557202115; a=rsa-sha256; cv=none; b=NAXroKIAMZb6X79rnv8he+0iOl41IaAdkgVdkrVzVfCxwETNVNVv+9pX0v6pF/9e9ZDOY9 pjKLPyiVCJ05eqhjVYSyhGFaIBfdsmo4+Ty1NRMm1ttGBeYU4zL4Zd07zp1XTU10AVqHMt jrlGHswUKDFKo36pieVdRZNjmvYbJlKwL4YNfBXZBGKuQQYd+s557rfzqyQNKjL6ubBkHF nICxIPbnzHFiNreJSxDCA32JOZcgTxSHaBRNtAEwFZ9FwP+Kb4fbkGIt+DU0Ep1g4riZOz ogqy0wKm4Zs6nJoh3dE6jEuYE9SGB6WLYOQfKMgGSzB69/xEp+4H3PDc33i3Nw== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue Authentication-Results: ORIGINATING; auth=pass smtp.auth=linus.luessing@c0d3.blue smtp.mailfrom=linus.luessing@c0d3.blue X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" 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 --- 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))