@@ -2,13 +2,15 @@ package controller
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "testing"
78 "time"
89
910 "github.com/stretchr/testify/require"
1011 "go.uber.org/mock/gomock"
1112
13+ "github.com/ovn-kubernetes/libovsdb/ovsdb"
1214 corev1 "k8s.io/api/core/v1"
1315 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1416
@@ -698,3 +700,176 @@ func Test_validateSubnetVlan(t *testing.T) {
698700 require .NoError (t , err )
699701 })
700702}
703+
704+ func Test_handleMcastQuerierChange (t * testing.T ) {
705+ t .Parallel ()
706+
707+ subnetName := "test-mcast-subnet"
708+ lspName := fmt .Sprintf (util .McastQuerierName , subnetName )
709+ querierIP := "10.16.0.100"
710+ querierMAC := "00:00:00:ab:cd:ef"
711+
712+ t .Run ("enable multicast snoop successfully" , func (t * testing.T ) {
713+ fakeController := newFakeController (t )
714+ ctrl := fakeController .fakeController
715+ mockOvnClient := fakeController .mockOvnClient
716+
717+ subnet := & kubeovnv1.Subnet {
718+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
719+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : true },
720+ Status : kubeovnv1.SubnetStatus {McastQuerierIP : querierIP , McastQuerierMAC : querierMAC },
721+ }
722+
723+ mockOvnClient .EXPECT ().CreateLogicalSwitchPort (subnetName , lspName , querierIP , querierMAC , lspName , metav1 .NamespaceDefault , false , "" , "" , false , nil , "" ).Return (nil )
724+ mockOvnClient .EXPECT ().LogicalSwitchUpdateOtherConfig (subnetName , ovsdb .MutateOperationInsert , gomock .Any ()).Return (nil )
725+
726+ err := ctrl .handleMcastQuerierChange (subnet )
727+ require .NoError (t , err )
728+ })
729+
730+ t .Run ("enable multicast snoop create lsp fails" , func (t * testing.T ) {
731+ fakeController := newFakeController (t )
732+ ctrl := fakeController .fakeController
733+ mockOvnClient := fakeController .mockOvnClient
734+
735+ subnet := & kubeovnv1.Subnet {
736+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
737+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : true },
738+ Status : kubeovnv1.SubnetStatus {McastQuerierIP : querierIP , McastQuerierMAC : querierMAC },
739+ }
740+
741+ mockOvnClient .EXPECT ().CreateLogicalSwitchPort (subnetName , lspName , querierIP , querierMAC , lspName , metav1 .NamespaceDefault , false , "" , "" , false , nil , "" ).Return (errors .New ("create lsp failed" ))
742+
743+ err := ctrl .handleMcastQuerierChange (subnet )
744+ require .Error (t , err )
745+ require .Contains (t , err .Error (), "create lsp failed" )
746+ })
747+
748+ t .Run ("enable multicast snoop update other config fails" , func (t * testing.T ) {
749+ fakeController := newFakeController (t )
750+ ctrl := fakeController .fakeController
751+ mockOvnClient := fakeController .mockOvnClient
752+
753+ subnet := & kubeovnv1.Subnet {
754+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
755+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : true },
756+ Status : kubeovnv1.SubnetStatus {McastQuerierIP : querierIP , McastQuerierMAC : querierMAC },
757+ }
758+
759+ mockOvnClient .EXPECT ().CreateLogicalSwitchPort (subnetName , lspName , querierIP , querierMAC , lspName , metav1 .NamespaceDefault , false , "" , "" , false , nil , "" ).Return (nil )
760+ mockOvnClient .EXPECT ().LogicalSwitchUpdateOtherConfig (subnetName , ovsdb .MutateOperationInsert , gomock .Any ()).Return (errors .New ("update config failed" ))
761+
762+ err := ctrl .handleMcastQuerierChange (subnet )
763+ require .Error (t , err )
764+ require .Contains (t , err .Error (), "update config failed" )
765+ })
766+
767+ t .Run ("disable multicast snoop successfully" , func (t * testing.T ) {
768+ fakeController := newFakeController (t )
769+ ctrl := fakeController .fakeController
770+ mockOvnClient := fakeController .mockOvnClient
771+
772+ subnet := & kubeovnv1.Subnet {
773+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
774+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : false },
775+ }
776+
777+ lss := []ovnnb.LogicalSwitch {{
778+ Name : subnetName ,
779+ OtherConfig : map [string ]string {
780+ "mcast_snoop" : "true" ,
781+ "mcast_querier" : "true" ,
782+ "mcast_ip4_src" : querierIP ,
783+ "mcast_eth_src" : querierMAC ,
784+ },
785+ }}
786+
787+ mockOvnClient .EXPECT ().ListLogicalSwitch (false , gomock .Any ()).Return (lss , nil )
788+ mockOvnClient .EXPECT ().LogicalSwitchUpdateOtherConfig (subnetName , ovsdb .MutateOperationDelete , gomock .Any ()).Return (nil )
789+ mockOvnClient .EXPECT ().DeleteLogicalSwitchPort (lspName ).Return (nil )
790+
791+ err := ctrl .handleMcastQuerierChange (subnet )
792+ require .NoError (t , err )
793+ })
794+
795+ t .Run ("disable multicast snoop list logical switch fails" , func (t * testing.T ) {
796+ fakeController := newFakeController (t )
797+ ctrl := fakeController .fakeController
798+ mockOvnClient := fakeController .mockOvnClient
799+
800+ subnet := & kubeovnv1.Subnet {
801+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
802+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : false },
803+ }
804+
805+ mockOvnClient .EXPECT ().ListLogicalSwitch (false , gomock .Any ()).Return (nil , errors .New ("list failed" ))
806+
807+ err := ctrl .handleMcastQuerierChange (subnet )
808+ require .Error (t , err )
809+ require .Contains (t , err .Error (), "list failed" )
810+ })
811+
812+ // logical switch not found: cleanup is unnecessary, should return nil to avoid infinite requeue
813+ t .Run ("disable multicast snoop logical switch not found skips cleanup" , func (t * testing.T ) {
814+ fakeController := newFakeController (t )
815+ ctrl := fakeController .fakeController
816+ mockOvnClient := fakeController .mockOvnClient
817+
818+ subnet := & kubeovnv1.Subnet {
819+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
820+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : false },
821+ }
822+
823+ mockOvnClient .EXPECT ().ListLogicalSwitch (false , gomock .Any ()).Return ([]ovnnb.LogicalSwitch {}, nil )
824+
825+ err := ctrl .handleMcastQuerierChange (subnet )
826+ require .NoError (t , err )
827+ })
828+
829+ t .Run ("disable multicast snoop delete other config fails" , func (t * testing.T ) {
830+ fakeController := newFakeController (t )
831+ ctrl := fakeController .fakeController
832+ mockOvnClient := fakeController .mockOvnClient
833+
834+ subnet := & kubeovnv1.Subnet {
835+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
836+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : false },
837+ }
838+
839+ lss := []ovnnb.LogicalSwitch {{
840+ Name : subnetName ,
841+ OtherConfig : map [string ]string {},
842+ }}
843+
844+ mockOvnClient .EXPECT ().ListLogicalSwitch (false , gomock .Any ()).Return (lss , nil )
845+ mockOvnClient .EXPECT ().LogicalSwitchUpdateOtherConfig (subnetName , ovsdb .MutateOperationDelete , gomock .Any ()).Return (errors .New ("delete config failed" ))
846+
847+ err := ctrl .handleMcastQuerierChange (subnet )
848+ require .Error (t , err )
849+ require .Contains (t , err .Error (), "delete config failed" )
850+ })
851+
852+ t .Run ("disable multicast snoop delete lsp fails" , func (t * testing.T ) {
853+ fakeController := newFakeController (t )
854+ ctrl := fakeController .fakeController
855+ mockOvnClient := fakeController .mockOvnClient
856+
857+ subnet := & kubeovnv1.Subnet {
858+ ObjectMeta : metav1.ObjectMeta {Name : subnetName },
859+ Spec : kubeovnv1.SubnetSpec {EnableMulticastSnoop : false },
860+ }
861+
862+ lss := []ovnnb.LogicalSwitch {{
863+ Name : subnetName ,
864+ OtherConfig : map [string ]string {},
865+ }}
866+
867+ mockOvnClient .EXPECT ().ListLogicalSwitch (false , gomock .Any ()).Return (lss , nil )
868+ mockOvnClient .EXPECT ().LogicalSwitchUpdateOtherConfig (subnetName , ovsdb .MutateOperationDelete , gomock .Any ()).Return (nil )
869+ mockOvnClient .EXPECT ().DeleteLogicalSwitchPort (lspName ).Return (errors .New ("delete lsp failed" ))
870+
871+ err := ctrl .handleMcastQuerierChange (subnet )
872+ require .Error (t , err )
873+ require .Contains (t , err .Error (), "delete lsp failed" )
874+ })
875+ }
0 commit comments