@@ -1797,9 +1797,9 @@ void br_multicast_enable_port(struct net_bridge_port *port)
1797
1797
{
1798
1798
struct net_bridge * br = port -> br ;
1799
1799
1800
- spin_lock (& br -> multicast_lock );
1800
+ spin_lock_bh (& br -> multicast_lock );
1801
1801
__br_multicast_enable_port_ctx (& port -> multicast_ctx );
1802
- spin_unlock (& br -> multicast_lock );
1802
+ spin_unlock_bh (& br -> multicast_lock );
1803
1803
}
1804
1804
1805
1805
static void __br_multicast_disable_port_ctx (struct net_bridge_mcast_port * pmctx )
@@ -1827,9 +1827,9 @@ static void __br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
1827
1827
1828
1828
void br_multicast_disable_port (struct net_bridge_port * port )
1829
1829
{
1830
- spin_lock (& port -> br -> multicast_lock );
1830
+ spin_lock_bh (& port -> br -> multicast_lock );
1831
1831
__br_multicast_disable_port_ctx (& port -> multicast_ctx );
1832
- spin_unlock (& port -> br -> multicast_lock );
1832
+ spin_unlock_bh (& port -> br -> multicast_lock );
1833
1833
}
1834
1834
1835
1835
static int __grp_src_delete_marked (struct net_bridge_port_group * pg )
@@ -3510,25 +3510,46 @@ static int br_multicast_ipv6_rcv(struct net_bridge_mcast *brmctx,
3510
3510
}
3511
3511
#endif
3512
3512
3513
- int br_multicast_rcv (struct net_bridge_mcast * brmctx ,
3514
- struct net_bridge_mcast_port * pmctx ,
3513
+ int br_multicast_rcv (struct net_bridge_mcast * * brmctx ,
3514
+ struct net_bridge_mcast_port * * pmctx ,
3515
+ struct net_bridge_vlan * vlan ,
3515
3516
struct sk_buff * skb , u16 vid )
3516
3517
{
3517
3518
int ret = 0 ;
3518
3519
3519
3520
BR_INPUT_SKB_CB (skb )-> igmp = 0 ;
3520
3521
BR_INPUT_SKB_CB (skb )-> mrouters_only = 0 ;
3521
3522
3522
- if (!br_opt_get (brmctx -> br , BROPT_MULTICAST_ENABLED ))
3523
+ if (!br_opt_get (( * brmctx ) -> br , BROPT_MULTICAST_ENABLED ))
3523
3524
return 0 ;
3524
3525
3526
+ if (br_opt_get ((* brmctx )-> br , BROPT_MCAST_VLAN_SNOOPING_ENABLED ) && vlan ) {
3527
+ const struct net_bridge_vlan * masterv ;
3528
+
3529
+ /* the vlan has the master flag set only when transmitting
3530
+ * through the bridge device
3531
+ */
3532
+ if (br_vlan_is_master (vlan )) {
3533
+ masterv = vlan ;
3534
+ * brmctx = & vlan -> br_mcast_ctx ;
3535
+ * pmctx = NULL ;
3536
+ } else {
3537
+ masterv = vlan -> brvlan ;
3538
+ * brmctx = & vlan -> brvlan -> br_mcast_ctx ;
3539
+ * pmctx = & vlan -> port_mcast_ctx ;
3540
+ }
3541
+
3542
+ if (!(masterv -> priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED ))
3543
+ return 0 ;
3544
+ }
3545
+
3525
3546
switch (skb -> protocol ) {
3526
3547
case htons (ETH_P_IP ):
3527
- ret = br_multicast_ipv4_rcv (brmctx , pmctx , skb , vid );
3548
+ ret = br_multicast_ipv4_rcv (* brmctx , * pmctx , skb , vid );
3528
3549
break ;
3529
3550
#if IS_ENABLED (CONFIG_IPV6 )
3530
3551
case htons (ETH_P_IPV6 ):
3531
- ret = br_multicast_ipv6_rcv (brmctx , pmctx , skb , vid );
3552
+ ret = br_multicast_ipv6_rcv (* brmctx , * pmctx , skb , vid );
3532
3553
break ;
3533
3554
#endif
3534
3555
}
@@ -3727,20 +3748,22 @@ static void __br_multicast_open(struct net_bridge_mcast *brmctx)
3727
3748
3728
3749
void br_multicast_open (struct net_bridge * br )
3729
3750
{
3730
- struct net_bridge_vlan_group * vg ;
3731
- struct net_bridge_vlan * vlan ;
3732
-
3733
3751
ASSERT_RTNL ();
3734
3752
3735
- vg = br_vlan_group (br );
3736
- if (vg ) {
3737
- list_for_each_entry (vlan , & vg -> vlan_list , vlist ) {
3738
- struct net_bridge_mcast * brmctx ;
3739
-
3740
- brmctx = & vlan -> br_mcast_ctx ;
3741
- if (br_vlan_is_brentry (vlan ) &&
3742
- !br_multicast_ctx_vlan_disabled (brmctx ))
3743
- __br_multicast_open (& vlan -> br_mcast_ctx );
3753
+ if (br_opt_get (br , BROPT_MCAST_VLAN_SNOOPING_ENABLED )) {
3754
+ struct net_bridge_vlan_group * vg ;
3755
+ struct net_bridge_vlan * vlan ;
3756
+
3757
+ vg = br_vlan_group (br );
3758
+ if (vg ) {
3759
+ list_for_each_entry (vlan , & vg -> vlan_list , vlist ) {
3760
+ struct net_bridge_mcast * brmctx ;
3761
+
3762
+ brmctx = & vlan -> br_mcast_ctx ;
3763
+ if (br_vlan_is_brentry (vlan ) &&
3764
+ !br_multicast_ctx_vlan_disabled (brmctx ))
3765
+ __br_multicast_open (& vlan -> br_mcast_ctx );
3766
+ }
3744
3767
}
3745
3768
}
3746
3769
@@ -3804,22 +3827,80 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
3804
3827
}
3805
3828
}
3806
3829
3807
- void br_multicast_stop (struct net_bridge * br )
3830
+ void br_multicast_toggle_vlan (struct net_bridge_vlan * vlan , bool on )
3831
+ {
3832
+ struct net_bridge_port * p ;
3833
+
3834
+ if (WARN_ON_ONCE (!br_vlan_is_master (vlan )))
3835
+ return ;
3836
+
3837
+ list_for_each_entry (p , & vlan -> br -> port_list , list ) {
3838
+ struct net_bridge_vlan * vport ;
3839
+
3840
+ vport = br_vlan_find (nbp_vlan_group (p ), vlan -> vid );
3841
+ if (!vport )
3842
+ continue ;
3843
+ br_multicast_toggle_one_vlan (vport , on );
3844
+ }
3845
+ }
3846
+
3847
+ int br_multicast_toggle_vlan_snooping (struct net_bridge * br , bool on ,
3848
+ struct netlink_ext_ack * extack )
3808
3849
{
3809
3850
struct net_bridge_vlan_group * vg ;
3810
3851
struct net_bridge_vlan * vlan ;
3852
+ struct net_bridge_port * p ;
3811
3853
3812
- ASSERT_RTNL ();
3854
+ if (br_opt_get (br , BROPT_MCAST_VLAN_SNOOPING_ENABLED ) == on )
3855
+ return 0 ;
3856
+
3857
+ if (on && !br_opt_get (br , BROPT_VLAN_ENABLED )) {
3858
+ NL_SET_ERR_MSG_MOD (extack , "Cannot enable multicast vlan snooping with vlan filtering disabled" );
3859
+ return - EINVAL ;
3860
+ }
3813
3861
3814
3862
vg = br_vlan_group (br );
3815
- if (vg ) {
3816
- list_for_each_entry (vlan , & vg -> vlan_list , vlist ) {
3817
- struct net_bridge_mcast * brmctx ;
3818
-
3819
- brmctx = & vlan -> br_mcast_ctx ;
3820
- if (br_vlan_is_brentry (vlan ) &&
3821
- !br_multicast_ctx_vlan_disabled (brmctx ))
3822
- __br_multicast_stop (& vlan -> br_mcast_ctx );
3863
+ if (!vg )
3864
+ return 0 ;
3865
+
3866
+ br_opt_toggle (br , BROPT_MCAST_VLAN_SNOOPING_ENABLED , on );
3867
+
3868
+ /* disable/enable non-vlan mcast contexts based on vlan snooping */
3869
+ if (on )
3870
+ __br_multicast_stop (& br -> multicast_ctx );
3871
+ else
3872
+ __br_multicast_open (& br -> multicast_ctx );
3873
+ list_for_each_entry (p , & br -> port_list , list ) {
3874
+ if (on )
3875
+ br_multicast_disable_port (p );
3876
+ else
3877
+ br_multicast_enable_port (p );
3878
+ }
3879
+
3880
+ list_for_each_entry (vlan , & vg -> vlan_list , vlist )
3881
+ br_multicast_toggle_vlan (vlan , on );
3882
+
3883
+ return 0 ;
3884
+ }
3885
+
3886
+ void br_multicast_stop (struct net_bridge * br )
3887
+ {
3888
+ ASSERT_RTNL ();
3889
+
3890
+ if (br_opt_get (br , BROPT_MCAST_VLAN_SNOOPING_ENABLED )) {
3891
+ struct net_bridge_vlan_group * vg ;
3892
+ struct net_bridge_vlan * vlan ;
3893
+
3894
+ vg = br_vlan_group (br );
3895
+ if (vg ) {
3896
+ list_for_each_entry (vlan , & vg -> vlan_list , vlist ) {
3897
+ struct net_bridge_mcast * brmctx ;
3898
+
3899
+ brmctx = & vlan -> br_mcast_ctx ;
3900
+ if (br_vlan_is_brentry (vlan ) &&
3901
+ !br_multicast_ctx_vlan_disabled (brmctx ))
3902
+ __br_multicast_stop (& vlan -> br_mcast_ctx );
3903
+ }
3823
3904
}
3824
3905
}
3825
3906
0 commit comments