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: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
This commit is contained in:
Linus Lüssing 2014-02-15 17:47:51 +01:00 committed by Antonio Quartulli
parent e17931d1a6
commit 60432d756c
7 changed files with 167 additions and 6 deletions

View File

@ -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);

View File

@ -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 @@ out:
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);
}

View File

@ -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_ */

View File

@ -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);

View File

@ -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_ */

View File

@ -688,6 +688,10 @@ static int batadv_softif_init_late(struct net_device *dev)
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_set(&bat_priv->distributed_arp_table, 1);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
bat_priv->mcast.flags = BATADV_NO_FLAGS;
atomic_set(&bat_priv->mcast.num_disabled, 0);
#endif
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20);

View File

@ -204,6 +204,7 @@ struct batadv_orig_bat_iv {
* @batadv_dat_addr_t: address of the orig node in the distributed hash
* @last_seen: time when last packet from this node was received
* @bcast_seqno_reset: time when the broadcast seqno window was reset
* @mcast_flags: multicast flags announced by the orig node
* @capabilities: announced capabilities of this originator
* @capa_initialized: bitfield to remember whether a capability was initialized
* @last_ttvn: last seen translation table version number
@ -246,6 +247,9 @@ struct batadv_orig_node {
#endif
unsigned long last_seen;
unsigned long bcast_seqno_reset;
#ifdef CONFIG_BATMAN_ADV_MCAST
uint8_t mcast_flags;
#endif
uint8_t capabilities;
uint8_t capa_initialized;
atomic_t last_ttvn;
@ -282,11 +286,14 @@ struct batadv_orig_node {
* @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled
* @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled
* @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability
* @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability
* (= orig node announces a tvlv of type BATADV_TVLV_MCAST)
*/
enum batadv_orig_capabilities {
BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
BATADV_ORIG_CAPA_HAS_NC = BIT(1),
BATADV_ORIG_CAPA_HAS_TT = BIT(2),
BATADV_ORIG_CAPA_HAS_MCAST = BIT(3),
};
/**
@ -612,9 +619,15 @@ struct batadv_priv_dat {
/**
* struct batadv_priv_mcast - per mesh interface mcast data
* @mla_list: list of multicast addresses we are currently announcing via TT
* @flags: the flags we have last sent in our mcast tvlv
* @enabled: whether the multicast tvlv is currently enabled
* @num_disabled: number of nodes that have no mcast tvlv
*/
struct batadv_priv_mcast {
struct hlist_head mla_list;
uint8_t flags;
bool enabled;
atomic_t num_disabled;
};
#endif