Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60432d75 authored by Linus Lüssing's avatar Linus Lüssing Committed by Antonio Quartulli
Browse files

batman-adv: Announce new capability via multicast TVLV



If the soft interface of a node is not part of a bridge then a node
announces a new multicast TVLV: The existence of this TVLV
signalizes that this node is announcing all of its multicast listeners
via the translation table infrastructure.

Signed-off-by: default avatarLinus Lüssing <linus.luessing@web.de>
Signed-off-by: default avatarMarek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: default avatarAntonio Quartulli <antonio@meshcoding.com>
parent e17931d1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
		goto err;

	batadv_gw_init(bat_priv);
	batadv_mcast_init(bat_priv);

	atomic_set(&bat_priv->gw.reselect, 0);
	atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
+117 −6
Original line number Diff line number Diff line
@@ -177,12 +177,53 @@ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
	return upper;
}

/**
 * batadv_mcast_mla_tvlv_update - update multicast tvlv
 * @bat_priv: the bat priv with all the soft interface information
 *
 * Updates the own multicast tvlv with our current multicast related settings,
 * capabilities and inabilities.
 *
 * Returns true if the tvlv container is registered afterwards. Otherwise
 * returns false.
 */
static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
{
	struct batadv_tvlv_mcast_data mcast_data;

	mcast_data.flags = BATADV_NO_FLAGS;
	memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));

	/* Avoid attaching MLAs, if there is a bridge on top of our soft
	 * interface, we don't support that yet (TODO)
	 */
	if (batadv_mcast_has_bridge(bat_priv)) {
		if (bat_priv->mcast.enabled) {
			batadv_tvlv_container_unregister(bat_priv,
							 BATADV_TVLV_MCAST, 1);
			bat_priv->mcast.enabled = false;
		}

		return false;
	}

	if (!bat_priv->mcast.enabled ||
	    mcast_data.flags != bat_priv->mcast.flags) {
		batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1,
					       &mcast_data, sizeof(mcast_data));
		bat_priv->mcast.flags = mcast_data.flags;
		bat_priv->mcast.enabled = true;
	}

	return true;
}

/**
 * batadv_mcast_mla_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.
 * Updates the own multicast listener announcements in the translation
 * table as well as the own, announced multicast tvlv container.
 */
void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
{
@@ -190,10 +231,7 @@ void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
	struct hlist_head mcast_list = HLIST_HEAD_INIT;
	int ret;

	/* Avoid attaching MLAs, if there is a bridge on top of our soft
	 * interface, we don't support that yet (TODO)
	 */
	if (batadv_mcast_has_bridge(bat_priv))
	if (!batadv_mcast_mla_tvlv_update(bat_priv))
		goto update;

	ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
@@ -208,11 +246,84 @@ void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
	batadv_mcast_mla_list_free(&mcast_list);
}

/**
 * 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)
{
	bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
	uint8_t mcast_flags = BATADV_NO_FLAGS;
	bool orig_initialized;

	orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST;

	/* If mcast support is turned on decrease the disabled mcast node
	 * counter only if we had increased it for this node before. If this
	 * is a completely new orig_node no need to decrease the counter.
	 */
	if (orig_mcast_enabled &&
	    !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) {
		if (orig_initialized)
			atomic_dec(&bat_priv->mcast.num_disabled);
		orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST;
	/* If mcast support is being switched off increase the disabled
	 * mcast node counter.
	 */
	} else if (!orig_mcast_enabled &&
		   orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) {
		atomic_inc(&bat_priv->mcast.num_disabled);
		orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST;
	}

	orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST;

	if (orig_mcast_enabled && tvlv_value &&
	    (tvlv_value_len >= sizeof(mcast_flags)))
		mcast_flags = *(uint8_t *)tvlv_value;

	orig->mcast_flags = mcast_flags;
}

/**
 * batadv_mcast_init - initialize the multicast optimizations structures
 * @bat_priv: the bat priv with all the soft interface information
 */
void 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);
}

/**
 * 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_retract(bat_priv, NULL);
}

/**
 * batadv_mcast_purge_orig - reset originator global mcast state modifications
 * @orig: the originator which is going to get purged
 */
void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
{
	struct batadv_priv *bat_priv = orig->bat_priv;

	if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST))
		atomic_dec(&bat_priv->mcast.num_disabled);
}
+14 −0
Original line number Diff line number Diff line
@@ -22,8 +22,12 @@

void batadv_mcast_mla_update(struct batadv_priv *bat_priv);

void 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_update(struct batadv_priv *bat_priv)
@@ -31,11 +35,21 @@ static inline void batadv_mcast_mla_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_ */
+6 −0
Original line number Diff line number Diff line
@@ -27,6 +27,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;
@@ -557,6 +558,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);

@@ -672,6 +675,9 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
	orig_node->tt_buff_len = 0;
	reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
	orig_node->bcast_seqno_reset = reset_time;
#ifdef CONFIG_BATMAN_ADV_MCAST
	orig_node->mcast_flags = BATADV_NO_FLAGS;
#endif

	/* create a vlan object for the "untagged" LAN */
	vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
+12 −0
Original line number Diff line number Diff line
@@ -145,6 +145,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 +153,7 @@ enum batadv_tvlv_type {
	BATADV_TVLV_NC		= 0x03,
	BATADV_TVLV_TT		= 0x04,
	BATADV_TVLV_ROAM	= 0x05,
	BATADV_TVLV_MCAST	= 0x06,
};

#pragma pack(2)
@@ -504,4 +506,14 @@ struct batadv_tvlv_roam_adv {
	__be16 vid;
};

/**
 * struct batadv_tvlv_mcast_data - payload of a multicast tvlv
 * @flags: multicast flags announced by the orig node
 * @reserved: reserved field
 */
struct batadv_tvlv_mcast_data {
	uint8_t	flags;
	uint8_t reserved[3];
};

#endif /* _NET_BATMAN_ADV_PACKET_H_ */
Loading