diff options
-rw-r--r-- | net/batman-adv/main.c | 6 | ||||
-rw-r--r-- | net/batman-adv/main.h | 1 | ||||
-rw-r--r-- | net/batman-adv/multicast.c | 135 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 9 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 1 | ||||
-rw-r--r-- | net/batman-adv/types.h | 12 |
6 files changed, 156 insertions, 8 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 8f11b67bc4f4..57b09fa54b14 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -111,6 +111,9 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
111 | spin_lock_init(&bat_priv->tt.last_changeset_lock); | 111 | spin_lock_init(&bat_priv->tt.last_changeset_lock); |
112 | spin_lock_init(&bat_priv->tt.commit_lock); | 112 | spin_lock_init(&bat_priv->tt.commit_lock); |
113 | spin_lock_init(&bat_priv->gw.list_lock); | 113 | spin_lock_init(&bat_priv->gw.list_lock); |
114 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
115 | spin_lock_init(&bat_priv->mcast.want_lists_lock); | ||
116 | #endif | ||
114 | spin_lock_init(&bat_priv->tvlv.container_list_lock); | 117 | spin_lock_init(&bat_priv->tvlv.container_list_lock); |
115 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); | 118 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); |
116 | spin_lock_init(&bat_priv->softif_vlan_list_lock); | 119 | spin_lock_init(&bat_priv->softif_vlan_list_lock); |
@@ -118,6 +121,9 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
118 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 121 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
119 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 122 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
120 | INIT_HLIST_HEAD(&bat_priv->gw.list); | 123 | INIT_HLIST_HEAD(&bat_priv->gw.list); |
124 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
125 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); | ||
126 | #endif | ||
121 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); | 127 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); |
122 | INIT_LIST_HEAD(&bat_priv->tt.req_list); | 128 | INIT_LIST_HEAD(&bat_priv->tt.req_list); |
123 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); | 129 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index aa4f73a044c5..515dce752fd2 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -177,6 +177,7 @@ enum batadv_uev_type { | |||
177 | #include <linux/slab.h> | 177 | #include <linux/slab.h> |
178 | #include <net/sock.h> /* struct sock */ | 178 | #include <net/sock.h> /* struct sock */ |
179 | #include <net/addrconf.h> /* ipv6 address stuff */ | 179 | #include <net/addrconf.h> /* ipv6 address stuff */ |
180 | #include <linux/ip.h> | ||
180 | #include <net/rtnetlink.h> | 181 | #include <net/rtnetlink.h> |
181 | #include <linux/jiffies.h> | 182 | #include <linux/jiffies.h> |
182 | #include <linux/seq_file.h> | 183 | #include <linux/seq_file.h> |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 1d1627fe0de0..a4804fa1ad11 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
@@ -248,9 +248,48 @@ out: | |||
248 | } | 248 | } |
249 | 249 | ||
250 | /** | 250 | /** |
251 | * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential | ||
252 | * @bat_priv: the bat priv with all the soft interface information | ||
253 | * @skb: the IPv4 packet to check | ||
254 | * @is_unsnoopable: stores whether the destination is snoopable | ||
255 | * | ||
256 | * Checks whether the given IPv4 packet has the potential to be forwarded with a | ||
257 | * mode more optimal than classic flooding. | ||
258 | * | ||
259 | * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM in case of | ||
260 | * memory allocation failure. | ||
261 | */ | ||
262 | static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, | ||
263 | struct sk_buff *skb, | ||
264 | bool *is_unsnoopable) | ||
265 | { | ||
266 | struct iphdr *iphdr; | ||
267 | |||
268 | /* We might fail due to out-of-memory -> drop it */ | ||
269 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | iphdr = ip_hdr(skb); | ||
273 | |||
274 | /* TODO: Implement Multicast Router Discovery (RFC4286), | ||
275 | * then allow scope > link local, too | ||
276 | */ | ||
277 | if (!ipv4_is_local_multicast(iphdr->daddr)) | ||
278 | return -EINVAL; | ||
279 | |||
280 | /* link-local multicast listeners behind a bridge are | ||
281 | * not snoopable (see RFC4541, section 2.1.2.2) | ||
282 | */ | ||
283 | *is_unsnoopable = true; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | /** | ||
251 | * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential | 289 | * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential |
252 | * @bat_priv: the bat priv with all the soft interface information | 290 | * @bat_priv: the bat priv with all the soft interface information |
253 | * @skb: the IPv6 packet to check | 291 | * @skb: the IPv6 packet to check |
292 | * @is_unsnoopable: stores whether the destination is snoopable | ||
254 | * | 293 | * |
255 | * Checks whether the given IPv6 packet has the potential to be forwarded with a | 294 | * Checks whether the given IPv6 packet has the potential to be forwarded with a |
256 | * mode more optimal than classic flooding. | 295 | * mode more optimal than classic flooding. |
@@ -259,7 +298,8 @@ out: | |||
259 | * of memory. | 298 | * of memory. |
260 | */ | 299 | */ |
261 | static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | 300 | static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, |
262 | struct sk_buff *skb) | 301 | struct sk_buff *skb, |
302 | bool *is_unsnoopable) | ||
263 | { | 303 | { |
264 | struct ipv6hdr *ip6hdr; | 304 | struct ipv6hdr *ip6hdr; |
265 | 305 | ||
@@ -279,7 +319,7 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | |||
279 | * not snoopable (see RFC4541, section 3, paragraph 3) | 319 | * not snoopable (see RFC4541, section 3, paragraph 3) |
280 | */ | 320 | */ |
281 | if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr)) | 321 | if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr)) |
282 | return -EINVAL; | 322 | *is_unsnoopable = true; |
283 | 323 | ||
284 | return 0; | 324 | return 0; |
285 | } | 325 | } |
@@ -288,6 +328,7 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | |||
288 | * batadv_mcast_forw_mode_check - check for optimized forwarding potential | 328 | * batadv_mcast_forw_mode_check - check for optimized forwarding potential |
289 | * @bat_priv: the bat priv with all the soft interface information | 329 | * @bat_priv: the bat priv with all the soft interface information |
290 | * @skb: the multicast frame to check | 330 | * @skb: the multicast frame to check |
331 | * @is_unsnoopable: stores whether the destination is snoopable | ||
291 | * | 332 | * |
292 | * Checks whether the given multicast ethernet frame has the potential to be | 333 | * Checks whether the given multicast ethernet frame has the potential to be |
293 | * forwarded with a mode more optimal than classic flooding. | 334 | * forwarded with a mode more optimal than classic flooding. |
@@ -296,7 +337,8 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | |||
296 | * of memory. | 337 | * of memory. |
297 | */ | 338 | */ |
298 | static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, | 339 | static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, |
299 | struct sk_buff *skb) | 340 | struct sk_buff *skb, |
341 | bool *is_unsnoopable) | ||
300 | { | 342 | { |
301 | struct ethhdr *ethhdr = eth_hdr(skb); | 343 | struct ethhdr *ethhdr = eth_hdr(skb); |
302 | 344 | ||
@@ -307,8 +349,12 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, | |||
307 | return -EINVAL; | 349 | return -EINVAL; |
308 | 350 | ||
309 | switch (ntohs(ethhdr->h_proto)) { | 351 | switch (ntohs(ethhdr->h_proto)) { |
352 | case ETH_P_IP: | ||
353 | return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, | ||
354 | is_unsnoopable); | ||
310 | case ETH_P_IPV6: | 355 | case ETH_P_IPV6: |
311 | return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb); | 356 | return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb, |
357 | is_unsnoopable); | ||
312 | default: | 358 | default: |
313 | return -EINVAL; | 359 | return -EINVAL; |
314 | } | 360 | } |
@@ -331,6 +377,33 @@ batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv, | |||
331 | } | 377 | } |
332 | 378 | ||
333 | /** | 379 | /** |
380 | * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag | ||
381 | * @bat_priv: the bat priv with all the soft interface information | ||
382 | * | ||
383 | * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag | ||
384 | * set and increases its refcount. | ||
385 | */ | ||
386 | static struct batadv_orig_node * | ||
387 | batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) | ||
388 | { | ||
389 | struct batadv_orig_node *tmp_orig_node, *orig_node = NULL; | ||
390 | |||
391 | rcu_read_lock(); | ||
392 | hlist_for_each_entry_rcu(tmp_orig_node, | ||
393 | &bat_priv->mcast.want_all_unsnoopables_list, | ||
394 | mcast_want_all_unsnoopables_node) { | ||
395 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
396 | continue; | ||
397 | |||
398 | orig_node = tmp_orig_node; | ||
399 | break; | ||
400 | } | ||
401 | rcu_read_unlock(); | ||
402 | |||
403 | return orig_node; | ||
404 | } | ||
405 | |||
406 | /** | ||
334 | * batadv_mcast_forw_mode - check on how to forward a multicast packet | 407 | * batadv_mcast_forw_mode - check on how to forward a multicast packet |
335 | * @bat_priv: the bat priv with all the soft interface information | 408 | * @bat_priv: the bat priv with all the soft interface information |
336 | * @skb: The multicast packet to check | 409 | * @skb: The multicast packet to check |
@@ -344,10 +417,11 @@ enum batadv_forw_mode | |||
344 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | 417 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, |
345 | struct batadv_orig_node **orig) | 418 | struct batadv_orig_node **orig) |
346 | { | 419 | { |
420 | int ret, tt_count, unsnoop_count, total_count; | ||
421 | bool is_unsnoopable = false; | ||
347 | struct ethhdr *ethhdr; | 422 | struct ethhdr *ethhdr; |
348 | int ret, tt_count; | ||
349 | 423 | ||
350 | ret = batadv_mcast_forw_mode_check(bat_priv, skb); | 424 | ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable); |
351 | if (ret == -ENOMEM) | 425 | if (ret == -ENOMEM) |
352 | return BATADV_FORW_NONE; | 426 | return BATADV_FORW_NONE; |
353 | else if (ret < 0) | 427 | else if (ret < 0) |
@@ -357,10 +431,18 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
357 | 431 | ||
358 | tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest, | 432 | tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest, |
359 | BATADV_NO_FLAGS); | 433 | BATADV_NO_FLAGS); |
434 | unsnoop_count = !is_unsnoopable ? 0 : | ||
435 | atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); | ||
436 | |||
437 | total_count = tt_count + unsnoop_count; | ||
360 | 438 | ||
361 | switch (tt_count) { | 439 | switch (total_count) { |
362 | case 1: | 440 | case 1: |
363 | *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr); | 441 | if (tt_count) |
442 | *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr); | ||
443 | else if (unsnoop_count) | ||
444 | *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv); | ||
445 | |||
364 | if (*orig) | 446 | if (*orig) |
365 | return BATADV_FORW_SINGLE; | 447 | return BATADV_FORW_SINGLE; |
366 | 448 | ||
@@ -373,6 +455,39 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
373 | } | 455 | } |
374 | 456 | ||
375 | /** | 457 | /** |
458 | * batadv_mcast_want_unsnoop_update - update unsnoop counter and list | ||
459 | * @bat_priv: the bat priv with all the soft interface information | ||
460 | * @orig: the orig_node which multicast state might have changed of | ||
461 | * @mcast_flags: flags indicating the new multicast state | ||
462 | * | ||
463 | * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator, | ||
464 | * orig, has toggled then this method updates counter and list accordingly. | ||
465 | */ | ||
466 | static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv, | ||
467 | struct batadv_orig_node *orig, | ||
468 | uint8_t mcast_flags) | ||
469 | { | ||
470 | /* switched from flag unset to set */ | ||
471 | if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES && | ||
472 | !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) { | ||
473 | atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables); | ||
474 | |||
475 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
476 | hlist_add_head_rcu(&orig->mcast_want_all_unsnoopables_node, | ||
477 | &bat_priv->mcast.want_all_unsnoopables_list); | ||
478 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
479 | /* switched from flag set to unset */ | ||
480 | } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) && | ||
481 | orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) { | ||
482 | atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables); | ||
483 | |||
484 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
485 | hlist_del_rcu(&orig->mcast_want_all_unsnoopables_node); | ||
486 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
487 | } | ||
488 | } | ||
489 | |||
490 | /** | ||
376 | * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container | 491 | * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container |
377 | * @bat_priv: the bat priv with all the soft interface information | 492 | * @bat_priv: the bat priv with all the soft interface information |
378 | * @orig: the orig_node of the ogm | 493 | * @orig: the orig_node of the ogm |
@@ -416,6 +531,8 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | |||
416 | (tvlv_value_len >= sizeof(mcast_flags))) | 531 | (tvlv_value_len >= sizeof(mcast_flags))) |
417 | mcast_flags = *(uint8_t *)tvlv_value; | 532 | mcast_flags = *(uint8_t *)tvlv_value; |
418 | 533 | ||
534 | batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags); | ||
535 | |||
419 | orig->mcast_flags = mcast_flags; | 536 | orig->mcast_flags = mcast_flags; |
420 | } | 537 | } |
421 | 538 | ||
@@ -452,4 +569,6 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig) | |||
452 | 569 | ||
453 | if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) | 570 | if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) |
454 | atomic_dec(&bat_priv->mcast.num_disabled); | 571 | atomic_dec(&bat_priv->mcast.num_disabled); |
572 | |||
573 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); | ||
455 | } | 574 | } |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e8c483d2da72..d061e26c2045 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -89,6 +89,15 @@ enum batadv_icmp_packettype { | |||
89 | BATADV_PARAMETER_PROBLEM = 12, | 89 | BATADV_PARAMETER_PROBLEM = 12, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /** | ||
93 | * enum batadv_mcast_flags - flags for multicast capabilities and settings | ||
94 | * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for | ||
95 | * 224.0.0.0/24 or ff02::1 | ||
96 | */ | ||
97 | enum batadv_mcast_flags { | ||
98 | BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0), | ||
99 | }; | ||
100 | |||
92 | /* tt data subtypes */ | 101 | /* tt data subtypes */ |
93 | #define BATADV_TT_DATA_TYPE_MASK 0x0F | 102 | #define BATADV_TT_DATA_TYPE_MASK 0x0F |
94 | 103 | ||
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 1a643fe647e1..db6fecaddb9c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -710,6 +710,7 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
710 | bat_priv->mcast.flags = BATADV_NO_FLAGS; | 710 | bat_priv->mcast.flags = BATADV_NO_FLAGS; |
711 | atomic_set(&bat_priv->multicast_mode, 1); | 711 | atomic_set(&bat_priv->multicast_mode, 1); |
712 | atomic_set(&bat_priv->mcast.num_disabled, 0); | 712 | atomic_set(&bat_priv->mcast.num_disabled, 0); |
713 | atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); | ||
713 | #endif | 714 | #endif |
714 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 715 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); |
715 | atomic_set(&bat_priv->gw_sel_class, 20); | 716 | atomic_set(&bat_priv->gw_sel_class, 20); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index c28fc4a403a3..1a674cb19553 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -205,6 +205,8 @@ struct batadv_orig_bat_iv { | |||
205 | * @last_seen: time when last packet from this node was received | 205 | * @last_seen: time when last packet from this node was received |
206 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 206 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
207 | * @mcast_flags: multicast flags announced by the orig node | 207 | * @mcast_flags: multicast flags announced by the orig node |
208 | * @mcast_want_all_unsnoop_node: a list node for the | ||
209 | * mcast.want_all_unsnoopables list | ||
208 | * @capabilities: announced capabilities of this originator | 210 | * @capabilities: announced capabilities of this originator |
209 | * @capa_initialized: bitfield to remember whether a capability was initialized | 211 | * @capa_initialized: bitfield to remember whether a capability was initialized |
210 | * @last_ttvn: last seen translation table version number | 212 | * @last_ttvn: last seen translation table version number |
@@ -249,6 +251,7 @@ struct batadv_orig_node { | |||
249 | unsigned long bcast_seqno_reset; | 251 | unsigned long bcast_seqno_reset; |
250 | #ifdef CONFIG_BATMAN_ADV_MCAST | 252 | #ifdef CONFIG_BATMAN_ADV_MCAST |
251 | uint8_t mcast_flags; | 253 | uint8_t mcast_flags; |
254 | struct hlist_node mcast_want_all_unsnoopables_node; | ||
252 | #endif | 255 | #endif |
253 | uint8_t capabilities; | 256 | uint8_t capabilities; |
254 | uint8_t capa_initialized; | 257 | uint8_t capa_initialized; |
@@ -619,15 +622,24 @@ struct batadv_priv_dat { | |||
619 | /** | 622 | /** |
620 | * struct batadv_priv_mcast - per mesh interface mcast data | 623 | * struct batadv_priv_mcast - per mesh interface mcast data |
621 | * @mla_list: list of multicast addresses we are currently announcing via TT | 624 | * @mla_list: list of multicast addresses we are currently announcing via TT |
625 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable | ||
626 | * multicast traffic | ||
622 | * @flags: the flags we have last sent in our mcast tvlv | 627 | * @flags: the flags we have last sent in our mcast tvlv |
623 | * @enabled: whether the multicast tvlv is currently enabled | 628 | * @enabled: whether the multicast tvlv is currently enabled |
624 | * @num_disabled: number of nodes that have no mcast tvlv | 629 | * @num_disabled: number of nodes that have no mcast tvlv |
630 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic | ||
631 | * @want_lists_lock: lock for protecting modifications to mcast want lists | ||
632 | * (traversals are rcu-locked) | ||
625 | */ | 633 | */ |
626 | struct batadv_priv_mcast { | 634 | struct batadv_priv_mcast { |
627 | struct hlist_head mla_list; | 635 | struct hlist_head mla_list; |
636 | struct hlist_head want_all_unsnoopables_list; | ||
628 | uint8_t flags; | 637 | uint8_t flags; |
629 | bool enabled; | 638 | bool enabled; |
630 | atomic_t num_disabled; | 639 | atomic_t num_disabled; |
640 | atomic_t num_want_all_unsnoopables; | ||
641 | /* protects want_all_unsnoopables_list */ | ||
642 | spinlock_t want_lists_lock; | ||
631 | }; | 643 | }; |
632 | #endif | 644 | #endif |
633 | 645 | ||