@@ -77,6 +77,222 @@ def test_PfcWdAclCreationDeletion(self, dvs, dvs_acl, testlog):
77
77
78
78
finally :
79
79
dvs_acl .remove_acl_table (PFCWD_TABLE_NAME )
80
+
81
+
82
+ class TestPfcwdFunc (object ):
83
+ @pytest .fixture
84
+ def setup_teardown_test (self , dvs ):
85
+ self .get_db_handle (dvs )
86
+
87
+ self .test_ports = ["Ethernet0" ]
88
+
89
+ self .setup_test (dvs )
90
+ self .get_port_oids ()
91
+ self .get_queue_oids ()
92
+
93
+ yield
94
+
95
+ self .teardown_test (dvs )
96
+
97
+ def setup_test (self , dvs ):
98
+ # get original cable len for test ports
99
+ fvs = self .config_db .get_entry ("CABLE_LENGTH" , "AZURE" )
100
+ self .orig_cable_len = dict ()
101
+ for port in self .test_ports :
102
+ self .orig_cable_len [port ] = fvs [port ]
103
+ # set cable len to non zero value. if port is down, default cable len is 0
104
+ self .set_cable_len (port , "5m" )
105
+ # startup port
106
+ dvs .runcmd ("config interface startup {}" .format (port ))
107
+
108
+ # enable pfcwd
109
+ self .set_flex_counter_status ("PFCWD" , "enable" )
110
+ # enable queue so that queue oids are generated
111
+ self .set_flex_counter_status ("QUEUE" , "enable" )
112
+
113
+ def teardown_test (self , dvs ):
114
+ # disable pfcwd
115
+ self .set_flex_counter_status ("PFCWD" , "disable" )
116
+ # disable queue
117
+ self .set_flex_counter_status ("QUEUE" , "disable" )
118
+
119
+ for port in self .test_ports :
120
+ if self .orig_cable_len :
121
+ self .set_cable_len (port , self .orig_cable_len [port ])
122
+ # shutdown port
123
+ dvs .runcmd ("config interface shutdown {}" .format (port ))
124
+
125
+ def get_db_handle (self , dvs ):
126
+ self .app_db = dvs .get_app_db ()
127
+ self .asic_db = dvs .get_asic_db ()
128
+ self .config_db = dvs .get_config_db ()
129
+ self .counters_db = dvs .get_counters_db ()
130
+
131
+ def set_flex_counter_status (self , key , state ):
132
+ fvs = {'FLEX_COUNTER_STATUS' : state }
133
+ self .config_db .update_entry ("FLEX_COUNTER_TABLE" , key , fvs )
134
+ time .sleep (1 )
135
+
136
+ def get_queue_oids (self ):
137
+ self .queue_oids = self .counters_db .get_entry ("COUNTERS_QUEUE_NAME_MAP" , "" )
138
+
139
+ def get_port_oids (self ):
140
+ self .port_oids = self .counters_db .get_entry ("COUNTERS_PORT_NAME_MAP" , "" )
141
+
142
+ def _get_bitmask (self , queues ):
143
+ mask = 0
144
+ if queues is not None :
145
+ for queue in queues :
146
+ mask = mask | 1 << queue
147
+
148
+ return str (mask )
149
+
150
+ def set_ports_pfc (self , status = 'enable' , pfc_queues = [3 ,4 ]):
151
+ for port in self .test_ports :
152
+ if 'enable' in status :
153
+ fvs = {'pfc_enable' : "," .join ([str (q ) for q in pfc_queues ])}
154
+ self .config_db .create_entry ("PORT_QOS_MAP" , port , fvs )
155
+ else :
156
+ self .config_db .delete_entry ("PORT_QOS_MAP" , port )
157
+
158
+ def set_cable_len (self , port_name , cable_len ):
159
+ fvs = {port_name : cable_len }
160
+ self .config_db .update_entry ("CABLE_LEN" , "AZURE" , fvs )
161
+
162
+ def start_pfcwd_on_ports (self , poll_interval = "200" , detection_time = "200" , restoration_time = "200" , action = "drop" ):
163
+ pfcwd_info = {"POLL_INTERVAL" : poll_interval }
164
+ self .config_db .update_entry ("PFC_WD" , "GLOBAL" , pfcwd_info )
165
+
166
+ pfcwd_info = {"action" : action ,
167
+ "detection_time" : detection_time ,
168
+ "restoration_time" : restoration_time
169
+ }
170
+ for port in self .test_ports :
171
+ self .config_db .update_entry ("PFC_WD" , port , pfcwd_info )
172
+
173
+ def stop_pfcwd_on_ports (self ):
174
+ for port in self .test_ports :
175
+ self .config_db .delete_entry ("PFC_WD" , port )
176
+
177
+ def verify_ports_pfc (self , queues = None ):
178
+ mask = self ._get_bitmask (queues )
179
+ fvs = {"SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL" : mask }
180
+ for port in self .test_ports :
181
+ self .asic_db .wait_for_field_match ("ASIC_STATE:SAI_OBJECT_TYPE_PORT" , self .port_oids [port ], fvs )
182
+
183
+ def verify_pfcwd_state (self , queues , state = "stormed" ):
184
+ fvs = {"PFC_WD_STATUS" : state }
185
+ for port in self .test_ports :
186
+ for queue in queues :
187
+ queue_name = port + ":" + str (queue )
188
+ self .counters_db .wait_for_field_match ("COUNTERS" , self .queue_oids [queue_name ], fvs )
189
+
190
+ def verify_pfcwd_counters (self , queues , restore = "0" ):
191
+ fvs = {"PFC_WD_QUEUE_STATS_DEADLOCK_DETECTED" : "1" ,
192
+ "PFC_WD_QUEUE_STATS_DEADLOCK_RESTORED" : restore
193
+ }
194
+ for port in self .test_ports :
195
+ for queue in queues :
196
+ queue_name = port + ":" + str (queue )
197
+ self .counters_db .wait_for_field_match ("COUNTERS" , self .queue_oids [queue_name ], fvs )
198
+
199
+ def reset_pfcwd_counters (self , queues ):
200
+ fvs = {"PFC_WD_QUEUE_STATS_DEADLOCK_DETECTED" : "0" ,
201
+ "PFC_WD_QUEUE_STATS_DEADLOCK_RESTORED" : "0"
202
+ }
203
+ for port in self .test_ports :
204
+ for queue in queues :
205
+ queue_name = port + ":" + str (queue )
206
+ self .counters_db .update_entry ("COUNTERS" , self .queue_oids [queue_name ], fvs )
207
+
208
+ def set_storm_state (self , queues , state = "enabled" ):
209
+ fvs = {"DEBUG_STORM" : state }
210
+ for port in self .test_ports :
211
+ for queue in queues :
212
+ queue_name = port + ":" + str (queue )
213
+ self .counters_db .update_entry ("COUNTERS" , self .queue_oids [queue_name ], fvs )
214
+
215
+ def test_pfcwd_single_queue (self , dvs , setup_teardown_test ):
216
+ try :
217
+ # enable PFC on queues
218
+ test_queues = [3 , 4 ]
219
+ self .set_ports_pfc (pfc_queues = test_queues )
220
+
221
+ # verify in asic db
222
+ self .verify_ports_pfc (test_queues )
223
+
224
+ # start pfcwd
225
+ self .start_pfcwd_on_ports ()
226
+
227
+ # start pfc storm
228
+ storm_queue = [3 ]
229
+ self .set_storm_state (storm_queue )
230
+
231
+ # verify pfcwd is triggered
232
+ self .verify_pfcwd_state (storm_queue )
233
+
234
+ # verify pfcwd counters
235
+ self .verify_pfcwd_counters (storm_queue )
236
+
237
+ # verify if queue is disabled
238
+ self .verify_ports_pfc (queues = [4 ])
239
+
240
+ # stop storm
241
+ self .set_storm_state (storm_queue , state = "disabled" )
242
+
243
+ # verify pfcwd state is restored
244
+ self .verify_pfcwd_state (storm_queue , state = "operational" )
245
+
246
+ # verify pfcwd counters
247
+ self .verify_pfcwd_counters (storm_queue , restore = "1" )
248
+
249
+ # verify if queue is enabled
250
+ self .verify_ports_pfc (test_queues )
251
+
252
+ finally :
253
+ self .reset_pfcwd_counters (storm_queue )
254
+ self .stop_pfcwd_on_ports ()
255
+
256
+ def test_pfcwd_multi_queue (self , dvs , setup_teardown_test ):
257
+ try :
258
+ # enable PFC on queues
259
+ test_queues = [3 , 4 ]
260
+ self .set_ports_pfc (pfc_queues = test_queues )
261
+
262
+ # verify in asic db
263
+ self .verify_ports_pfc (test_queues )
264
+
265
+ # start pfcwd
266
+ self .start_pfcwd_on_ports ()
267
+
268
+ # start pfc storm
269
+ self .set_storm_state (test_queues )
270
+
271
+ # verify pfcwd is triggered
272
+ self .verify_pfcwd_state (test_queues )
273
+
274
+ # verify pfcwd counters
275
+ self .verify_pfcwd_counters (test_queues )
276
+
277
+ # verify if queue is disabled. Expected mask is 0
278
+ self .verify_ports_pfc ()
279
+
280
+ # stop storm
281
+ self .set_storm_state (test_queues , state = "disabled" )
282
+
283
+ # verify pfcwd state is restored
284
+ self .verify_pfcwd_state (test_queues , state = "operational" )
285
+
286
+ # verify pfcwd counters
287
+ self .verify_pfcwd_counters (test_queues , restore = "1" )
288
+
289
+ # verify if queue is enabled
290
+ self .verify_ports_pfc (test_queues )
291
+
292
+ finally :
293
+ self .reset_pfcwd_counters (test_queues )
294
+ self .stop_pfcwd_on_ports ()
295
+
80
296
#
81
297
# Add Dummy always-pass test at end as workaroud
82
298
# for issue when Flaky fail on final test it invokes module tear-down before retrying
0 commit comments