Commit 60432d756cf06e597ef9da511402dd059b112447
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
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 |