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:
parent
e17931d1a6
commit
60432d756c
|
@ -149,6 +149,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
batadv_gw_init(bat_priv);
|
batadv_gw_init(bat_priv);
|
||||||
|
batadv_mcast_init(bat_priv);
|
||||||
|
|
||||||
atomic_set(&bat_priv->gw.reselect, 0);
|
atomic_set(&bat_priv->gw.reselect, 0);
|
||||||
atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
|
atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
|
||||||
|
|
|
@ -177,12 +177,53 @@ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
|
||||||
return upper;
|
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
|
* batadv_mcast_mla_update - update the own MLAs
|
||||||
* @bat_priv: the bat priv with all the soft interface information
|
* @bat_priv: the bat priv with all the soft interface information
|
||||||
*
|
*
|
||||||
* Update the own multicast listener announcements in the translation
|
* Updates the own multicast listener announcements in the translation
|
||||||
* table.
|
* table as well as the own, announced multicast tvlv container.
|
||||||
*/
|
*/
|
||||||
void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
|
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;
|
struct hlist_head mcast_list = HLIST_HEAD_INIT;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Avoid attaching MLAs, if there is a bridge on top of our soft
|
if (!batadv_mcast_mla_tvlv_update(bat_priv))
|
||||||
* interface, we don't support that yet (TODO)
|
|
||||||
*/
|
|
||||||
if (batadv_mcast_has_bridge(bat_priv))
|
|
||||||
goto update;
|
goto update;
|
||||||
|
|
||||||
ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
|
ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
|
||||||
|
@ -208,11 +246,84 @@ out:
|
||||||
batadv_mcast_mla_list_free(&mcast_list);
|
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
|
* batadv_mcast_free - free the multicast optimizations structures
|
||||||
* @bat_priv: the bat priv with all the soft interface information
|
* @bat_priv: the bat priv with all the soft interface information
|
||||||
*/
|
*/
|
||||||
void batadv_mcast_free(struct batadv_priv *bat_priv)
|
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_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);
|
||||||
|
}
|
||||||
|
|
|
@ -22,8 +22,12 @@
|
||||||
|
|
||||||
void batadv_mcast_mla_update(struct batadv_priv *bat_priv);
|
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_free(struct batadv_priv *bat_priv);
|
||||||
|
|
||||||
|
void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
|
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;
|
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)
|
static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_BATMAN_ADV_MCAST */
|
#endif /* CONFIG_BATMAN_ADV_MCAST */
|
||||||
|
|
||||||
#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
|
#endif /* _NET_BATMAN_ADV_MULTICAST_H_ */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "bridge_loop_avoidance.h"
|
#include "bridge_loop_avoidance.h"
|
||||||
#include "network-coding.h"
|
#include "network-coding.h"
|
||||||
#include "fragmentation.h"
|
#include "fragmentation.h"
|
||||||
|
#include "multicast.h"
|
||||||
|
|
||||||
/* hash class keys */
|
/* hash class keys */
|
||||||
static struct lock_class_key batadv_orig_hash_lock_class_key;
|
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);
|
spin_unlock_bh(&orig_node->neigh_list_lock);
|
||||||
|
|
||||||
|
batadv_mcast_purge_orig(orig_node);
|
||||||
|
|
||||||
/* Free nc_nodes */
|
/* Free nc_nodes */
|
||||||
batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
|
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;
|
orig_node->tt_buff_len = 0;
|
||||||
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
|
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
|
||||||
orig_node->bcast_seqno_reset = reset_time;
|
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 */
|
/* create a vlan object for the "untagged" LAN */
|
||||||
vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
|
vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum batadv_bla_claimframe {
|
||||||
* @BATADV_TVLV_NC: network coding tvlv
|
* @BATADV_TVLV_NC: network coding tvlv
|
||||||
* @BATADV_TVLV_TT: translation table tvlv
|
* @BATADV_TVLV_TT: translation table tvlv
|
||||||
* @BATADV_TVLV_ROAM: roaming advertisement tvlv
|
* @BATADV_TVLV_ROAM: roaming advertisement tvlv
|
||||||
|
* @BATADV_TVLV_MCAST: multicast capability tvlv
|
||||||
*/
|
*/
|
||||||
enum batadv_tvlv_type {
|
enum batadv_tvlv_type {
|
||||||
BATADV_TVLV_GW = 0x01,
|
BATADV_TVLV_GW = 0x01,
|
||||||
|
@ -152,6 +153,7 @@ enum batadv_tvlv_type {
|
||||||
BATADV_TVLV_NC = 0x03,
|
BATADV_TVLV_NC = 0x03,
|
||||||
BATADV_TVLV_TT = 0x04,
|
BATADV_TVLV_TT = 0x04,
|
||||||
BATADV_TVLV_ROAM = 0x05,
|
BATADV_TVLV_ROAM = 0x05,
|
||||||
|
BATADV_TVLV_MCAST = 0x06,
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(2)
|
#pragma pack(2)
|
||||||
|
@ -504,4 +506,14 @@ struct batadv_tvlv_roam_adv {
|
||||||
__be16 vid;
|
__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_ */
|
#endif /* _NET_BATMAN_ADV_PACKET_H_ */
|
||||||
|
|
|
@ -688,6 +688,10 @@ static int batadv_softif_init_late(struct net_device *dev)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BATMAN_ADV_DAT
|
#ifdef CONFIG_BATMAN_ADV_DAT
|
||||||
atomic_set(&bat_priv->distributed_arp_table, 1);
|
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
|
#endif
|
||||||
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
|
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
|
||||||
atomic_set(&bat_priv->gw_sel_class, 20);
|
atomic_set(&bat_priv->gw_sel_class, 20);
|
||||||
|
|
|
@ -204,6 +204,7 @@ struct batadv_orig_bat_iv {
|
||||||
* @batadv_dat_addr_t: address of the orig node in the distributed hash
|
* @batadv_dat_addr_t: address of the orig node in the distributed hash
|
||||||
* @last_seen: time when last packet from this node was received
|
* @last_seen: time when last packet from this node was received
|
||||||
* @bcast_seqno_reset: time when the broadcast seqno window was reset
|
* @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
|
* @capabilities: announced capabilities of this originator
|
||||||
* @capa_initialized: bitfield to remember whether a capability was initialized
|
* @capa_initialized: bitfield to remember whether a capability was initialized
|
||||||
* @last_ttvn: last seen translation table version number
|
* @last_ttvn: last seen translation table version number
|
||||||
|
@ -246,6 +247,9 @@ struct batadv_orig_node {
|
||||||
#endif
|
#endif
|
||||||
unsigned long last_seen;
|
unsigned long last_seen;
|
||||||
unsigned long bcast_seqno_reset;
|
unsigned long bcast_seqno_reset;
|
||||||
|
#ifdef CONFIG_BATMAN_ADV_MCAST
|
||||||
|
uint8_t mcast_flags;
|
||||||
|
#endif
|
||||||
uint8_t capabilities;
|
uint8_t capabilities;
|
||||||
uint8_t capa_initialized;
|
uint8_t capa_initialized;
|
||||||
atomic_t last_ttvn;
|
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_DAT: orig node has distributed arp table enabled
|
||||||
* @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding 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_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 {
|
enum batadv_orig_capabilities {
|
||||||
BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
|
BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
|
||||||
BATADV_ORIG_CAPA_HAS_NC = BIT(1),
|
BATADV_ORIG_CAPA_HAS_NC = BIT(1),
|
||||||
BATADV_ORIG_CAPA_HAS_TT = BIT(2),
|
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
|
* struct batadv_priv_mcast - per mesh interface mcast data
|
||||||
* @mla_list: list of multicast addresses we are currently announcing via TT
|
* @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 batadv_priv_mcast {
|
||||||
struct hlist_head mla_list;
|
struct hlist_head mla_list;
|
||||||
|
uint8_t flags;
|
||||||
|
bool enabled;
|
||||||
|
atomic_t num_disabled;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue