@@ -32,6 +32,7 @@ import (
32
32
"time"
33
33
34
34
current "github.com/containernetworking/cni/pkg/types/100"
35
+ "github.com/google/uuid"
35
36
netdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
36
37
netdefclientfake "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/fake"
37
38
"github.com/stretchr/testify/assert"
@@ -43,12 +44,15 @@ import (
43
44
"k8s.io/client-go/kubernetes/fake"
44
45
"k8s.io/client-go/util/workqueue"
45
46
47
+ "antrea.io/antrea/pkg/agent/cniserver"
46
48
"antrea.io/antrea/pkg/agent/cniserver/ipam"
47
49
cnitypes "antrea.io/antrea/pkg/agent/cniserver/types"
48
50
"antrea.io/antrea/pkg/agent/interfacestore"
49
51
podwatchtesting "antrea.io/antrea/pkg/agent/secondarynetwork/podwatch/testing"
50
52
"antrea.io/antrea/pkg/agent/types"
51
53
crdv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1"
54
+ "antrea.io/antrea/pkg/ovs/ovsconfig"
55
+ ovsconfigtest "antrea.io/antrea/pkg/ovs/ovsconfig/testing"
52
56
)
53
57
54
58
const (
@@ -213,14 +217,17 @@ func TestPodControllerRun(t *testing.T) {
213
217
ctrl := gomock .NewController (t )
214
218
client := fake .NewSimpleClientset ()
215
219
netdefclient := netdefclientfake .NewSimpleClientset ().K8sCniCncfIoV1 ()
220
+ mockOVSBridgeClient := ovsconfigtest .NewMockOVSBridgeClient (ctrl )
221
+ mockOVSBridgeClient .EXPECT ().GetPortList ().Return (nil , nil ).AnyTimes ()
222
+ primaryInterfaceStore := interfacestore .NewInterfaceStore ()
216
223
informerFactory := informers .NewSharedInformerFactory (client , resyncPeriod )
217
224
interfaceConfigurator := podwatchtesting .NewMockInterfaceConfigurator (ctrl )
218
225
mockIPAM := podwatchtesting .NewMockIPAMAllocator (ctrl )
219
226
podController , _ := NewPodController (
220
227
client ,
221
228
netdefclient ,
222
229
informerFactory .Core ().V1 ().Pods ().Informer (),
223
- nil , nil )
230
+ nil , primaryInterfaceStore , mockOVSBridgeClient )
224
231
podController .interfaceConfigurator = interfaceConfigurator
225
232
podController .ipamAllocator = mockIPAM
226
233
cniCache := & podController .cniCache
@@ -968,7 +975,7 @@ func TestPodControllerAddPod(t *testing.T) {
968
975
969
976
t .Run ("updating deviceID cache per Pod" , func (t * testing.T ) {
970
977
ctrl := gomock .NewController (t )
971
- podController , _ , _ := testPodController (ctrl )
978
+ podController , _ , _ , _ := testPodController (ctrl )
972
979
_ , err := podController .assignUnusedSriovVFDeviceID (podName , testNamespace , sriovResourceName1 , interfaceName )
973
980
_ , exists := podController .vfDeviceIDUsageMap .Load (podKey )
974
981
assert .True (t , exists )
@@ -984,16 +991,18 @@ func TestPodControllerAddPod(t *testing.T) {
984
991
985
992
func testPodController (ctrl * gomock.Controller ) (
986
993
* PodController , * podwatchtesting.MockIPAMAllocator ,
987
- * podwatchtesting.MockInterfaceConfigurator ) {
994
+ * podwatchtesting.MockInterfaceConfigurator , * ovsconfigtest. MockOVSBridgeClient ) {
988
995
client := fake .NewSimpleClientset ()
989
996
netdefclient := netdefclientfake .NewSimpleClientset ().K8sCniCncfIoV1 ()
990
997
informerFactory := informers .NewSharedInformerFactory (client , resyncPeriod )
991
998
interfaceConfigurator := podwatchtesting .NewMockInterfaceConfigurator (ctrl )
992
999
mockIPAM := podwatchtesting .NewMockIPAMAllocator (ctrl )
1000
+ mockOVSBridgeClient := ovsconfigtest .NewMockOVSBridgeClient (ctrl )
993
1001
994
1002
// PodController without event handlers.
995
1003
return & PodController {
996
1004
kubeClient : client ,
1005
+ ovsBridgeClient : mockOVSBridgeClient ,
997
1006
netAttachDefClient : netdefclient ,
998
1007
queue : workqueue .NewTypedRateLimitingQueueWithConfig (
999
1008
workqueue .NewTypedItemExponentialFailureRateLimiter [string ](minRetryDelay , maxRetryDelay ),
@@ -1005,18 +1014,140 @@ func testPodController(ctrl *gomock.Controller) (
1005
1014
interfaceConfigurator : interfaceConfigurator ,
1006
1015
ipamAllocator : mockIPAM ,
1007
1016
interfaceStore : interfacestore .NewInterfaceStore (),
1008
- }, mockIPAM , interfaceConfigurator
1017
+ }, mockIPAM , interfaceConfigurator , mockOVSBridgeClient
1009
1018
}
1010
1019
1011
1020
// Create a test PodController and start informerFactory.
1012
1021
func testPodControllerStart (ctrl * gomock.Controller ) (
1013
1022
* PodController , * podwatchtesting.MockIPAMAllocator ,
1014
1023
* podwatchtesting.MockInterfaceConfigurator ) {
1015
- podController , mockIPAM , interfaceConfigurator := testPodController (ctrl )
1024
+ podController , mockIPAM , interfaceConfigurator , _ := testPodController (ctrl )
1016
1025
informerFactory := informers .NewSharedInformerFactory (podController .kubeClient , resyncPeriod )
1017
1026
podController .podInformer = informerFactory .Core ().V1 ().Pods ().Informer ()
1018
1027
stopCh := make (chan struct {})
1019
1028
informerFactory .Start (stopCh )
1020
1029
informerFactory .WaitForCacheSync (stopCh )
1021
1030
return podController , mockIPAM , interfaceConfigurator
1022
1031
}
1032
+
1033
+ func convertExternalIDMap (in map [string ]interface {}) map [string ]string {
1034
+ out := make (map [string ]string , len (in ))
1035
+ for k , v := range in {
1036
+ out [k ] = v .(string )
1037
+ }
1038
+ return out
1039
+ }
1040
+
1041
+ func createTestInterfaces () (map [string ]string , []ovsconfig.OVSPortData , []* interfacestore.InterfaceConfig ) {
1042
+ uuid1 := uuid .New ().String ()
1043
+ uuid2 := uuid .New ().String ()
1044
+ uuid3 := uuid .New ().String ()
1045
+ uuid4 := uuid .New ().String ()
1046
+
1047
+ p1MAC , p1IP := "11:22:33:44:55:66" , "192.168.1.10"
1048
+ p2MAC , p2IP := "11:22:33:44:55:77" , "192.168.1.11"
1049
+
1050
+ p1NetMAC , _ := net .ParseMAC (p1MAC )
1051
+ p1NetIP := net .ParseIP (p1IP )
1052
+ p2NetMAC , _ := net .ParseMAC (p2MAC )
1053
+ p2NetIP := net .ParseIP (p2IP )
1054
+
1055
+ // Create InterfaceConfig objects directly
1056
+ containerConfig1 := interfacestore .NewContainerInterface ("p1" , uuid1 , "Pod1" , "nsA" , "eth0" , p1NetMAC , []net.IP {p1NetIP }, 100 )
1057
+ containerConfig2 := interfacestore .NewContainerInterface ("p2" , uuid2 , "Pod2" , "nsA" , "eth0" , p2NetMAC , []net.IP {p2NetIP }, 100 )
1058
+ containerConfig3 := interfacestore .NewContainerInterface ("p3" , uuid3 , "Pod3" , "nsA" , "eth0" , p2NetMAC , []net.IP {p2NetIP }, 100 )
1059
+
1060
+ ovsPort1 := ovsconfig.OVSPortData {
1061
+ UUID : uuid1 , Name : "p1" , OFPort : 11 ,
1062
+ ExternalIDs : convertExternalIDMap (cniserver .BuildOVSPortExternalIDs (
1063
+ containerConfig1 ))}
1064
+
1065
+ ovsPort2 := ovsconfig.OVSPortData {
1066
+ UUID : uuid2 , Name : "p2" , OFPort : 12 ,
1067
+ ExternalIDs : convertExternalIDMap (cniserver .BuildOVSPortExternalIDs (
1068
+ containerConfig2 ))}
1069
+
1070
+ ovsPort3 := ovsconfig.OVSPortData {
1071
+ UUID : uuid3 , Name : "p3" , OFPort : - 1 ,
1072
+ ExternalIDs : convertExternalIDMap (cniserver .BuildOVSPortExternalIDs (
1073
+ containerConfig3 ))}
1074
+
1075
+ ovsPort4 := ovsconfig.OVSPortData {
1076
+ UUID : uuid4 ,
1077
+ Name : "unknownIface" ,
1078
+ OFPort : 20 ,
1079
+ ExternalIDs : map [string ]string {
1080
+ "unknownKey" : "unknownValue" }}
1081
+
1082
+ return map [string ]string {"uuid1" : uuid1 , "uuid2" : uuid2 , "uuid3" : uuid3 , "uuid4" : uuid4 }, []ovsconfig.OVSPortData {ovsPort1 , ovsPort2 , ovsPort3 , ovsPort4 }, []* interfacestore.InterfaceConfig {containerConfig1 , containerConfig2 , containerConfig3 }
1083
+ }
1084
+
1085
+ func TestInitializeSecondaryInterfaceStore (t * testing.T ) {
1086
+ ctrl := gomock .NewController (t )
1087
+ pc , _ , _ , mockOVSBridgeClient := testPodController (ctrl )
1088
+ uuids , ovsPorts , _ := createTestInterfaces ()
1089
+ mockOVSBridgeClient .EXPECT ().GetPortList ().Return (ovsPorts , nil )
1090
+
1091
+ err := pc .initializeSecondaryInterfaceStore ()
1092
+ require .NoError (t , err , "OVS ports list successfully" )
1093
+
1094
+ // Validate stored interfaces
1095
+ require .Equal (t , 3 , pc .interfaceStore .Len (), "Only valid interfaces should be stored" )
1096
+
1097
+ _ , found1 := pc .interfaceStore .GetContainerInterface (uuids ["uuid1" ])
1098
+ assert .True (t , found1 , "Interface 1 should be stored" )
1099
+
1100
+ _ , found2 := pc .interfaceStore .GetContainerInterface (uuids ["uuid2" ])
1101
+ assert .True (t , found2 , "Interface 2 should be stored" )
1102
+
1103
+ _ , found3 := pc .interfaceStore .GetContainerInterface (uuids ["uuid3" ])
1104
+ assert .True (t , found3 , "Interface 3 should be stored" )
1105
+
1106
+ _ , found4 := pc .interfaceStore .GetContainerInterface (uuids ["uuid4" ])
1107
+ assert .False (t , found4 , "Unknown interface type should not be stored" )
1108
+ }
1109
+
1110
+ func TestReconcileSecondaryInterfaces (t * testing.T ) {
1111
+ ctrl := gomock .NewController (t )
1112
+ pc , mockIPAM , interfaceConfigurator , _ := testPodController (ctrl )
1113
+ primaryStore := interfacestore .NewInterfaceStore ()
1114
+
1115
+ _ , _ , containerConfigs := createTestInterfaces ()
1116
+
1117
+ // Ensure OVSPortConfig is initialized to avoid nil pointer dereference issues
1118
+ // when accessing or modifying OFPort.
1119
+ containerConfigs [0 ].OVSPortConfig = & interfacestore.OVSPortConfig {}
1120
+ containerConfigs [0 ].OFPort = 11
1121
+ containerConfigs [1 ].OVSPortConfig = & interfacestore.OVSPortConfig {}
1122
+ containerConfigs [1 ].OFPort = 12
1123
+ containerConfigs [2 ].OVSPortConfig = & interfacestore.OVSPortConfig {}
1124
+ containerConfigs [2 ].OFPort = - 1
1125
+
1126
+ // Add interfaces to primary store
1127
+ primaryStore .AddInterface (containerConfigs [0 ])
1128
+ primaryStore .AddInterface (containerConfigs [1 ])
1129
+
1130
+ // Add interfaces to controller secondaryInterfaceStore
1131
+ pc .interfaceStore .AddInterface (containerConfigs [0 ])
1132
+ pc .interfaceStore .AddInterface (containerConfigs [1 ])
1133
+ // Case when OFPort == -1
1134
+ pc .interfaceStore .AddInterface (containerConfigs [2 ])
1135
+
1136
+ interfaceConfigurator .EXPECT ().DeleteVLANSecondaryInterface (gomock .Any ()).Return (nil ).Times (1 )
1137
+ mockIPAM .EXPECT ().SecondaryNetworkRelease (gomock .Any ()).Return (nil ).Times (1 )
1138
+
1139
+ err := pc .reconcileSecondaryInterfaces (primaryStore )
1140
+
1141
+ require .NoError (t , err )
1142
+
1143
+ // Check CNI Cache
1144
+ _ , foundPod1 := pc .cniCache .Load ("nsA/Pod1" )
1145
+ assert .True (t , foundPod1 , "CNI Cache should contain nsA/Pod1" )
1146
+
1147
+ _ , foundPod2 := pc .cniCache .Load ("nsA/Pod2" )
1148
+ assert .True (t , foundPod2 , "CNI Cache should contain nsA/Pod2" )
1149
+
1150
+ // Ensure stale interfaces are removed
1151
+ _ , foundPod3 := pc .cniCache .Load ("nsA/Pod3" )
1152
+ assert .False (t , foundPod3 , "Stale interface should have been removed" )
1153
+ }
0 commit comments