@@ -1659,11 +1659,38 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
1659
1659
}
1660
1660
}
1661
1661
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
+
1662
1688
static void br_multicast_send_query (struct net_bridge_mcast * brmctx ,
1663
1689
struct net_bridge_mcast_port * pmctx ,
1664
1690
struct bridge_mcast_own_query * own_query )
1665
1691
{
1666
1692
struct bridge_mcast_other_query * other_query = NULL ;
1693
+ struct bridge_mcast_querier * querier ;
1667
1694
struct br_ip br_group ;
1668
1695
unsigned long time ;
1669
1696
@@ -1676,10 +1703,12 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
1676
1703
1677
1704
if (pmctx ? (own_query == & pmctx -> ip4_own_query ) :
1678
1705
(own_query == & brmctx -> ip4_own_query )) {
1706
+ querier = & brmctx -> ip4_querier ;
1679
1707
other_query = & brmctx -> ip4_other_query ;
1680
1708
br_group .proto = htons (ETH_P_IP );
1681
1709
#if IS_ENABLED (CONFIG_IPV6 )
1682
1710
} else {
1711
+ querier = & brmctx -> ip6_querier ;
1683
1712
other_query = & brmctx -> ip6_other_query ;
1684
1713
br_group .proto = htons (ETH_P_IPV6 );
1685
1714
#endif
@@ -1688,6 +1717,13 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
1688
1717
if (!other_query || timer_pending (& other_query -> timer ))
1689
1718
return ;
1690
1719
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
+
1691
1727
__br_multicast_send_query (brmctx , pmctx , NULL , NULL , & br_group , false,
1692
1728
0 , NULL );
1693
1729
@@ -2828,58 +2864,147 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
2828
2864
}
2829
2865
#endif
2830
2866
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 )
2834
2870
{
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 ;
2836
2874
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
+ }
2843
2896
2844
- if (ntohl ( saddr ) <= ntohl ( brmctx -> ip4_querier . addr . src . ip4 ))
2897
+ if (! timer_pending ( own_timer ) && ! timer_pending ( other_timer ))
2845
2898
goto update ;
2846
2899
2847
2900
return false;
2848
2901
2849
2902
update :
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 );
2854
2904
2855
2905
return true;
2856
2906
}
2857
2907
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 )
2862
2911
{
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 ;
2864
2915
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 ;
2868
2918
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 ;
2871
2925
2872
- return false;
2926
+ return p ;
2927
+ }
2873
2928
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
+ }
2876
2936
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 ;
2879
2945
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 :
2882
2996
#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
+ }
2883
3008
2884
3009
static void
2885
3010
br_multicast_update_query_timer (struct net_bridge_mcast * brmctx ,
@@ -3082,7 +3207,7 @@ br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
3082
3207
struct br_ip * saddr ,
3083
3208
unsigned long max_delay )
3084
3209
{
3085
- if (!br_ip4_multicast_select_querier (brmctx , pmctx , saddr -> src . ip4 ))
3210
+ if (!br_multicast_select_querier (brmctx , pmctx , saddr ))
3086
3211
return ;
3087
3212
3088
3213
br_multicast_update_query_timer (brmctx , query , max_delay );
@@ -3097,7 +3222,7 @@ br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
3097
3222
struct br_ip * saddr ,
3098
3223
unsigned long max_delay )
3099
3224
{
3100
- if (!br_ip6_multicast_select_querier (brmctx , pmctx , & saddr -> src . ip6 ))
3225
+ if (!br_multicast_select_querier (brmctx , pmctx , saddr ))
3101
3226
return ;
3102
3227
3103
3228
br_multicast_update_query_timer (brmctx , query , max_delay );
@@ -3117,7 +3242,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
3117
3242
struct igmpv3_query * ih3 ;
3118
3243
struct net_bridge_port_group * p ;
3119
3244
struct net_bridge_port_group __rcu * * pp ;
3120
- struct br_ip saddr ;
3245
+ struct br_ip saddr = {} ;
3121
3246
unsigned long max_delay ;
3122
3247
unsigned long now = jiffies ;
3123
3248
__be32 group ;
@@ -3197,7 +3322,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
3197
3322
struct mld2_query * mld2q ;
3198
3323
struct net_bridge_port_group * p ;
3199
3324
struct net_bridge_port_group __rcu * * pp ;
3200
- struct br_ip saddr ;
3325
+ struct br_ip saddr = {} ;
3201
3326
unsigned long max_delay ;
3202
3327
unsigned long now = jiffies ;
3203
3328
unsigned int offset = skb_transport_offset (skb );
@@ -3675,7 +3800,6 @@ static void br_multicast_query_expired(struct net_bridge_mcast *brmctx,
3675
3800
if (query -> startup_sent < brmctx -> multicast_startup_query_count )
3676
3801
query -> startup_sent ++ ;
3677
3802
3678
- RCU_INIT_POINTER (querier -> port , NULL );
3679
3803
br_multicast_send_query (brmctx , NULL , query );
3680
3804
out :
3681
3805
spin_unlock (& brmctx -> br -> multicast_lock );
@@ -3732,12 +3856,14 @@ void br_multicast_ctx_init(struct net_bridge *br,
3732
3856
brmctx -> multicast_membership_interval = 260 * HZ ;
3733
3857
3734
3858
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 );
3736
3861
brmctx -> multicast_igmp_version = 2 ;
3737
3862
#if IS_ENABLED (CONFIG_IPV6 )
3738
3863
brmctx -> multicast_mld_version = 1 ;
3739
3864
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 );
3741
3867
#endif
3742
3868
3743
3869
timer_setup (& brmctx -> ip4_mc_router_timer ,
@@ -4479,6 +4605,7 @@ bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
4479
4605
struct net_bridge * br ;
4480
4606
struct net_bridge_port * port ;
4481
4607
bool ret = false;
4608
+ int port_ifidx ;
4482
4609
4483
4610
rcu_read_lock ();
4484
4611
if (!netif_is_bridge_port (dev ))
@@ -4493,14 +4620,16 @@ bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
4493
4620
4494
4621
switch (proto ) {
4495
4622
case ETH_P_IP :
4623
+ port_ifidx = brmctx -> ip4_querier .port_ifidx ;
4496
4624
if (!timer_pending (& brmctx -> ip4_other_query .timer ) ||
4497
- rcu_dereference ( brmctx -> ip4_querier . port ) == port )
4625
+ port_ifidx == port -> dev -> ifindex )
4498
4626
goto unlock ;
4499
4627
break ;
4500
4628
#if IS_ENABLED (CONFIG_IPV6 )
4501
4629
case ETH_P_IPV6 :
4630
+ port_ifidx = brmctx -> ip6_querier .port_ifidx ;
4502
4631
if (!timer_pending (& brmctx -> ip6_other_query .timer ) ||
4503
- rcu_dereference ( brmctx -> ip6_querier . port ) == port )
4632
+ port_ifidx == port -> dev -> ifindex )
4504
4633
goto unlock ;
4505
4634
break ;
4506
4635
#endif
0 commit comments