Hi Marec,
On Tue, Jun 25, 2013 at 05:47:20AM +0800, Marek Lindner wrote:
> On Saturday, June 15, 2013 01:50:07 Linus Lüssing wrote:
> > With this patch a node which has no bridge interface on top of its soft
> > interface announces its local multicast listeners via the translation
> > table.
> >
> > Signed-off-by: Linus Lüssing <linus.luessing@web.de>
> > ---
> > Makefile | 2 +
> > Makefile.kbuild | 1 +
> > compat.h | 20 ++++-
> > gen-compat-autoconf.sh | 1 +
> > main.c | 6 ++
> > main.h | 1 +
> > multicast.c | 210
> > ++++++++++++++++++++++++++++++++++++++++++++++++ multicast.h |
> > 43 ++++++++++
> > soft-interface.c | 3 +
> > sysfs.c | 6 ++
> > translation-table.c | 22 ++++-
> > types.h | 12 +++
> > 12 files changed, 322 insertions(+), 5 deletions(-)
> > create mode 100644 multicast.c
> > create mode 100644 multicast.h
> >
> > diff --git a/Makefile b/Makefile
> > index 407cdc4..d7c6fa6 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -27,6 +27,8 @@ export CONFIG_BATMAN_ADV_BLA=y
> > export CONFIG_BATMAN_ADV_DAT=y
> > # B.A.T.M.A.N network coding (catwoman):
> > export CONFIG_BATMAN_ADV_NC=n
> > +# B.A.T.M.A.N. multicast optimizations:
> > +export CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS=y
>
> Can we please find a shorter define ? How about "CONFIG_BATMAN_ADV_MCAST" ?
> That would be in line with the rest.
Hm, yes I also don't like the length of that so much. But I had
dismissed "CONFIG_BATMAN_ADV_MCAST" so far because I thought it
might seem as if batman-adv were not able to handle multicast at
all without that option.
What about CONFIG_BATMAN_ADV_MCAST_OPT (hm, that could suggest
'optional', too...) or CONFIG_BATMAN_ADV_MCO?
.oO(also don't sound as nice as the other CONFIG_ exports...)
Ok, maybe CONFIG_BATMAN_ADV_MCAST is still the best option. I'll
change it to that.
>
>
> > +struct batadv_hw_addr {
> > + struct list_head list;
> > + unsigned char addr[ETH_ALEN];
> > +};
>
> All struct defines should go into types.h or packet.h if they are sent over
> the wire.
This struct isn't sent over the wire, it's just for local book
keeping. I was thinking about naming it 'struct batadv_mcast_hw_addr'
but didn't do that because it is so generic and thought maybe
because of that it might be reusable in the future.
Hm, maybe it's better to rename it to 'struct
batadv_mcast_hw_addr' anyways and leave it in that place to avoid
bloating types.h/packet.h with "unimportant" structs and defines?
>
>
> > +/**
> > + * batadv_mcast_mla_tt_update - update the own MLAs
> > + * @bat_priv: the bat priv with all the soft interface information
> > + *
> > + * Update the own multicast listener announcements in the translation
> > + * table. Also take care of registering or unregistering the multicast
> > + * tvlv depending on whether the user activated or deactivated
> > + * multicast optimizations.
> > + */
> > +void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
> > +{
> > + struct net_device *soft_iface = bat_priv->soft_iface;
> > + struct list_head mcast_list;
> > + int ret;
> > + static bool enabled;
> > +
> > + INIT_LIST_HEAD(&mcast_list);
> > +
> > + /* Avoid attaching MLAs, if multicast optimization is disabled
> > + * or there is a bridge on top of our soft interface (TODO)
> > + */
> > + if (!atomic_read(&bat_priv->mcast_group_awareness) ||
> > + bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT) {
> > + if (enabled)
> > + enabled = false;
> > +
> > + goto update;
> > + }
> > +
> > + if (!enabled)
> > + enabled = true;
> > +
> > + ret = batadv_mcast_mla_local_collect(soft_iface, &mcast_list);
> > + if (ret < 0)
> > + goto out;
> > +
> > +update:
> > + batadv_mcast_mla_tt_clean(bat_priv, &mcast_list);
a> > + batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
> > +
> > +out:
> > + batadv_mcast_mla_collect_free(&mcast_list);
> > +}
>
> You can use the LIST_HEAD static initializer.
Ah, indeed, will change that.
> The "enabled" variable does not make any sense.
Woops, indeed, makes more sense in [PATCH 2/3], I'll move it
there.
>
> How about we change some function names for the sake of clarity ? Here my
> suggestions:
>
> * batadv_mcast_mla_local_collect() => batadv_mcast_mla_softif_retrieve() or
> batadv_mcast_mla_softif_get()
Sounds good, I like the latter very much (I was using the terms
local, bridge, global - but yes, our own bridge is also kind of
local, so softif is better :) ).
> * batadv_mcast_mla_tt_clean() => batadv_mcast_mla_tt_retract()
Hm, I think I'd find that a little confusing when reading a
batadv_mcast_mla_tt_retract(bat_priv, mcast_list) in the code
somewhere because I'd think that the things provided by mcast_list
were going to get retracted. batadv_mcast_mla_tt_clean(bat_priv,
mcast_list) would feel more like dusting the table while the
given argument provides the list of valuable items on the table
which you are taking special care of, which you don't want to
accidentally knock over :) (in my opinion).
> * batadv_mcast_mla_collect_free() => batadv_mcast_mla_list_free()
Sounds good!
>
>
> > +#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
> > +struct batadv_priv_mcast {
> > + struct list_head mla_list;
> > +};
> > +#endif
>
> I don't see a good reason to use a double linked list or is there one ?
No, you're right, currently we don't need a double linked list head.
I'll change it to an HLIST.
Thanks for all the feedback so far!
>
> Cheers,
> Marek
Cheers, Linus
@@ -27,6 +27,8 @@ export CONFIG_BATMAN_ADV_BLA=y
export CONFIG_BATMAN_ADV_DAT=y
# B.A.T.M.A.N network coding (catwoman):
export CONFIG_BATMAN_ADV_NC=n
+# B.A.T.M.A.N. multicast optimizations:
+export CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS=y
PWD:=$(shell pwd)
KERNELPATH ?= /lib/modules/$(shell uname -r)/build
@@ -38,3 +38,4 @@ batman-adv-y += send.o
batman-adv-y += soft-interface.o
batman-adv-y += sysfs.o
batman-adv-y += translation-table.o
+batman-adv-$(CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS) += multicast.o
@@ -103,13 +103,31 @@ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
#define pr_warn pr_warning
+#undef netdev_for_each_mc_addr
+#define netdev_for_each_mc_addr(mclist, dev) \
+ for (mclist = (struct bat_dev_addr_list *)dev->mc_list; mclist; \
+ mclist = (struct bat_dev_addr_list *)mclist->next)
+
+/* Note, that this breaks the usage of the normal 'struct netdev_hw_addr'
+ * for kernels < 2.6.35 in batman-adv!
+ */
+#define netdev_hw_addr batadv_dev_addr_list
+struct batadv_dev_addr_list {
+ struct dev_addr_list *next;
+ u8 addr[MAX_ADDR_LEN];
+ u8 da_addrlen;
+ u8 da_synced;
+ int da_users;
+ int da_gusers;
+};
+
#endif /* < KERNEL_VERSION(2, 6, 35) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
#define __rcu
-#define IFF_BRIDGE_PORT 0 || (hard_iface->net_dev->br_port ? 1 : 0)
+#define IFF_BRIDGE_PORT 0 || (soft_iface->br_port ? 1 : 0)
struct kernel_param_ops {
/* Returns 0, or -errno. arg is in kp->arg. */
@@ -39,6 +39,7 @@ gen_config() {
gen_config 'CONFIG_BATMAN_ADV_DEBUG' ${CONFIG_BATMAN_ADV_DEBUG:="n"} >> "${TMP}"
gen_config 'CONFIG_BATMAN_ADV_BLA' ${CONFIG_BATMAN_ADV_BLA:="y"} >> "${TMP}"
gen_config 'CONFIG_BATMAN_ADV_DAT' ${CONFIG_BATMAN_ADV_DAT:="y"} >> "${TMP}"
+gen_config 'CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS' ${CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS:="y"} >> "${TMP}"
gen_config 'CONFIG_BATMAN_ADV_NC' ${CONFIG_BATMAN_ADV_NC:="n"} >> "${TMP}"
# only regenerate compat-autoconf.h when config was changed
@@ -33,6 +33,7 @@
#include "gateway_client.h"
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
+#include "multicast.h"
#include "gateway_common.h"
#include "hash.h"
#include "bat_algo.h"
@@ -116,6 +117,9 @@ int batadv_mesh_init(struct net_device *soft_iface)
INIT_LIST_HEAD(&bat_priv->tt.changes_list);
INIT_LIST_HEAD(&bat_priv->tt.req_list);
INIT_LIST_HEAD(&bat_priv->tt.roam_list);
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+ INIT_LIST_HEAD(&bat_priv->mcast.mla_list);
+#endif
INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
@@ -169,6 +173,8 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_dat_free(bat_priv);
batadv_bla_free(bat_priv);
+ batadv_mcast_free(bat_priv);
+
/* Free the TT and the originator tables only after having terminated
* all the other depending components which may use these structures for
* their purposes.
@@ -164,6 +164,7 @@ enum batadv_uev_type {
#include <linux/percpu.h>
#include <linux/slab.h>
#include <net/sock.h> /* struct sock */
+#include <net/addrconf.h> /* ipv6 address stuff */
#include <net/rtnetlink.h>
#include <linux/jiffies.h>
#include <linux/seq_file.h>
new file mode 100644
@@ -0,0 +1,210 @@
+/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+ *
+ * Linus Lüssing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include "main.h"
+#include "originator.h"
+#include "hard-interface.h"
+#include "translation-table.h"
+
+struct batadv_hw_addr {
+ struct list_head list;
+ unsigned char addr[ETH_ALEN];
+};
+
+/**
+ * batadv_mcast_mla_local_collect - collect local multicast listeners
+ * @dev: the device to collect multicast addresses from
+ * @mcast_list: a list to put found addresses into
+ *
+ * Collect multicast addresses of the local multicast listeners
+ * on the given interface, dev, in the given mcast_list.
+ *
+ * Return -ENOMEM on memory allocation error or the number of
+ * items added to the mcast_list otherwise.
+ */
+static int batadv_mcast_mla_local_collect(struct net_device *dev,
+ struct list_head *mcast_list)
+{
+ struct netdev_hw_addr *mc_list_entry;
+ struct batadv_hw_addr *new;
+ int ret = 0;
+
+ netif_addr_lock_bh(dev);
+ netdev_for_each_mc_addr(mc_list_entry, dev) {
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ if (!new) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ memcpy(&new->addr, &mc_list_entry->addr, ETH_ALEN);
+ list_add(&new->list, mcast_list);
+ ret++;
+ }
+ netif_addr_unlock_bh(dev);
+
+ return ret;
+}
+
+/**
+ * batadv_mcast_mla_is_duplicate - check whether an address is in a list
+ * @mcast_addr: the multicast address to check
+ * @mcast_list: the list with multicast addresses to search in
+ *
+ * Return true if the given address is already in the given list.
+ * Otherwise returns false.
+ */
+static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr,
+ struct list_head *mcast_list)
+{
+ struct batadv_hw_addr *mcast_entry;
+
+ list_for_each_entry(mcast_entry, mcast_list, list)
+ if (batadv_compare_eth(mcast_entry->addr, mcast_addr))
+ return true;
+
+ return false;
+}
+
+/**
+ * batadv_mcast_mla_collect_free - free a list of multicast addresses
+ * @mcast_list: the list to free
+ *
+ * Remove and free all items in the given mcast_list.
+ */
+void batadv_mcast_mla_collect_free(struct list_head *mcast_list)
+{
+ struct batadv_hw_addr *mcast_entry, *tmp;
+
+ list_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
+ list_del(&mcast_entry->list);
+ kfree(mcast_entry);
+ }
+}
+
+/**
+ * batadv_mcast_mla_tt_clean - clean up multicast listener announcements
+ * @bat_priv: the bat priv with all the soft interface information
+ * @mcast_list: a list of addresses which should _not_ be removed
+ *
+ * Retract the announcement of any multicast listener from the
+ * translation table except the ones listed in the given mcast_list.
+ *
+ * If mcast_list is NULL then all are retracted.
+ */
+static void batadv_mcast_mla_tt_clean(struct batadv_priv *bat_priv,
+ struct list_head *mcast_list)
+{
+ struct batadv_hw_addr *mcast_entry, *tmp;
+
+ list_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
+ list) {
+ if (mcast_list &&
+ batadv_mcast_mla_is_duplicate(mcast_entry->addr,
+ mcast_list))
+ continue;
+
+ batadv_tt_local_remove(bat_priv, mcast_entry->addr,
+ BATADV_NO_FLAGS,
+ "mcast TT outdated", false);
+
+ list_del(&mcast_entry->list);
+ kfree(mcast_entry);
+ }
+}
+
+/**
+ * batadv_mcast_mla_tt_add - add multicast listener announcements
+ * @bat_priv: the bat priv with all the soft interface information
+ * @mcast_list: a list of addresses which are going to get added
+ *
+ * Add multicast listener announcements from the given mcast_list to the
+ * translation table if they have not been added yet.
+ */
+static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
+ struct list_head *mcast_list)
+{
+ struct batadv_hw_addr *mcast_entry, *tmp;
+
+ if (!mcast_list)
+ return;
+
+ list_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
+ if (batadv_mcast_mla_is_duplicate(mcast_entry->addr,
+ &bat_priv->mcast.mla_list))
+ continue;
+
+ batadv_tt_local_add(bat_priv->soft_iface, mcast_entry->addr,
+ BATADV_NO_FLAGS, BATADV_NULL_IFINDEX);
+ list_move_tail(&mcast_entry->list, &bat_priv->mcast.mla_list);
+ }
+}
+
+/**
+ * batadv_mcast_mla_tt_update - update the own MLAs
+ * @bat_priv: the bat priv with all the soft interface information
+ *
+ * Update the own multicast listener announcements in the translation
+ * table. Also take care of registering or unregistering the multicast
+ * tvlv depending on whether the user activated or deactivated
+ * multicast optimizations.
+ */
+void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
+{
+ struct net_device *soft_iface = bat_priv->soft_iface;
+ struct list_head mcast_list;
+ int ret;
+ static bool enabled;
+
+ INIT_LIST_HEAD(&mcast_list);
+
+ /* Avoid attaching MLAs, if multicast optimization is disabled
+ * or there is a bridge on top of our soft interface (TODO)
+ */
+ if (!atomic_read(&bat_priv->mcast_group_awareness) ||
+ bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT) {
+ if (enabled)
+ enabled = false;
+
+ goto update;
+ }
+
+ if (!enabled)
+ enabled = true;
+
+ ret = batadv_mcast_mla_local_collect(soft_iface, &mcast_list);
+ if (ret < 0)
+ goto out;
+
+update:
+ batadv_mcast_mla_tt_clean(bat_priv, &mcast_list);
+ batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
+
+out:
+ batadv_mcast_mla_collect_free(&mcast_list);
+}
+
+/**
+ * batadv_mcast_free - free the multicast optimizations structures
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_mcast_free(struct batadv_priv *bat_priv)
+{
+ batadv_mcast_mla_tt_clean(bat_priv, NULL);
+}
new file mode 100644
@@ -0,0 +1,43 @@
+/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+ *
+ * Linus Lüssing
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_MULTICAST_H_
+#define _NET_BATMAN_ADV_MULTICAST_H_
+
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+
+void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv);
+
+void batadv_mcast_free(struct batadv_priv *bat_priv);
+
+#else
+
+static inline void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
+{
+ return;
+}
+
+static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
+{
+ return;
+}
+
+#endif /* CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS */
+
+#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
@@ -471,6 +471,9 @@ static int batadv_softif_init_late(struct net_device *dev)
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_set(&bat_priv->distributed_arp_table, 1);
#endif
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+ atomic_set(&bat_priv->mcast_group_awareness, 1);
+#endif
atomic_set(&bat_priv->ap_isolation, 0);
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20);
@@ -369,6 +369,9 @@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE,
batadv_post_gw_deselect);
static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
batadv_store_gw_bwidth);
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+BATADV_ATTR_SIF_BOOL(mcast_group_awareness, S_IRUGO | S_IWUSR, NULL);
+#endif
#ifdef CONFIG_BATMAN_ADV_DEBUG
BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
#endif
@@ -386,6 +389,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
#ifdef CONFIG_BATMAN_ADV_DAT
&batadv_attr_distributed_arp_table,
#endif
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+ &batadv_attr_mcast_group_awareness,
+#endif
&batadv_attr_fragmentation,
&batadv_attr_ap_isolation,
&batadv_attr_routing_algo,
@@ -26,6 +26,7 @@
#include "originator.h"
#include "routing.h"
#include "bridge_loop_avoidance.h"
+#include "multicast.h"
#include <linux/crc32c.h>
@@ -351,14 +352,16 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
{
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
struct batadv_tt_local_entry *tt_local;
- struct batadv_tt_global_entry *tt_global;
+ struct batadv_tt_global_entry *tt_global = NULL;
struct hlist_head *head;
struct batadv_tt_orig_list_entry *orig_entry;
int hash_added;
bool roamed_back = false;
tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
- tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
+
+ if (!is_multicast_ether_addr(addr))
+ tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
if (tt_local) {
tt_local->last_seen = jiffies;
@@ -412,8 +415,11 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
tt_local->last_seen = jiffies;
tt_local->common.added_at = tt_local->last_seen;
- /* the batman interface mac address should never be purged */
- if (batadv_compare_eth(addr, soft_iface->dev_addr))
+ /* the batman interface mac and multicast addresses should never be
+ * purged
+ */
+ if (batadv_compare_eth(addr, soft_iface->dev_addr) ||
+ is_multicast_ether_addr(addr))
tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
@@ -1007,6 +1013,11 @@ add_orig_entry:
ret = true;
out_remove:
+ /* Do not remove multicast addresses from the local hash on
+ * global additions
+ */
+ if (is_multicast_ether_addr(tt_addr))
+ goto out;
/* remove address from local hash if present */
local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
@@ -2521,6 +2532,9 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
{
uint16_t changed_num = 0;
+ /* Update multicast addresses in local translation table */
+ batadv_mcast_mla_tt_update(bat_priv);
+
if (atomic_read(&bat_priv->tt.local_changes) < 1) {
if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
batadv_tt_tvlv_container_update(bat_priv);
@@ -501,6 +501,12 @@ struct batadv_priv_dat {
};
#endif
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+struct batadv_priv_mcast {
+ struct list_head mla_list;
+};
+#endif
+
/**
* struct batadv_priv_nc - per mesh interface network coding private data
* @work: work queue callback item for cleanup
@@ -591,6 +597,9 @@ struct batadv_priv {
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_t distributed_arp_table;
#endif
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+ atomic_t mcast_group_awareness;
+#endif
atomic_t gw_mode;
atomic_t gw_sel_class;
atomic_t orig_interval;
@@ -625,6 +634,9 @@ struct batadv_priv {
#ifdef CONFIG_BATMAN_ADV_DAT
struct batadv_priv_dat dat;
#endif
+#ifdef CONFIG_BATMAN_ADV_MCAST_OPTIMIZATIONS
+ struct batadv_priv_mcast mcast;
+#endif
#ifdef CONFIG_BATMAN_ADV_NC
atomic_t network_coding;
struct batadv_priv_nc nc;