@@ -1659,11 +1659,38 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
16591659 }
16601660}
16611661
1662+ static void br_multicast_read_querier (const struct bridge_mcast_querier * querier ,
1663+ struct bridge_mcast_querier * dest )
1664+ {
1665+ unsigned int seq ;
1666+
1667+ memset (dest , 0 , sizeof (* dest ));
1668+ do {
1669+ seq = read_seqcount_begin (& querier -> seq );
1670+ dest -> port_ifidx = querier -> port_ifidx ;
1671+ memcpy (& dest -> addr , & querier -> addr , sizeof (struct br_ip ));
1672+ } while (read_seqcount_retry (& querier -> seq , seq ));
1673+ }
1674+
1675+ static void br_multicast_update_querier (struct net_bridge_mcast * brmctx ,
1676+ struct bridge_mcast_querier * querier ,
1677+ int ifindex ,
1678+ struct br_ip * saddr )
1679+ {
1680+ lockdep_assert_held_once (& brmctx -> br -> multicast_lock );
1681+
1682+ write_seqcount_begin (& querier -> seq );
1683+ querier -> port_ifidx = ifindex ;
1684+ memcpy (& querier -> addr , saddr , sizeof (* saddr ));
1685+ write_seqcount_end (& querier -> seq );
1686+ }
1687+
16621688static void br_multicast_send_query (struct net_bridge_mcast * brmctx ,
16631689 struct net_bridge_mcast_port * pmctx ,
16641690 struct bridge_mcast_own_query * own_query )
16651691{
16661692 struct bridge_mcast_other_query * other_query = NULL ;
1693+ struct bridge_mcast_querier * querier ;
16671694 struct br_ip br_group ;
16681695 unsigned long time ;
16691696
@@ -1676,10 +1703,12 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
16761703
16771704 if (pmctx ? (own_query == & pmctx -> ip4_own_query ) :
16781705 (own_query == & brmctx -> ip4_own_query )) {
1706+ querier = & brmctx -> ip4_querier ;
16791707 other_query = & brmctx -> ip4_other_query ;
16801708 br_group .proto = htons (ETH_P_IP );
16811709#if IS_ENABLED (CONFIG_IPV6 )
16821710 } else {
1711+ querier = & brmctx -> ip6_querier ;
16831712 other_query = & brmctx -> ip6_other_query ;
16841713 br_group .proto = htons (ETH_P_IPV6 );
16851714#endif
@@ -1688,6 +1717,13 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
16881717 if (!other_query || timer_pending (& other_query -> timer ))
16891718 return ;
16901719
1720+ /* we're about to select ourselves as querier */
1721+ if (!pmctx && querier -> port_ifidx ) {
1722+ struct br_ip zeroip = {};
1723+
1724+ br_multicast_update_querier (brmctx , querier , 0 , & zeroip );
1725+ }
1726+
16911727 __br_multicast_send_query (brmctx , pmctx , NULL , NULL , & br_group , false,
16921728 0 , NULL );
16931729
@@ -2828,58 +2864,147 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
28282864}
28292865#endif
28302866
2831- static bool br_ip4_multicast_select_querier (struct net_bridge_mcast * brmctx ,
2832- struct net_bridge_mcast_port * pmctx ,
2833- __be32 saddr )
2867+ static bool br_multicast_select_querier (struct net_bridge_mcast * brmctx ,
2868+ struct net_bridge_mcast_port * pmctx ,
2869+ struct br_ip * saddr )
28342870{
2835- struct net_bridge_port * port = pmctx ? pmctx -> port : NULL ;
2871+ int port_ifidx = pmctx ? pmctx -> port -> dev -> ifindex : 0 ;
2872+ struct timer_list * own_timer , * other_timer ;
2873+ struct bridge_mcast_querier * querier ;
28362874
2837- if (!timer_pending (& brmctx -> ip4_own_query .timer ) &&
2838- !timer_pending (& brmctx -> ip4_other_query .timer ))
2839- goto update ;
2840-
2841- if (!brmctx -> ip4_querier .addr .src .ip4 )
2842- goto update ;
2875+ switch (saddr -> proto ) {
2876+ case htons (ETH_P_IP ):
2877+ querier = & brmctx -> ip4_querier ;
2878+ own_timer = & brmctx -> ip4_own_query .timer ;
2879+ other_timer = & brmctx -> ip4_other_query .timer ;
2880+ if (!querier -> addr .src .ip4 ||
2881+ ntohl (saddr -> src .ip4 ) <= ntohl (querier -> addr .src .ip4 ))
2882+ goto update ;
2883+ break ;
2884+ #if IS_ENABLED (CONFIG_IPV6 )
2885+ case htons (ETH_P_IPV6 ):
2886+ querier = & brmctx -> ip6_querier ;
2887+ own_timer = & brmctx -> ip6_own_query .timer ;
2888+ other_timer = & brmctx -> ip6_other_query .timer ;
2889+ if (ipv6_addr_cmp (& saddr -> src .ip6 , & querier -> addr .src .ip6 ) <= 0 )
2890+ goto update ;
2891+ break ;
2892+ #endif
2893+ default :
2894+ return false;
2895+ }
28432896
2844- if (ntohl ( saddr ) <= ntohl ( brmctx -> ip4_querier . addr . src . ip4 ))
2897+ if (! timer_pending ( own_timer ) && ! timer_pending ( other_timer ))
28452898 goto update ;
28462899
28472900 return false;
28482901
28492902update :
2850- brmctx -> ip4_querier .addr .src .ip4 = saddr ;
2851-
2852- /* update protected by general multicast_lock by caller */
2853- rcu_assign_pointer (brmctx -> ip4_querier .port , port );
2903+ br_multicast_update_querier (brmctx , querier , port_ifidx , saddr );
28542904
28552905 return true;
28562906}
28572907
2858- #if IS_ENABLED (CONFIG_IPV6 )
2859- static bool br_ip6_multicast_select_querier (struct net_bridge_mcast * brmctx ,
2860- struct net_bridge_mcast_port * pmctx ,
2861- struct in6_addr * saddr )
2908+ static struct net_bridge_port *
2909+ __br_multicast_get_querier_port (struct net_bridge * br ,
2910+ const struct bridge_mcast_querier * querier )
28622911{
2863- struct net_bridge_port * port = pmctx ? pmctx -> port : NULL ;
2912+ int port_ifidx = READ_ONCE (querier -> port_ifidx );
2913+ struct net_bridge_port * p ;
2914+ struct net_device * dev ;
28642915
2865- if (!timer_pending (& brmctx -> ip6_own_query .timer ) &&
2866- !timer_pending (& brmctx -> ip6_other_query .timer ))
2867- goto update ;
2916+ if (port_ifidx == 0 )
2917+ return NULL ;
28682918
2869- if (ipv6_addr_cmp (saddr , & brmctx -> ip6_querier .addr .src .ip6 ) <= 0 )
2870- goto update ;
2919+ dev = dev_get_by_index_rcu (dev_net (br -> dev ), port_ifidx );
2920+ if (!dev )
2921+ return NULL ;
2922+ p = br_port_get_rtnl_rcu (dev );
2923+ if (!p || p -> br != br )
2924+ return NULL ;
28712925
2872- return false;
2926+ return p ;
2927+ }
28732928
2874- update :
2875- brmctx -> ip6_querier .addr .src .ip6 = * saddr ;
2929+ size_t br_multicast_querier_state_size (void )
2930+ {
2931+ return nla_total_size (sizeof (0 )) + /* nest attribute */
2932+ nla_total_size (sizeof (__be32 )) + /* BRIDGE_QUERIER_IP_ADDRESS */
2933+ nla_total_size (sizeof (int )) + /* BRIDGE_QUERIER_IP_PORT */
2934+ nla_total_size_64bit (sizeof (u64 )); /* BRIDGE_QUERIER_IP_OTHER_TIMER */
2935+ }
28762936
2877- /* update protected by general multicast_lock by caller */
2878- rcu_assign_pointer (brmctx -> ip6_querier .port , port );
2937+ /* protected by rtnl or rcu */
2938+ int br_multicast_dump_querier_state (struct sk_buff * skb ,
2939+ const struct net_bridge_mcast * brmctx ,
2940+ int nest_attr )
2941+ {
2942+ struct bridge_mcast_querier querier = {};
2943+ struct net_bridge_port * p ;
2944+ struct nlattr * nest ;
28792945
2880- return true;
2881- }
2946+ nest = nla_nest_start (skb , nest_attr );
2947+ if (!nest )
2948+ return - EMSGSIZE ;
2949+
2950+ rcu_read_lock ();
2951+ if (!brmctx -> multicast_querier &&
2952+ !timer_pending (& brmctx -> ip4_other_query .timer ))
2953+ goto out_v6 ;
2954+
2955+ br_multicast_read_querier (& brmctx -> ip4_querier , & querier );
2956+ if (nla_put_in_addr (skb , BRIDGE_QUERIER_IP_ADDRESS ,
2957+ querier .addr .src .ip4 )) {
2958+ rcu_read_unlock ();
2959+ goto out_err ;
2960+ }
2961+
2962+ p = __br_multicast_get_querier_port (brmctx -> br , & querier );
2963+ if (timer_pending (& brmctx -> ip4_other_query .timer ) &&
2964+ (nla_put_u64_64bit (skb , BRIDGE_QUERIER_IP_OTHER_TIMER ,
2965+ br_timer_value (& brmctx -> ip4_other_query .timer ),
2966+ BRIDGE_QUERIER_PAD ) ||
2967+ (p && nla_put_u32 (skb , BRIDGE_QUERIER_IP_PORT , p -> dev -> ifindex )))) {
2968+ rcu_read_unlock ();
2969+ goto out_err ;
2970+ }
2971+
2972+ out_v6 :
2973+ #if IS_ENABLED (CONFIG_IPV6 )
2974+ if (!brmctx -> multicast_querier &&
2975+ !timer_pending (& brmctx -> ip6_other_query .timer ))
2976+ goto out ;
2977+
2978+ br_multicast_read_querier (& brmctx -> ip6_querier , & querier );
2979+ if (nla_put_in6_addr (skb , BRIDGE_QUERIER_IPV6_ADDRESS ,
2980+ & querier .addr .src .ip6 )) {
2981+ rcu_read_unlock ();
2982+ goto out_err ;
2983+ }
2984+
2985+ p = __br_multicast_get_querier_port (brmctx -> br , & querier );
2986+ if (timer_pending (& brmctx -> ip6_other_query .timer ) &&
2987+ (nla_put_u64_64bit (skb , BRIDGE_QUERIER_IPV6_OTHER_TIMER ,
2988+ br_timer_value (& brmctx -> ip6_other_query .timer ),
2989+ BRIDGE_QUERIER_PAD ) ||
2990+ (p && nla_put_u32 (skb , BRIDGE_QUERIER_IPV6_PORT ,
2991+ p -> dev -> ifindex )))) {
2992+ rcu_read_unlock ();
2993+ goto out_err ;
2994+ }
2995+ out :
28822996#endif
2997+ rcu_read_unlock ();
2998+ nla_nest_end (skb , nest );
2999+ if (!nla_len (nest ))
3000+ nla_nest_cancel (skb , nest );
3001+
3002+ return 0 ;
3003+
3004+ out_err :
3005+ nla_nest_cancel (skb , nest );
3006+ return - EMSGSIZE ;
3007+ }
28833008
28843009static void
28853010br_multicast_update_query_timer (struct net_bridge_mcast * brmctx ,
@@ -3082,7 +3207,7 @@ br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
30823207 struct br_ip * saddr ,
30833208 unsigned long max_delay )
30843209{
3085- if (!br_ip4_multicast_select_querier (brmctx , pmctx , saddr -> src . ip4 ))
3210+ if (!br_multicast_select_querier (brmctx , pmctx , saddr ))
30863211 return ;
30873212
30883213 br_multicast_update_query_timer (brmctx , query , max_delay );
@@ -3097,7 +3222,7 @@ br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
30973222 struct br_ip * saddr ,
30983223 unsigned long max_delay )
30993224{
3100- if (!br_ip6_multicast_select_querier (brmctx , pmctx , & saddr -> src . ip6 ))
3225+ if (!br_multicast_select_querier (brmctx , pmctx , saddr ))
31013226 return ;
31023227
31033228 br_multicast_update_query_timer (brmctx , query , max_delay );
@@ -3117,7 +3242,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
31173242 struct igmpv3_query * ih3 ;
31183243 struct net_bridge_port_group * p ;
31193244 struct net_bridge_port_group __rcu * * pp ;
3120- struct br_ip saddr ;
3245+ struct br_ip saddr = {} ;
31213246 unsigned long max_delay ;
31223247 unsigned long now = jiffies ;
31233248 __be32 group ;
@@ -3197,7 +3322,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
31973322 struct mld2_query * mld2q ;
31983323 struct net_bridge_port_group * p ;
31993324 struct net_bridge_port_group __rcu * * pp ;
3200- struct br_ip saddr ;
3325+ struct br_ip saddr = {} ;
32013326 unsigned long max_delay ;
32023327 unsigned long now = jiffies ;
32033328 unsigned int offset = skb_transport_offset (skb );
@@ -3675,7 +3800,6 @@ static void br_multicast_query_expired(struct net_bridge_mcast *brmctx,
36753800 if (query -> startup_sent < brmctx -> multicast_startup_query_count )
36763801 query -> startup_sent ++ ;
36773802
3678- RCU_INIT_POINTER (querier -> port , NULL );
36793803 br_multicast_send_query (brmctx , NULL , query );
36803804out :
36813805 spin_unlock (& brmctx -> br -> multicast_lock );
@@ -3732,12 +3856,14 @@ void br_multicast_ctx_init(struct net_bridge *br,
37323856 brmctx -> multicast_membership_interval = 260 * HZ ;
37333857
37343858 brmctx -> ip4_other_query .delay_time = 0 ;
3735- brmctx -> ip4_querier .port = NULL ;
3859+ brmctx -> ip4_querier .port_ifidx = 0 ;
3860+ seqcount_init (& brmctx -> ip4_querier .seq );
37363861 brmctx -> multicast_igmp_version = 2 ;
37373862#if IS_ENABLED (CONFIG_IPV6 )
37383863 brmctx -> multicast_mld_version = 1 ;
37393864 brmctx -> ip6_other_query .delay_time = 0 ;
3740- brmctx -> ip6_querier .port = NULL ;
3865+ brmctx -> ip6_querier .port_ifidx = 0 ;
3866+ seqcount_init (& brmctx -> ip6_querier .seq );
37413867#endif
37423868
37433869 timer_setup (& brmctx -> ip4_mc_router_timer ,
@@ -4479,6 +4605,7 @@ bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
44794605 struct net_bridge * br ;
44804606 struct net_bridge_port * port ;
44814607 bool ret = false;
4608+ int port_ifidx ;
44824609
44834610 rcu_read_lock ();
44844611 if (!netif_is_bridge_port (dev ))
@@ -4493,14 +4620,16 @@ bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
44934620
44944621 switch (proto ) {
44954622 case ETH_P_IP :
4623+ port_ifidx = brmctx -> ip4_querier .port_ifidx ;
44964624 if (!timer_pending (& brmctx -> ip4_other_query .timer ) ||
4497- rcu_dereference ( brmctx -> ip4_querier . port ) == port )
4625+ port_ifidx == port -> dev -> ifindex )
44984626 goto unlock ;
44994627 break ;
45004628#if IS_ENABLED (CONFIG_IPV6 )
45014629 case ETH_P_IPV6 :
4630+ port_ifidx = brmctx -> ip6_querier .port_ifidx ;
45024631 if (!timer_pending (& brmctx -> ip6_other_query .timer ) ||
4503- rcu_dereference ( brmctx -> ip6_querier . port ) == port )
4632+ port_ifidx == port -> dev -> ifindex )
45044633 goto unlock ;
45054634 break ;
45064635#endif
0 commit comments