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:
Родитель
e17931d1a6
Коммит
60432d756c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче