Commit 60432d756cf06e597ef9da511402dd059b112447

Authored by Linus Lüssing
Committed by Antonio Quartulli
1 parent e17931d1a6

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>

Showing 7 changed files with 167 additions and 6 deletions Side-by-side Diff

net/batman-adv/main.c
... ... @@ -149,6 +149,7 @@
149 149 goto err;
150 150  
151 151 batadv_gw_init(bat_priv);
  152 + batadv_mcast_init(bat_priv);
152 153  
153 154 atomic_set(&bat_priv->gw.reselect, 0);
154 155 atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
net/batman-adv/multicast.c
... ... @@ -178,11 +178,52 @@
178 178 }
179 179  
180 180 /**
  181 + * batadv_mcast_mla_tvlv_update - update multicast tvlv
  182 + * @bat_priv: the bat priv with all the soft interface information
  183 + *
  184 + * Updates the own multicast tvlv with our current multicast related settings,
  185 + * capabilities and inabilities.
  186 + *
  187 + * Returns true if the tvlv container is registered afterwards. Otherwise
  188 + * returns false.
  189 + */
  190 +static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
  191 +{
  192 + struct batadv_tvlv_mcast_data mcast_data;
  193 +
  194 + mcast_data.flags = BATADV_NO_FLAGS;
  195 + memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
  196 +
  197 + /* Avoid attaching MLAs, if there is a bridge on top of our soft
  198 + * interface, we don't support that yet (TODO)
  199 + */
  200 + if (batadv_mcast_has_bridge(bat_priv)) {
  201 + if (bat_priv->mcast.enabled) {
  202 + batadv_tvlv_container_unregister(bat_priv,
  203 + BATADV_TVLV_MCAST, 1);
  204 + bat_priv->mcast.enabled = false;
  205 + }
  206 +
  207 + return false;
  208 + }
  209 +
  210 + if (!bat_priv->mcast.enabled ||
  211 + mcast_data.flags != bat_priv->mcast.flags) {
  212 + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1,
  213 + &mcast_data, sizeof(mcast_data));
  214 + bat_priv->mcast.flags = mcast_data.flags;
  215 + bat_priv->mcast.enabled = true;
  216 + }
  217 +
  218 + return true;
  219 +}
  220 +
  221 +/**
181 222 * batadv_mcast_mla_update - update the own MLAs
182 223 * @bat_priv: the bat priv with all the soft interface information
183 224 *
184   - * Update the own multicast listener announcements in the translation
185   - * table.
  225 + * Updates the own multicast listener announcements in the translation
  226 + * table as well as the own, announced multicast tvlv container.
186 227 */
187 228 void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
188 229 {
... ... @@ -190,10 +231,7 @@
190 231 struct hlist_head mcast_list = HLIST_HEAD_INIT;
191 232 int ret;
192 233  
193   - /* Avoid attaching MLAs, if there is a bridge on top of our soft
194   - * interface, we don't support that yet (TODO)
195   - */
196   - if (batadv_mcast_has_bridge(bat_priv))
  234 + if (!batadv_mcast_mla_tvlv_update(bat_priv))
197 235 goto update;
198 236  
199 237 ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
200 238  
201 239  
... ... @@ -209,11 +247,84 @@
209 247 }
210 248  
211 249 /**
  250 + * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
  251 + * @bat_priv: the bat priv with all the soft interface information
  252 + * @orig: the orig_node of the ogm
  253 + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
  254 + * @tvlv_value: tvlv buffer containing the multicast data
  255 + * @tvlv_value_len: tvlv buffer length
  256 + */
  257 +static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
  258 + struct batadv_orig_node *orig,
  259 + uint8_t flags,
  260 + void *tvlv_value,
  261 + uint16_t tvlv_value_len)
  262 +{
  263 + bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
  264 + uint8_t mcast_flags = BATADV_NO_FLAGS;
  265 + bool orig_initialized;
  266 +
  267 + orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST;
  268 +
  269 + /* If mcast support is turned on decrease the disabled mcast node
  270 + * counter only if we had increased it for this node before. If this
  271 + * is a completely new orig_node no need to decrease the counter.
  272 + */
  273 + if (orig_mcast_enabled &&
  274 + !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) {
  275 + if (orig_initialized)
  276 + atomic_dec(&bat_priv->mcast.num_disabled);
  277 + orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST;
  278 + /* If mcast support is being switched off increase the disabled
  279 + * mcast node counter.
  280 + */
  281 + } else if (!orig_mcast_enabled &&
  282 + orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) {
  283 + atomic_inc(&bat_priv->mcast.num_disabled);
  284 + orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST;
  285 + }
  286 +
  287 + orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST;
  288 +
  289 + if (orig_mcast_enabled && tvlv_value &&
  290 + (tvlv_value_len >= sizeof(mcast_flags)))
  291 + mcast_flags = *(uint8_t *)tvlv_value;
  292 +
  293 + orig->mcast_flags = mcast_flags;
  294 +}
  295 +
  296 +/**
  297 + * batadv_mcast_init - initialize the multicast optimizations structures
  298 + * @bat_priv: the bat priv with all the soft interface information
  299 + */
  300 +void batadv_mcast_init(struct batadv_priv *bat_priv)
  301 +{
  302 + batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1,
  303 + NULL, BATADV_TVLV_MCAST, 1,
  304 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
  305 +}
  306 +
  307 +/**
212 308 * batadv_mcast_free - free the multicast optimizations structures
213 309 * @bat_priv: the bat priv with all the soft interface information
214 310 */
215 311 void batadv_mcast_free(struct batadv_priv *bat_priv)
216 312 {
  313 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
  314 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
  315 +
217 316 batadv_mcast_mla_tt_retract(bat_priv, NULL);
  317 +}
  318 +
  319 +/**
  320 + * batadv_mcast_purge_orig - reset originator global mcast state modifications
  321 + * @orig: the originator which is going to get purged
  322 + */
  323 +void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
  324 +{
  325 + struct batadv_priv *bat_priv = orig->bat_priv;
  326 +
  327 + if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST))
  328 + atomic_dec(&bat_priv->mcast.num_disabled);
218 329 }
net/batman-adv/multicast.h
... ... @@ -22,8 +22,12 @@
22 22  
23 23 void batadv_mcast_mla_update(struct batadv_priv *bat_priv);
24 24  
  25 +void batadv_mcast_init(struct batadv_priv *bat_priv);
  26 +
25 27 void batadv_mcast_free(struct batadv_priv *bat_priv);
26 28  
  29 +void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
  30 +
27 31 #else
28 32  
29 33 static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
30 34  
... ... @@ -31,7 +35,17 @@
31 35 return;
32 36 }
33 37  
  38 +static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
  39 +{
  40 + return 0;
  41 +}
  42 +
34 43 static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
  44 +{
  45 + return;
  46 +}
  47 +
  48 +static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node)
35 49 {
36 50 return;
37 51 }
net/batman-adv/originator.c
... ... @@ -27,6 +27,7 @@
27 27 #include "bridge_loop_avoidance.h"
28 28 #include "network-coding.h"
29 29 #include "fragmentation.h"
  30 +#include "multicast.h"
30 31  
31 32 /* hash class keys */
32 33 static struct lock_class_key batadv_orig_hash_lock_class_key;
... ... @@ -557,6 +558,8 @@
557 558 }
558 559 spin_unlock_bh(&orig_node->neigh_list_lock);
559 560  
  561 + batadv_mcast_purge_orig(orig_node);
  562 +
560 563 /* Free nc_nodes */
561 564 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
562 565  
... ... @@ -672,6 +675,9 @@
672 675 orig_node->tt_buff_len = 0;
673 676 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
674 677 orig_node->bcast_seqno_reset = reset_time;
  678 +#ifdef CONFIG_BATMAN_ADV_MCAST
  679 + orig_node->mcast_flags = BATADV_NO_FLAGS;
  680 +#endif
675 681  
676 682 /* create a vlan object for the "untagged" LAN */
677 683 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
net/batman-adv/packet.h
... ... @@ -145,6 +145,7 @@
145 145 * @BATADV_TVLV_NC: network coding tvlv
146 146 * @BATADV_TVLV_TT: translation table tvlv
147 147 * @BATADV_TVLV_ROAM: roaming advertisement tvlv
  148 + * @BATADV_TVLV_MCAST: multicast capability tvlv
148 149 */
149 150 enum batadv_tvlv_type {
150 151 BATADV_TVLV_GW = 0x01,
... ... @@ -152,6 +153,7 @@
152 153 BATADV_TVLV_NC = 0x03,
153 154 BATADV_TVLV_TT = 0x04,
154 155 BATADV_TVLV_ROAM = 0x05,
  156 + BATADV_TVLV_MCAST = 0x06,
155 157 };
156 158  
157 159 #pragma pack(2)
... ... @@ -502,6 +504,16 @@
502 504 struct batadv_tvlv_roam_adv {
503 505 uint8_t client[ETH_ALEN];
504 506 __be16 vid;
  507 +};
  508 +
  509 +/**
  510 + * struct batadv_tvlv_mcast_data - payload of a multicast tvlv
  511 + * @flags: multicast flags announced by the orig node
  512 + * @reserved: reserved field
  513 + */
  514 +struct batadv_tvlv_mcast_data {
  515 + uint8_t flags;
  516 + uint8_t reserved[3];
505 517 };
506 518  
507 519 #endif /* _NET_BATMAN_ADV_PACKET_H_ */
net/batman-adv/soft-interface.c
... ... @@ -689,6 +689,10 @@
689 689 #ifdef CONFIG_BATMAN_ADV_DAT
690 690 atomic_set(&bat_priv->distributed_arp_table, 1);
691 691 #endif
  692 +#ifdef CONFIG_BATMAN_ADV_MCAST
  693 + bat_priv->mcast.flags = BATADV_NO_FLAGS;
  694 + atomic_set(&bat_priv->mcast.num_disabled, 0);
  695 +#endif
692 696 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
693 697 atomic_set(&bat_priv->gw_sel_class, 20);
694 698 atomic_set(&bat_priv->gw.bandwidth_down, 100);
net/batman-adv/types.h
... ... @@ -204,6 +204,7 @@
204 204 * @batadv_dat_addr_t: address of the orig node in the distributed hash
205 205 * @last_seen: time when last packet from this node was received
206 206 * @bcast_seqno_reset: time when the broadcast seqno window was reset
  207 + * @mcast_flags: multicast flags announced by the orig node
207 208 * @capabilities: announced capabilities of this originator
208 209 * @capa_initialized: bitfield to remember whether a capability was initialized
209 210 * @last_ttvn: last seen translation table version number
... ... @@ -246,6 +247,9 @@
246 247 #endif
247 248 unsigned long last_seen;
248 249 unsigned long bcast_seqno_reset;
  250 +#ifdef CONFIG_BATMAN_ADV_MCAST
  251 + uint8_t mcast_flags;
  252 +#endif
249 253 uint8_t capabilities;
250 254 uint8_t capa_initialized;
251 255 atomic_t last_ttvn;
252 256  
... ... @@ -282,11 +286,14 @@
282 286 * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled
283 287 * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled
284 288 * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability
  289 + * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability
  290 + * (= orig node announces a tvlv of type BATADV_TVLV_MCAST)
285 291 */
286 292 enum batadv_orig_capabilities {
287 293 BATADV_ORIG_CAPA_HAS_DAT = BIT(0),
288 294 BATADV_ORIG_CAPA_HAS_NC = BIT(1),
289 295 BATADV_ORIG_CAPA_HAS_TT = BIT(2),
  296 + BATADV_ORIG_CAPA_HAS_MCAST = BIT(3),
290 297 };
291 298  
292 299 /**
293 300  
... ... @@ -612,9 +619,15 @@
612 619 /**
613 620 * struct batadv_priv_mcast - per mesh interface mcast data
614 621 * @mla_list: list of multicast addresses we are currently announcing via TT
  622 + * @flags: the flags we have last sent in our mcast tvlv
  623 + * @enabled: whether the multicast tvlv is currently enabled
  624 + * @num_disabled: number of nodes that have no mcast tvlv
615 625 */
616 626 struct batadv_priv_mcast {
617 627 struct hlist_head mla_list;
  628 + uint8_t flags;
  629 + bool enabled;
  630 + atomic_t num_disabled;
618 631 };
619 632 #endif
620 633