[v7,2/4] batman-adv: Announce new capability via multicast TVLV
Commit Message
If the soft interface of a node is not part of a bridge then a node
announces a new multicast TVLV: The according flag
(BATADV_MCAST_LISTENER_ANNOUNCEMENT) signalizes that this node is
announcing all of its multicast listeners via the translation table
infrastructure. More precisely, all multicast listeners of scope greater
than link-local for IPv4 and of scope greater
or equal to link-local for IPv6.
Signed-off-by: Linus Lüssing <linus.luessing@web.de>
---
main.c | 4 +++
main.h | 1 +
multicast.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
multicast.h | 14 +++++++++++
originator.c | 6 +++++
packet.h | 7 ++++++
soft-interface.c | 1 +
types.h | 4 +++
8 files changed, 110 insertions(+), 1 deletion(-)
Comments
On Thursday, July 04, 2013 06:03:20 Linus Lüssing wrote:
> diff --git a/multicast.c b/multicast.c
> index 7ea19ab..4af4bc9 100644
> --- a/net/batman-adv/multicast.c
> +++ b/net/batman-adv/multicast.c
> @@ -169,13 +169,30 @@ void batadv_mcast_mla_tt_update(struct batadv_priv
> *bat_priv) struct net_device *soft_iface = bat_priv->soft_iface;
> struct hlist_head mcast_list = HLIST_HEAD_INIT;
> int ret;
> + static bool enabled;
> + uint8_t mcast_flags;
>
> /* 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->multicast_mode) ||
> - bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT)
> + bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT) {
> + if (enabled) {
> + batadv_tvlv_container_unregister(bat_priv,
> + BATADV_TVLV_MCAST,
> 1); + enabled = false;
> + }
> +
> goto update;
> + }
> +
> + if (!enabled) {
> + mcast_flags = BATADV_MCAST_LISTENER_ANNOUNCEMENT;
> + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST,
> 1, + &mcast_flags,
> + sizeof(mcast_flags));
> + enabled = true;
> + }
>
> ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
> if (ret < 0)
Is there no better way than using a static variable ? Apart from bad
readibility this totally breaks when using several batX interfaces with
different settings.
> +/* multicast capabilities */
> +enum batadv_mcast_flags {
> + BATADV_MCAST_LISTENER_ANNOUNCEMENT = BIT(0),
> +};
Didn't we discuss that using feature names is better ? We talked about things
like UNICAST, TRACKER, etc ?
Cheers,
Marek
On Sat, Jul 06, 2013 at 06:57:44PM +0800, Marek Lindner wrote:
> On Thursday, July 04, 2013 06:03:20 Linus Lüssing wrote:
> > diff --git a/multicast.c b/multicast.c
> > index 7ea19ab..4af4bc9 100644
> > --- a/net/batman-adv/multicast.c
> > +++ b/net/batman-adv/multicast.c
> > @@ -169,13 +169,30 @@ void batadv_mcast_mla_tt_update(struct batadv_priv
> > *bat_priv) struct net_device *soft_iface = bat_priv->soft_iface;
> > struct hlist_head mcast_list = HLIST_HEAD_INIT;
> > int ret;
> > + static bool enabled;
> > + uint8_t mcast_flags;
> >
> > /* 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->multicast_mode) ||
> > - bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT)
> > + bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT) {
> > + if (enabled) {
> > + batadv_tvlv_container_unregister(bat_priv,
> > + BATADV_TVLV_MCAST,
> > 1); + enabled = false;
> > + }
> > +
> > goto update;
> > + }
> > +
> > + if (!enabled) {
> > + mcast_flags = BATADV_MCAST_LISTENER_ANNOUNCEMENT;
> > + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST,
> > 1, + &mcast_flags,
> > + sizeof(mcast_flags));
> > + enabled = true;
> > + }
> >
> > ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
> > if (ret < 0)
>
> Is there no better way than using a static variable ? Apart from bad
> readibility this totally breaks when using several batX interfaces with
> different settings.
Ah, right, didn't think of multiple batX interfaces, that's a bug
indeed. I'm going to fix that.
What do you think about adding new tvlv API like:
---
bool batadv_tvlv_container_is_registered(struct batadv_priv *bat_priv,
uint8_t type, uint8_t version)
{
struct batadv_tvlv_container *tvlv;
bool ret;
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
tvlv = batadv_tvlv_container_get(bat_priv, type, version);
ret = tvlv ? true : false;
batadv_tvlv_container_free_ref(tvlv);
spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
return ret;
}
----
The disadvantage is that this is a little heavier as it will
perform a list lookup and holds a spin-lock.
If we were going to use something like bat_priv->mcast.tvlv_container_enabled
instead, that would be lighter but less readable.
>
>
> > +/* multicast capabilities */
> > +enum batadv_mcast_flags {
> > + BATADV_MCAST_LISTENER_ANNOUNCEMENT = BIT(0),
> > +};
>
> Didn't we discuss that using feature names is better ? We talked about things
> like UNICAST, TRACKER, etc ?
Hm, I only remember discussing the name for sysfs. For the flags
I thought we were only using UNICAST, TRACKER, etc. as
abbreviations for the current names in our IRC discussion, I didn't
interpret that as a suggestion to change these names.
Anyways, let's discuss a renaming of the flags then. I don't like a change
like:
BATADV_MCAST_LISTENER_ANNOUNCEMENT -> BATADV_MCAST_UNICAST
Because for one thing, it isn't up to the node announcing this
flag to deceide whether another, sending node is able use unicast.
Whether unicast can be used depends on a lot more factors.
For another thing this flag is not only adding a unicast feature if
all these factors are met, but also adds the dropping feature
introduced by this patchset.
I'd rather keep the naming for the multicast flags to reflect the
capabilities and settings of the local, announcing node.
Cheers, Linus
@@ -145,6 +145,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
if (ret < 0)
goto err;
+ ret = batadv_mcast_init(bat_priv);
+ if (ret < 0)
+ goto err;
+
ret = batadv_gw_init(bat_priv);
if (ret < 0)
goto err;
@@ -68,6 +68,7 @@
#define BATADV_ROAMING_MAX_TIME 20000
#define BATADV_ROAMING_MAX_COUNT 5
+#define BATADV_UNINIT_FLAGS -1
#define BATADV_NO_FLAGS 0
#define BATADV_NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
@@ -169,13 +169,30 @@ void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
struct net_device *soft_iface = bat_priv->soft_iface;
struct hlist_head mcast_list = HLIST_HEAD_INIT;
int ret;
+ static bool enabled;
+ uint8_t mcast_flags;
/* 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->multicast_mode) ||
- bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT)
+ bat_priv->soft_iface->priv_flags & IFF_BRIDGE_PORT) {
+ if (enabled) {
+ batadv_tvlv_container_unregister(bat_priv,
+ BATADV_TVLV_MCAST, 1);
+ enabled = false;
+ }
+
goto update;
+ }
+
+ if (!enabled) {
+ mcast_flags = BATADV_MCAST_LISTENER_ANNOUNCEMENT;
+ batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1,
+ &mcast_flags,
+ sizeof(mcast_flags));
+ enabled = true;
+ }
ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
if (ret < 0)
@@ -190,10 +207,65 @@ out:
}
/**
+ * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig: the orig_node of the ogm
+ * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
+ * @tvlv_value: tvlv buffer containing the multicast data
+ * @tvlv_value_len: tvlv buffer length
+ */
+static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
+ struct batadv_orig_node *orig,
+ uint8_t flags,
+ void *tvlv_value,
+ uint16_t tvlv_value_len)
+{
+ uint8_t mcast_flags = BATADV_NO_FLAGS;
+
+ /* only fetch the tvlv value if the handler wasn't called via the
+ * CIFNOTFND flag and if there is data to fetch
+ */
+ if (!(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
+ (tvlv_value) && (tvlv_value_len == sizeof(mcast_flags)))
+ mcast_flags = *(uint8_t *)tvlv_value;
+
+ if (!(mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT) &&
+ (orig->mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT ||
+ orig->mcast_flags & BATADV_UNINIT_FLAGS))
+ atomic_inc(&bat_priv->mcast.num_no_mla);
+ else if (mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT &&
+ !(orig->mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT))
+ atomic_dec(&bat_priv->mcast.num_no_mla);
+
+ orig->mcast_flags = mcast_flags;
+}
+
+/**
+ * batadv_mcast_init - initialize the multicast optimizations structures
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_mcast_init(struct batadv_priv *bat_priv)
+{
+ batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1,
+ NULL, BATADV_TVLV_MCAST, 1,
+ BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
+ return 0;
+}
+
+/**
* 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_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
+ batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
+
batadv_mcast_mla_tt_clean(bat_priv, NULL);
}
+
+void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node)
+{
+ if (!(orig_node->mcast_flags & BATADV_MCAST_LISTENER_ANNOUNCEMENT))
+ atomic_dec(&orig_node->bat_priv->mcast.num_no_mla);
+}
@@ -24,8 +24,12 @@
void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv);
+int batadv_mcast_init(struct batadv_priv *bat_priv);
+
void batadv_mcast_free(struct batadv_priv *bat_priv);
+void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
+
#else
static inline void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
@@ -33,11 +37,21 @@ static inline void batadv_mcast_mla_tt_update(struct batadv_priv *bat_priv)
return;
}
+static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
+{
+ return 0;
+}
+
static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
{
return;
}
+static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node)
+{
+ return;
+}
+
#endif /* CONFIG_BATMAN_ADV_MCAST */
#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
@@ -29,6 +29,7 @@
#include "bridge_loop_avoidance.h"
#include "network-coding.h"
#include "fragmentation.h"
+#include "multicast.h"
/* hash class keys */
static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -143,6 +144,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
spin_unlock_bh(&orig_node->neigh_list_lock);
+ batadv_mcast_purge_orig(orig_node);
+
/* Free nc_nodes */
batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
@@ -258,6 +261,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
orig_node->bcast_seqno_reset = reset_time;
orig_node->batman_seqno_reset = reset_time;
+#ifdef CONFIG_BATMAN_ADV_MCAST
+ orig_node->mcast_flags = BATADV_UNINIT_FLAGS;
+#endif
atomic_set(&orig_node->bond_candidates, 0);
@@ -91,6 +91,11 @@ enum batadv_icmp_packettype {
BATADV_PARAMETER_PROBLEM = 12,
};
+/* multicast capabilities */
+enum batadv_mcast_flags {
+ BATADV_MCAST_LISTENER_ANNOUNCEMENT = BIT(0),
+};
+
/* tt data subtypes */
#define BATADV_TT_DATA_TYPE_MASK 0x0F
@@ -145,6 +150,7 @@ enum batadv_bla_claimframe {
* @BATADV_TVLV_NC: network coding tvlv
* @BATADV_TVLV_TT: translation table tvlv
* @BATADV_TVLV_ROAM: roaming advertisement tvlv
+ * @BATADV_TVLV_MCAST: multicast capability tvlv
*/
enum batadv_tvlv_type {
BATADV_TVLV_GW = 0x01,
@@ -152,6 +158,7 @@ enum batadv_tvlv_type {
BATADV_TVLV_NC = 0x03,
BATADV_TVLV_TT = 0x04,
BATADV_TVLV_ROAM = 0x05,
+ BATADV_TVLV_MCAST = 0x06,
};
/* the destination hardware field in the ARP frame is used to
@@ -648,6 +648,7 @@ static int batadv_softif_init_late(struct net_device *dev)
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
atomic_set(&bat_priv->multicast_mode, 1);
+ atomic_set(&bat_priv->mcast.num_no_mla, 0);
#endif
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20);
@@ -163,6 +163,9 @@ struct batadv_orig_node {
unsigned long last_seen;
unsigned long bcast_seqno_reset;
unsigned long batman_seqno_reset;
+#ifdef CONFIG_BATMAN_ADV_MCAST
+ int mcast_flags;
+#endif
uint8_t capabilities;
atomic_t last_ttvn;
uint32_t tt_crc;
@@ -504,6 +507,7 @@ struct batadv_priv_dat {
#ifdef CONFIG_BATMAN_ADV_MCAST
struct batadv_priv_mcast {
struct hlist_head mla_list;
+ atomic_t num_no_mla;
};
#endif