aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/main.c2
-rw-r--r--net/batman-adv/multicast.c178
-rw-r--r--net/batman-adv/packet.h4
-rw-r--r--net/batman-adv/send.c1
-rw-r--r--net/batman-adv/soft-interface.c2
-rw-r--r--net/batman-adv/types.h14
6 files changed, 198 insertions, 3 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 57b09fa54b14..d1183e882167 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -123,6 +123,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
123 INIT_HLIST_HEAD(&bat_priv->gw.list); 123 INIT_HLIST_HEAD(&bat_priv->gw.list);
124#ifdef CONFIG_BATMAN_ADV_MCAST 124#ifdef CONFIG_BATMAN_ADV_MCAST
125 INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); 125 INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list);
126 INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list);
127 INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv6_list);
126#endif 128#endif
127 INIT_LIST_HEAD(&bat_priv->tt.changes_list); 129 INIT_LIST_HEAD(&bat_priv->tt.changes_list);
128 INIT_LIST_HEAD(&bat_priv->tt.req_list); 130 INIT_LIST_HEAD(&bat_priv->tt.req_list);
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index a4804fa1ad11..8c7ca811de6e 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -361,6 +361,29 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
361} 361}
362 362
363/** 363/**
364 * batadv_mcast_want_all_ip_count - count nodes with unspecific mcast interest
365 * @bat_priv: the bat priv with all the soft interface information
366 * @ethhdr: ethernet header of a packet
367 *
368 * Returns the number of nodes which want all IPv4 multicast traffic if the
369 * given ethhdr is from an IPv4 packet or the number of nodes which want all
370 * IPv6 traffic if it matches an IPv6 packet.
371 */
372static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv,
373 struct ethhdr *ethhdr)
374{
375 switch (ntohs(ethhdr->h_proto)) {
376 case ETH_P_IP:
377 return atomic_read(&bat_priv->mcast.num_want_all_ipv4);
378 case ETH_P_IPV6:
379 return atomic_read(&bat_priv->mcast.num_want_all_ipv6);
380 default:
381 /* we shouldn't be here... */
382 return 0;
383 }
384}
385
386/**
364 * batadv_mcast_forw_tt_node_get - get a multicast tt node 387 * batadv_mcast_forw_tt_node_get - get a multicast tt node
365 * @bat_priv: the bat priv with all the soft interface information 388 * @bat_priv: the bat priv with all the soft interface information
366 * @ethhdr: the ether header containing the multicast destination 389 * @ethhdr: the ether header containing the multicast destination
@@ -377,6 +400,84 @@ batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
377} 400}
378 401
379/** 402/**
403 * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag
404 * @bat_priv: the bat priv with all the soft interface information
405 *
406 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and
407 * increases its refcount.
408 */
409static struct batadv_orig_node *
410batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
411{
412 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
413
414 rcu_read_lock();
415 hlist_for_each_entry_rcu(tmp_orig_node,
416 &bat_priv->mcast.want_all_ipv4_list,
417 mcast_want_all_ipv4_node) {
418 if (!atomic_inc_not_zero(&orig_node->refcount))
419 continue;
420
421 orig_node = tmp_orig_node;
422 break;
423 }
424 rcu_read_unlock();
425
426 return orig_node;
427}
428
429/**
430 * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag
431 * @bat_priv: the bat priv with all the soft interface information
432 *
433 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set
434 * and increases its refcount.
435 */
436static struct batadv_orig_node *
437batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
438{
439 struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
440
441 rcu_read_lock();
442 hlist_for_each_entry_rcu(tmp_orig_node,
443 &bat_priv->mcast.want_all_ipv6_list,
444 mcast_want_all_ipv6_node) {
445 if (!atomic_inc_not_zero(&orig_node->refcount))
446 continue;
447
448 orig_node = tmp_orig_node;
449 break;
450 }
451 rcu_read_unlock();
452
453 return orig_node;
454}
455
456/**
457 * batadv_mcast_want_forw_ip_node_get - get a node with an ipv4/ipv6 flag
458 * @bat_priv: the bat priv with all the soft interface information
459 * @ethhdr: an ethernet header to determine the protocol family from
460 *
461 * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or
462 * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and
463 * increases its refcount.
464 */
465static struct batadv_orig_node *
466batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv,
467 struct ethhdr *ethhdr)
468{
469 switch (ntohs(ethhdr->h_proto)) {
470 case ETH_P_IP:
471 return batadv_mcast_forw_ipv4_node_get(bat_priv);
472 case ETH_P_IPV6:
473 return batadv_mcast_forw_ipv6_node_get(bat_priv);
474 default:
475 /* we shouldn't be here... */
476 return NULL;
477 }
478}
479
480/**
380 * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag 481 * 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 482 * @bat_priv: the bat priv with all the soft interface information
382 * 483 *
@@ -417,7 +518,7 @@ enum batadv_forw_mode
417batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, 518batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
418 struct batadv_orig_node **orig) 519 struct batadv_orig_node **orig)
419{ 520{
420 int ret, tt_count, unsnoop_count, total_count; 521 int ret, tt_count, ip_count, unsnoop_count, total_count;
421 bool is_unsnoopable = false; 522 bool is_unsnoopable = false;
422 struct ethhdr *ethhdr; 523 struct ethhdr *ethhdr;
423 524
@@ -431,15 +532,18 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
431 532
432 tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest, 533 tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
433 BATADV_NO_FLAGS); 534 BATADV_NO_FLAGS);
535 ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
434 unsnoop_count = !is_unsnoopable ? 0 : 536 unsnoop_count = !is_unsnoopable ? 0 :
435 atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); 537 atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
436 538
437 total_count = tt_count + unsnoop_count; 539 total_count = tt_count + ip_count + unsnoop_count;
438 540
439 switch (total_count) { 541 switch (total_count) {
440 case 1: 542 case 1:
441 if (tt_count) 543 if (tt_count)
442 *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr); 544 *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
545 else if (ip_count)
546 *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr);
443 else if (unsnoop_count) 547 else if (unsnoop_count)
444 *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv); 548 *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv);
445 549
@@ -488,6 +592,72 @@ static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
488} 592}
489 593
490/** 594/**
595 * batadv_mcast_want_ipv4_update - update want-all-ipv4 counter and list
596 * @bat_priv: the bat priv with all the soft interface information
597 * @orig: the orig_node which multicast state might have changed of
598 * @mcast_flags: flags indicating the new multicast state
599 *
600 * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has
601 * toggled then this method updates counter and list accordingly.
602 */
603static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
604 struct batadv_orig_node *orig,
605 uint8_t mcast_flags)
606{
607 /* switched from flag unset to set */
608 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 &&
609 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) {
610 atomic_inc(&bat_priv->mcast.num_want_all_ipv4);
611
612 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
613 hlist_add_head_rcu(&orig->mcast_want_all_ipv4_node,
614 &bat_priv->mcast.want_all_ipv4_list);
615 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
616 /* switched from flag set to unset */
617 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) &&
618 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) {
619 atomic_dec(&bat_priv->mcast.num_want_all_ipv4);
620
621 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
622 hlist_del_rcu(&orig->mcast_want_all_ipv4_node);
623 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
624 }
625}
626
627/**
628 * batadv_mcast_want_ipv6_update - update want-all-ipv6 counter and list
629 * @bat_priv: the bat priv with all the soft interface information
630 * @orig: the orig_node which multicast state might have changed of
631 * @mcast_flags: flags indicating the new multicast state
632 *
633 * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has
634 * toggled then this method updates counter and list accordingly.
635 */
636static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
637 struct batadv_orig_node *orig,
638 uint8_t mcast_flags)
639{
640 /* switched from flag unset to set */
641 if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 &&
642 !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) {
643 atomic_inc(&bat_priv->mcast.num_want_all_ipv6);
644
645 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
646 hlist_add_head_rcu(&orig->mcast_want_all_ipv6_node,
647 &bat_priv->mcast.want_all_ipv6_list);
648 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
649 /* switched from flag set to unset */
650 } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) &&
651 orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) {
652 atomic_dec(&bat_priv->mcast.num_want_all_ipv6);
653
654 spin_lock_bh(&bat_priv->mcast.want_lists_lock);
655 hlist_del_rcu(&orig->mcast_want_all_ipv6_node);
656 spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
657 }
658}
659
660/**
491 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container 661 * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
492 * @bat_priv: the bat priv with all the soft interface information 662 * @bat_priv: the bat priv with all the soft interface information
493 * @orig: the orig_node of the ogm 663 * @orig: the orig_node of the ogm
@@ -532,6 +702,8 @@ static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
532 mcast_flags = *(uint8_t *)tvlv_value; 702 mcast_flags = *(uint8_t *)tvlv_value;
533 703
534 batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags); 704 batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags);
705 batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags);
706 batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
535 707
536 orig->mcast_flags = mcast_flags; 708 orig->mcast_flags = mcast_flags;
537} 709}
@@ -571,4 +743,6 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
571 atomic_dec(&bat_priv->mcast.num_disabled); 743 atomic_dec(&bat_priv->mcast.num_disabled);
572 744
573 batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); 745 batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
746 batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
747 batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
574} 748}
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index d061e26c2045..c7f6eefda681 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -93,9 +93,13 @@ enum batadv_icmp_packettype {
93 * enum batadv_mcast_flags - flags for multicast capabilities and settings 93 * enum batadv_mcast_flags - flags for multicast capabilities and settings
94 * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for 94 * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for
95 * 224.0.0.0/24 or ff02::1 95 * 224.0.0.0/24 or ff02::1
96 * @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets
97 * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets
96 */ 98 */
97enum batadv_mcast_flags { 99enum batadv_mcast_flags {
98 BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0), 100 BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0),
101 BATADV_MCAST_WANT_ALL_IPV4 = BIT(1),
102 BATADV_MCAST_WANT_ALL_IPV6 = BIT(2),
99}; 103};
100 104
101/* tt data subtypes */ 105/* tt data subtypes */
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 8bee5e8536b7..3d64ed20c393 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -27,6 +27,7 @@
27#include "originator.h" 27#include "originator.h"
28#include "network-coding.h" 28#include "network-coding.h"
29#include "fragmentation.h" 29#include "fragmentation.h"
30#include "multicast.h"
30 31
31static void batadv_send_outstanding_bcast_packet(struct work_struct *work); 32static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
32 33
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index db6fecaddb9c..744a59b85e15 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -711,6 +711,8 @@ static int batadv_softif_init_late(struct net_device *dev)
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 atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0);
714 atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0);
715 atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
714#endif 716#endif
715 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 717 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
716 atomic_set(&bat_priv->gw_sel_class, 20); 718 atomic_set(&bat_priv->gw_sel_class, 20);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 1a674cb19553..d4b923c7229c 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -207,6 +207,8 @@ struct batadv_orig_bat_iv {
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 208 * @mcast_want_all_unsnoop_node: a list node for the
209 * mcast.want_all_unsnoopables list 209 * mcast.want_all_unsnoopables list
210 * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list
211 * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list
210 * @capabilities: announced capabilities of this originator 212 * @capabilities: announced capabilities of this originator
211 * @capa_initialized: bitfield to remember whether a capability was initialized 213 * @capa_initialized: bitfield to remember whether a capability was initialized
212 * @last_ttvn: last seen translation table version number 214 * @last_ttvn: last seen translation table version number
@@ -252,6 +254,8 @@ struct batadv_orig_node {
252#ifdef CONFIG_BATMAN_ADV_MCAST 254#ifdef CONFIG_BATMAN_ADV_MCAST
253 uint8_t mcast_flags; 255 uint8_t mcast_flags;
254 struct hlist_node mcast_want_all_unsnoopables_node; 256 struct hlist_node mcast_want_all_unsnoopables_node;
257 struct hlist_node mcast_want_all_ipv4_node;
258 struct hlist_node mcast_want_all_ipv6_node;
255#endif 259#endif
256 uint8_t capabilities; 260 uint8_t capabilities;
257 uint8_t capa_initialized; 261 uint8_t capa_initialized;
@@ -624,21 +628,29 @@ struct batadv_priv_dat {
624 * @mla_list: list of multicast addresses we are currently announcing via TT 628 * @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 629 * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable
626 * multicast traffic 630 * multicast traffic
631 * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic
632 * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic
627 * @flags: the flags we have last sent in our mcast tvlv 633 * @flags: the flags we have last sent in our mcast tvlv
628 * @enabled: whether the multicast tvlv is currently enabled 634 * @enabled: whether the multicast tvlv is currently enabled
629 * @num_disabled: number of nodes that have no mcast tvlv 635 * @num_disabled: number of nodes that have no mcast tvlv
630 * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic 636 * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic
637 * @num_want_all_ipv4: counter for items in want_all_ipv4_list
638 * @num_want_all_ipv6: counter for items in want_all_ipv6_list
631 * @want_lists_lock: lock for protecting modifications to mcast want lists 639 * @want_lists_lock: lock for protecting modifications to mcast want lists
632 * (traversals are rcu-locked) 640 * (traversals are rcu-locked)
633 */ 641 */
634struct batadv_priv_mcast { 642struct batadv_priv_mcast {
635 struct hlist_head mla_list; 643 struct hlist_head mla_list;
636 struct hlist_head want_all_unsnoopables_list; 644 struct hlist_head want_all_unsnoopables_list;
645 struct hlist_head want_all_ipv4_list;
646 struct hlist_head want_all_ipv6_list;
637 uint8_t flags; 647 uint8_t flags;
638 bool enabled; 648 bool enabled;
639 atomic_t num_disabled; 649 atomic_t num_disabled;
640 atomic_t num_want_all_unsnoopables; 650 atomic_t num_want_all_unsnoopables;
641 /* protects want_all_unsnoopables_list */ 651 atomic_t num_want_all_ipv4;
652 atomic_t num_want_all_ipv6;
653 /* protects want_all_{unsnoopables,ipv4,ipv6}_list */
642 spinlock_t want_lists_lock; 654 spinlock_t want_lists_lock;
643}; 655};
644#endif 656#endif