blob: 915729c642b7546fb40d4e714ff25a531fc9a4d4 [file] [log] [blame]
Rich Lane284dc4d2014-01-06 15:24:07 -08001# Distributed under the OpenFlow Software License (see LICENSE)
2# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
3"""
4BSN gentable extension test cases
5"""
6
7import logging
Rich Lane232d2ab2014-01-07 12:23:16 -08008import math
Rich Lane14e4c142014-01-09 10:31:08 -08009import random
Rich Lane284dc4d2014-01-06 15:24:07 -080010
11from oftest import config
12import oftest.base_tests as base_tests
13import ofp
14
15from oftest.testutils import *
16
17# Hardcoded in the switch to ease testing
18TABLE_ID = 0
19
Rich Laneb2c5bf62014-01-06 17:18:40 -080020def tlv_dict(tlvs):
21 d = {}
22 for tlv in tlvs:
23 d[tlv.__class__] = tlv.value
24 return d
25
Rich Lane64c4e602014-01-07 11:27:06 -080026def make_checksum(hi, lo):
27 """
28 Place 'hi' in the upper 8 bits and 'lo' in the lower bits.
29 """
30 return ((hi & 0xff) << 120) | lo
31
32assert make_checksum(0xab, 0xcd) == 0xab0000000000000000000000000000cd
33
Rich Lane284dc4d2014-01-06 15:24:07 -080034class BaseGenTableTest(base_tests.SimpleProtocol):
35 def setUp(self):
36 base_tests.SimpleProtocol.setUp(self)
Rich Laneb2c5bf62014-01-06 17:18:40 -080037 self.do_clear()
Rich Lane284dc4d2014-01-06 15:24:07 -080038
39 def tearDown(self):
Rich Laneb2c5bf62014-01-06 17:18:40 -080040 self.do_clear()
Rich Lane284dc4d2014-01-06 15:24:07 -080041 base_tests.SimpleProtocol.tearDown(self)
42
Rich Laneb2c5bf62014-01-06 17:18:40 -080043 def do_clear(self, checksum=0, checksum_mask=0):
44 request = ofp.message.bsn_gentable_clear_request(
45 table_id=TABLE_ID,
Rich Lane20f6b592014-01-08 15:17:50 -080046 checksum=checksum,
47 checksum_mask=checksum_mask)
Rich Lane284dc4d2014-01-06 15:24:07 -080048 response, _ = self.controller.transact(request)
49 self.assertIsInstance(response, ofp.message.bsn_gentable_clear_reply)
Rich Lane20f6b592014-01-08 15:17:50 -080050 return response.deleted_count, response.error_count
Rich Lane284dc4d2014-01-06 15:24:07 -080051
Rich Laneb2c5bf62014-01-06 17:18:40 -080052 def do_add(self, vlan_vid, ipv4, mac, idle_notification=False, checksum=0):
Rich Lane284dc4d2014-01-06 15:24:07 -080053 msg = ofp.message.bsn_gentable_entry_add(
54 table_id=TABLE_ID,
55 key=[
56 ofp.bsn_tlv.vlan_vid(vlan_vid),
57 ofp.bsn_tlv.ipv4(ipv4)],
58 value=[
59 ofp.bsn_tlv.mac(mac)],
Rich Laneb2c5bf62014-01-06 17:18:40 -080060 checksum=checksum)
Rich Lane284dc4d2014-01-06 15:24:07 -080061 if idle_notification:
62 msg.value.append(ofp.bsn_tlv.idle_notification())
63 self.controller.message_send(msg)
64
65 def do_delete(self, vlan_vid, ipv4):
66 msg = ofp.message.bsn_gentable_entry_delete(
67 table_id=TABLE_ID,
68 key=[
69 ofp.bsn_tlv.vlan_vid(vlan_vid),
70 ofp.bsn_tlv.ipv4(ipv4)])
71 self.controller.message_send(msg)
72
Rich Laneb2c5bf62014-01-06 17:18:40 -080073 def do_entry_stats(self, checksum=0, checksum_mask=0):
74 request = ofp.message.bsn_gentable_entry_stats_request(
75 table_id=TABLE_ID,
76 checksum=checksum,
77 checksum_mask=checksum_mask)
78 return get_stats(self, request)
79
80 def do_entry_desc_stats(self, checksum=0, checksum_mask=0):
81 request = ofp.message.bsn_gentable_entry_desc_stats_request(
82 table_id=TABLE_ID,
83 checksum=checksum,
84 checksum_mask=checksum_mask)
85 return get_stats(self, request)
86
Rich Lane4e691ad2014-01-06 17:45:20 -080087 def do_table_desc_stats(self):
88 request = ofp.message.bsn_gentable_desc_stats_request()
89 return get_stats(self, request)
90
Rich Lanea8f56672014-01-06 17:50:39 -080091 def do_table_stats(self):
92 request = ofp.message.bsn_gentable_stats_request()
93 return get_stats(self, request)
94
Rich Lane64c4e602014-01-07 11:27:06 -080095 def do_test_table_stats(self):
96 entries = self.do_table_stats()
97 for entry in entries:
98 if entry.table_id == TABLE_ID:
99 return entry
100 raise AssertionError("did not find test table")
101
Rich Lane232d2ab2014-01-07 12:23:16 -0800102 def do_bucket_stats(self):
103 request = ofp.message.bsn_gentable_bucket_stats_request(table_id=TABLE_ID)
104 return get_stats(self, request)
105
Rich Lane78bd3772014-01-08 11:51:13 -0800106 def do_set_buckets_size(self, buckets_size):
107 msg = ofp.message.bsn_gentable_set_buckets_size(
108 table_id=TABLE_ID,
109 buckets_size=buckets_size)
110 self.controller.message_send(msg)
111
Rich Lane284dc4d2014-01-06 15:24:07 -0800112class ClearAll(BaseGenTableTest):
113 """
114 Test clearing entire table
115 """
116 def runTest(self):
117 # Add a few entries
118 for i in range(0, 3):
119 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i))
120
121 do_barrier(self.controller)
122 verify_no_errors(self.controller)
123
124 # Delete all entries
Rich Lane20f6b592014-01-08 15:17:50 -0800125 deleted, errors = self.do_clear(checksum=0, checksum_mask=0)
126 self.assertEquals(deleted, 3)
127 self.assertEquals(errors, 0)
128
129class ClearMasked(BaseGenTableTest):
130 """
131 Test clearing with a checksum mask
132 """
133 def runTest(self):
134 # Add 4 entries to each checksum bucket
135 for i in range(0, 256):
136 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
137 checksum=make_checksum(i, i*31))
138
139 do_barrier(self.controller)
140 verify_no_errors(self.controller)
141
142 # Delete bucket 0
143 deleted, errors = self.do_clear(make_checksum(0, 0), make_checksum(0xFC, 0))
144 self.assertEquals(deleted, 4)
145 self.assertEquals(errors, 0)
146
147 # Delete buckets 0 (already cleared), 1, 2, 3
148 deleted, errors = self.do_clear(make_checksum(0, 0), make_checksum(0xF0, 0))
149 self.assertEquals(deleted, 12)
150 self.assertEquals(errors, 0)
151
152 # Delete second half of bucket 4
153 deleted, errors = self.do_clear(make_checksum(0x10, 0), make_checksum(0xFE, 0))
154 self.assertEquals(deleted, 2)
155 self.assertEquals(errors, 0)
Rich Lane284dc4d2014-01-06 15:24:07 -0800156
157class AddDelete(BaseGenTableTest):
158 """
159 Test adding and deleting entries
160 """
161 def runTest(self):
162 # Add a few entries
163 for i in range(0, 3):
164 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i))
165
166 do_barrier(self.controller)
167 verify_no_errors(self.controller)
168
169 # Delete each entry
170 for i in range(0, 3):
171 self.do_delete(vlan_vid=i, ipv4=0x12345678)
172
173 do_barrier(self.controller)
174 verify_no_errors(self.controller)
175
176 # Clear table, but expect it to have already been empty
177 request = ofp.message.bsn_gentable_clear_request(table_id=TABLE_ID)
178 response, _ = self.controller.transact(request)
179 self.assertIsInstance(response, ofp.message.bsn_gentable_clear_reply)
180 self.assertEquals(response.error_count, 0)
181 self.assertEquals(response.deleted_count, 0)
Rich Laneb2c5bf62014-01-06 17:18:40 -0800182
183class EntryStats(BaseGenTableTest):
184 """
185 Test retrieving entry stats
186 """
187 def runTest(self):
188 # Add a few entries
189 for i in range(0, 3):
190 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i))
191
192 do_barrier(self.controller)
193 verify_no_errors(self.controller)
194
195 entries = self.do_entry_stats()
196 seen = set()
197 for entry in entries:
198 logging.debug(entry.show())
199 key = tlv_dict(entry.key)
200 stats = tlv_dict(entry.stats)
201 self.assertIn(ofp.bsn_tlv.vlan_vid, key)
202 self.assertIn(ofp.bsn_tlv.ipv4, key)
203 self.assertIn(ofp.bsn_tlv.rx_packets, stats)
204 self.assertIn(ofp.bsn_tlv.tx_packets, stats)
205 vlan_vid = key[ofp.bsn_tlv.vlan_vid]
206 seen.add(vlan_vid)
207 self.assertEqual(key[ofp.bsn_tlv.ipv4], 0x12345678)
208 self.assertEqual(stats[ofp.bsn_tlv.rx_packets], 100 * vlan_vid)
209 self.assertEqual(stats[ofp.bsn_tlv.tx_packets], 101 * vlan_vid)
210
211 self.assertEquals(seen, set([0, 1, 2]))
212
Rich Lane790cc202014-01-08 14:54:25 -0800213class EntryStatsMasked(BaseGenTableTest):
214 """
215 Test retrieving entry stats with a checksum mask
216 """
217 def runTest(self):
218 def get_range(checksum, checksum_mask):
219 entries = self.do_entry_stats(checksum, checksum_mask)
220 vlan_vids = []
221 for entry in entries:
222 key = tlv_dict(entry.key)
223 vlan_vids.append(key[ofp.bsn_tlv.vlan_vid])
224 return sorted(vlan_vids)
225
226 # Add 4 entries to each checksum bucket
227 for i in range(0, 256):
228 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
229 checksum=make_checksum(i, i))
230
231 do_barrier(self.controller)
232 verify_no_errors(self.controller)
233
234 # Check first bucket
235 self.assertEquals(get_range(make_checksum(0, 0), make_checksum(0xFC, 0)),
236 [0, 1, 2, 3])
237
238 # Check last bucket
239 self.assertEquals(get_range(make_checksum(0xFC, 0), make_checksum(0xFC, 0)),
240 [252, 253, 254, 255])
241
242 # Check first half of first bucket
243 self.assertEquals(get_range(make_checksum(0x00, 0), make_checksum(0xFE, 0)),
244 [0, 1])
245
246 # Check second half of first bucket
247 self.assertEquals(get_range(make_checksum(0x02, 0), make_checksum(0xFE, 0)),
248 [2, 3])
249
250 # Check first half of last bucket
251 self.assertEquals(get_range(make_checksum(0xFC, 0), make_checksum(0xFE, 0)),
252 [252, 253])
253
254 # Check second half of last bucket
255 self.assertEquals(get_range(make_checksum(0xFE, 0), make_checksum(0xFE, 0)),
256 [254, 255])
257
258 # Check first two buckets
259 self.assertEquals(get_range(make_checksum(0, 0), make_checksum(0xF8, 0)),
260 [0, 1, 2, 3, 4, 5, 6, 7])
261
262 # Check last two buckets
263 self.assertEquals(get_range(make_checksum(0xF8, 0), make_checksum(0xF8, 0)),
264 [248, 249, 250, 251, 252, 253, 254, 255])
265
266 # Check matching on low bits
267 self.assertEquals(get_range(make_checksum(0x00, 0x00), ~1), [0])
268 self.assertEquals(get_range(make_checksum(0x01, 0x00), ~1), [1])
269 self.assertEquals(get_range(make_checksum(0x01, 0x02), ~1), [])
270
Rich Lane464960b2014-01-08 17:30:07 -0800271class EntryStatsFragmented(BaseGenTableTest):
272 """
273 Test retrieving entry stats in mutiple replies
274 """
275 def runTest(self):
276 # Add a bunch of entries
277 # Enough for 3 stats replies
Rich Lane87f54bd2014-01-08 17:53:14 -0800278 for i in range(0, 4095):
Rich Lane464960b2014-01-08 17:30:07 -0800279 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
280
281 do_barrier(self.controller)
282 verify_no_errors(self.controller)
283
284 entries = self.do_entry_stats()
285 seen = set()
286 for entry in entries:
287 key = tlv_dict(entry.key)
288 vlan_vid = key[ofp.bsn_tlv.vlan_vid]
289 self.assertNotIn(vlan_vid, seen)
290 seen.add(vlan_vid)
291
Rich Lane87f54bd2014-01-08 17:53:14 -0800292 self.assertEquals(seen, set(range(0, 4095)))
Rich Lane790cc202014-01-08 14:54:25 -0800293
Rich Laneb2c5bf62014-01-06 17:18:40 -0800294class EntryDescStats(BaseGenTableTest):
295 """
296 Test retrieving entry desc stats
297 """
298 def runTest(self):
299 # Add a few entries
300 for i in range(0, 3):
301 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
302 checksum=0xfedcba9876543210fedcba9876543210 + i)
303
304 do_barrier(self.controller)
305 verify_no_errors(self.controller)
306
307 entries = self.do_entry_desc_stats()
308 seen = set()
309 for entry in entries:
310 logging.debug(entry.show())
311 key = tlv_dict(entry.key)
312 value = tlv_dict(entry.value)
313 self.assertIn(ofp.bsn_tlv.vlan_vid, key)
314 self.assertIn(ofp.bsn_tlv.ipv4, key)
315 self.assertIn(ofp.bsn_tlv.mac, value)
316 vlan_vid = key[ofp.bsn_tlv.vlan_vid]
317 seen.add(vlan_vid)
318 self.assertEqual(key[ofp.bsn_tlv.ipv4], 0x12345678)
319 self.assertEqual(value[ofp.bsn_tlv.mac], [0, 1, 2, 3, 4, vlan_vid])
320 self.assertEqual(entry.checksum, 0xfedcba9876543210fedcba9876543210 + vlan_vid)
321
322 self.assertEquals(seen, set([0, 1, 2]))
Rich Lane4e691ad2014-01-06 17:45:20 -0800323
Rich Lane790cc202014-01-08 14:54:25 -0800324class EntryDescStatsMasked(BaseGenTableTest):
325 """
326 Test retrieving entry desc stats with a checksum mask
327 """
328 def runTest(self):
329 def get_range(checksum, checksum_mask):
330 entries = self.do_entry_desc_stats(checksum, checksum_mask)
331 vlan_vids = []
332 for entry in entries:
333 key = tlv_dict(entry.key)
334 vlan_vids.append(key[ofp.bsn_tlv.vlan_vid])
335 return sorted(vlan_vids)
336
337 # Add 4 entries to each checksum bucket
338 for i in range(0, 256):
339 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
Rich Lane8d867ee2014-01-08 17:29:55 -0800340 checksum=make_checksum(i, i))
Rich Lane790cc202014-01-08 14:54:25 -0800341
342 do_barrier(self.controller)
343 verify_no_errors(self.controller)
344
345 # Check first bucket
346 self.assertEquals(get_range(make_checksum(0, 0), make_checksum(0xFC, 0)),
347 [0, 1, 2, 3])
348
349 # Check last bucket
350 self.assertEquals(get_range(make_checksum(0xFC, 0), make_checksum(0xFC, 0)),
351 [252, 253, 254, 255])
352
353 # Check first half of first bucket
354 self.assertEquals(get_range(make_checksum(0x00, 0), make_checksum(0xFE, 0)),
355 [0, 1])
356
357 # Check second half of first bucket
358 self.assertEquals(get_range(make_checksum(0x02, 0), make_checksum(0xFE, 0)),
359 [2, 3])
360
361 # Check first half of last bucket
362 self.assertEquals(get_range(make_checksum(0xFC, 0), make_checksum(0xFE, 0)),
363 [252, 253])
364
365 # Check second half of last bucket
366 self.assertEquals(get_range(make_checksum(0xFE, 0), make_checksum(0xFE, 0)),
367 [254, 255])
368
369 # Check first two buckets
370 self.assertEquals(get_range(make_checksum(0, 0), make_checksum(0xF8, 0)),
371 [0, 1, 2, 3, 4, 5, 6, 7])
372
373 # Check last two buckets
374 self.assertEquals(get_range(make_checksum(0xF8, 0), make_checksum(0xF8, 0)),
375 [248, 249, 250, 251, 252, 253, 254, 255])
376
377 # Check matching on low bits
378 self.assertEquals(get_range(make_checksum(0x00, 0x00), ~1), [0])
379 self.assertEquals(get_range(make_checksum(0x01, 0x00), ~1), [1])
380 self.assertEquals(get_range(make_checksum(0x01, 0x02), ~1), [])
381
Rich Lane5003c292014-01-08 17:34:45 -0800382class EntryDescStatsFragmented(BaseGenTableTest):
383 """
384 Test retrieving entry stats in mutiple replies
385 """
386 def runTest(self):
387 # Add a bunch of entries
388 # Enough for 3 stats replies
Rich Lane87f54bd2014-01-08 17:53:14 -0800389 for i in range(0, 4095):
Rich Lane5003c292014-01-08 17:34:45 -0800390 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
391
392 do_barrier(self.controller)
393 verify_no_errors(self.controller)
394
395 entries = self.do_entry_desc_stats()
396 seen = set()
397 for entry in entries:
398 key = tlv_dict(entry.key)
399 vlan_vid = key[ofp.bsn_tlv.vlan_vid]
400 self.assertNotIn(vlan_vid, seen)
401 seen.add(vlan_vid)
402
Rich Lane87f54bd2014-01-08 17:53:14 -0800403 self.assertEquals(seen, set(range(0, 4095)))
Rich Lane5003c292014-01-08 17:34:45 -0800404
Rich Lane4e691ad2014-01-06 17:45:20 -0800405class TableDescStats(BaseGenTableTest):
406 """
407 Test retrieving table desc stats
408 """
409 def runTest(self):
410 entries = self.do_table_desc_stats()
411 seen = set()
412 for entry in entries:
413 logging.debug(entry.show())
414 self.assertNotIn(entry.table_id, seen)
415 self.assertNotIn(entry.name, seen)
416 seen.add(entry.table_id)
417 seen.add(entry.name)
418 if entry.table_id == TABLE_ID:
419 self.assertEqual(entry.name, "test")
420 self.assertEqual(entry.buckets_size, 64)
421 self.assertEqual(entry.max_entries, 1000)
422
423 self.assertIn(TABLE_ID, seen)
Rich Lanea8f56672014-01-06 17:50:39 -0800424
425class TableStats(BaseGenTableTest):
426 """
427 Test retrieving table stats
428 """
429 def runTest(self):
Rich Lane64c4e602014-01-07 11:27:06 -0800430 # Verify we have the test table and no duplicates
Rich Lanea8f56672014-01-06 17:50:39 -0800431 entries = self.do_table_stats()
432 seen = set()
433 for entry in entries:
434 logging.debug(entry.show())
435 self.assertNotIn(entry.table_id, seen)
436 seen.add(entry.table_id)
437 if entry.table_id == TABLE_ID:
438 self.assertEqual(entry.entry_count, 0)
439 self.assertEqual(entry.checksum, 0)
Rich Lanea8f56672014-01-06 17:50:39 -0800440 self.assertIn(TABLE_ID, seen)
Rich Lane64c4e602014-01-07 11:27:06 -0800441
442 table_checksum = 0
443
444 # Add a bunch of entries, spread among the checksum buckets
445 for i in range(0, 256):
446 table_checksum ^= make_checksum(i, i*31)
447 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
448 checksum=make_checksum(i, i*31))
449
450 do_barrier(self.controller)
451 verify_no_errors(self.controller)
452
453 table_stats = self.do_test_table_stats()
454 self.assertEqual(table_stats.entry_count, 256)
455 self.assertEqual(table_stats.checksum, table_checksum)
456
457 # Modify an entry, changing its checksum
458 i = 30
459 table_checksum ^= make_checksum(i, i*31) # subtract old checksum
460 table_checksum ^= make_checksum(i, i*37) # add new checksum
461 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 4, 3, 2, 1, i),
462 checksum=make_checksum(i, i*37))
463
464 do_barrier(self.controller)
465 verify_no_errors(self.controller)
466
467 table_stats = self.do_test_table_stats()
468 self.assertEqual(table_stats.entry_count, 256)
469 self.assertEqual(table_stats.checksum, table_checksum)
470
471 # Delete an entry
472 i = 87
473 table_checksum ^= make_checksum(i, i*31)
474 self.do_delete(vlan_vid=i, ipv4=0x12345678)
475
476 do_barrier(self.controller)
477 verify_no_errors(self.controller)
478
479 table_stats = self.do_test_table_stats()
480 self.assertEqual(table_stats.entry_count, 255)
481 self.assertEqual(table_stats.checksum, table_checksum)
Rich Lane232d2ab2014-01-07 12:23:16 -0800482
483class BucketStats(BaseGenTableTest):
484 """
485 Test retrieving checksum bucket stats
486 """
487 def runTest(self):
488 # Verify initial state
489 entries = self.do_bucket_stats()
490 self.assertEquals(len(entries), 64)
491 for entry in entries:
492 self.assertEquals(entry.checksum, 0)
493
494 buckets = [0] * len(entries)
495 checksum_bits = int(math.log(len(buckets), 2))
496
497 def update_bucket(checksum):
498 index = checksum >> (128 - checksum_bits)
499 buckets[index] ^= checksum
500
501 # Add a bunch of entries, spread among the checksum buckets
502 for i in range(0, 256):
503 update_bucket(make_checksum(i, i*31))
504 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
505 checksum=make_checksum(i, i*31))
506
507 entries = self.do_bucket_stats()
508 self.assertEquals(len(entries), 64)
509 for i, entry in enumerate(entries):
510 self.assertEquals(entry.checksum, buckets[i])
511
512 # Modify an entry, changing its checksum
513 i = 30
514 update_bucket(make_checksum(i, i*31)) # subtract old checksum
515 update_bucket(make_checksum(i, i*37)) # add new checksum
516 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 4, 3, 2, 1, i),
517 checksum=make_checksum(i, i*37))
518
519 do_barrier(self.controller)
520 verify_no_errors(self.controller)
521
522 entries = self.do_bucket_stats()
523 self.assertEquals(len(entries), 64)
524 for i, entry in enumerate(entries):
525 self.assertEquals(entry.checksum, buckets[i])
526
527 # Delete an entry
528 i = 87
529 update_bucket(make_checksum(i, i*31))
530 self.do_delete(vlan_vid=i, ipv4=0x12345678)
531
532 do_barrier(self.controller)
533 verify_no_errors(self.controller)
534
535 entries = self.do_bucket_stats()
536 self.assertEquals(len(entries), 64)
537 for i, entry in enumerate(entries):
538 self.assertEquals(entry.checksum, buckets[i])
Rich Lane78bd3772014-01-08 11:51:13 -0800539
Rich Lane7fdc07d2014-01-09 14:24:40 -0800540class BucketStatsFragmented(BaseGenTableTest):
541 """
542 Test retrieving checksum bucket stats in multiple replies
543 """
544
545 def tearDown(self):
546 self.do_set_buckets_size(64)
547 do_barrier(self.controller)
548 BaseGenTableTest.tearDown(self)
549
550 def runTest(self):
551 # Enough for 3 stats messages
552 self.do_set_buckets_size(8192)
553 do_barrier(self.controller)
554 verify_no_errors(self.controller)
555
556 entries = self.do_bucket_stats()
557 self.assertEquals(len(entries), 8192)
558
Rich Lane78bd3772014-01-08 11:51:13 -0800559class SetBucketsSize(BaseGenTableTest):
560 """
561 Test setting the checksum buckets size
562 """
563 def setUp(self):
564 BaseGenTableTest.setUp(self)
565 self.do_set_buckets_size(64)
566 do_barrier(self.controller)
567
568 def tearDown(self):
569 self.do_set_buckets_size(64)
570 do_barrier(self.controller)
571 BaseGenTableTest.tearDown(self)
572
573 def runTest(self):
574 # Verify initial state
575 entries = self.do_bucket_stats()
576 self.assertEquals(len(entries), 64)
577 for entry in entries:
578 self.assertEquals(entry.checksum, 0)
579
580 buckets32 = [0] * 32
581 buckets64 = [0] * 64
582
583 def update_bucket(checksum):
584 buckets32[checksum >> (128 - int(math.log(32, 2)))] ^= checksum
585 buckets64[checksum >> (128 - int(math.log(64, 2)))] ^= checksum
586
587 # Add a bunch of entries, spread among the checksum buckets
588 for i in range(0, 256):
589 update_bucket(make_checksum(i, i*31))
590 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
591 checksum=make_checksum(i, i*31))
592
593 entries = self.do_bucket_stats()
594 self.assertEquals(len(entries), 64)
595 for i, entry in enumerate(entries):
596 self.assertEquals(entry.checksum, buckets64[i])
597
598 self.do_set_buckets_size(32)
599 do_barrier(self.controller)
600
601 entries = self.do_bucket_stats()
602 self.assertEquals(len(entries), 32)
603 for i, entry in enumerate(entries):
604 self.assertEquals(entry.checksum, buckets32[i])
605
606 self.do_set_buckets_size(64)
607 do_barrier(self.controller)
608
609 entries = self.do_bucket_stats()
610 self.assertEquals(len(entries), 64)
611 for i, entry in enumerate(entries):
612 self.assertEquals(entry.checksum, buckets64[i])
Rich Lane55408072014-01-09 10:12:36 -0800613
Rich Laneeda1a4a2014-01-09 12:26:27 -0800614class SetBucketsSizeError(BaseGenTableTest):
615 """
616 Test error cases in setting the checksum buckets size
617 """
618 def setUp(self):
619 BaseGenTableTest.setUp(self)
620 self.do_set_buckets_size(64)
621 do_barrier(self.controller)
622
623 def tearDown(self):
624 self.do_set_buckets_size(64)
625 do_barrier(self.controller)
626 BaseGenTableTest.tearDown(self)
627
628 def runTest(self):
629 # Zero buckets size
630 self.do_set_buckets_size(0)
631 do_barrier(self.controller)
632
633 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
634 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
635 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
636
637 # Non power of 2 buckets size
638 self.do_set_buckets_size(7)
639 do_barrier(self.controller)
640
641 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
642 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
643 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
644
Rich Lane55408072014-01-09 10:12:36 -0800645class AddError(BaseGenTableTest):
646 """
647 Test failure adding entries
648 """
649 def runTest(self):
650 # Invalid key
651 self.do_add(vlan_vid=10000, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
652 do_barrier(self.controller)
653
654 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
655 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
656 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
657
658 self.assertEquals(len(self.do_entry_desc_stats()), 0)
659
660 # Invalid value
661 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(1, 1, 2, 3, 4, 5))
662 do_barrier(self.controller)
663
664 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
665 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
666 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
667
668 self.assertEquals(len(self.do_entry_desc_stats()), 0)
669
670class ModifyError(BaseGenTableTest):
671 """
672 Test failure modifying entries
673 """
674 def runTest(self):
675 # Add a valid entry we'll try to modify
676 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
677 do_barrier(self.controller)
678 verify_no_errors(self.controller)
679
680 orig_entries = self.do_entry_desc_stats()
681 self.assertEquals(len(orig_entries), 1)
682
683 # Invalid value
684 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(1, 1, 2, 3, 4, 5))
685 do_barrier(self.controller)
686
687 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
688 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
689 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
690
691 # Check that the table wasn't modified
692 new_entries = self.do_entry_desc_stats()
693 self.assertEquals(len(new_entries), 1)
694 self.assertEquals(new_entries, orig_entries)
Rich Lane14e4c142014-01-09 10:31:08 -0800695
Rich Laneb1186cc2014-01-09 11:20:26 -0800696class DeleteNonexistentError(BaseGenTableTest):
697 """
698 Test failure deleting a nonexistent entry
699 """
700 def runTest(self):
701 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
702 do_barrier(self.controller)
703
704 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
Rich Lanea49c4de2014-02-05 14:18:40 -0800705 self.assertEquals(error, None)
Rich Laneb1186cc2014-01-09 11:20:26 -0800706
Rich Lane9f6c6272014-01-09 12:16:08 -0800707class DeleteFailureError(BaseGenTableTest):
708 """
709 Test failure deleting a nonexistent entry
710
711 The very special idle_notification TLV will cause the entry to fail
712 being deleted the first time. This behavior is only there to help
713 test this error path.
714 """
715 def runTest(self):
716 self.do_add(vlan_vid=1000, ipv4=0x12345678,
717 mac=(0, 1, 2, 3, 4, 5), idle_notification=True)
718 do_barrier(self.controller)
719 verify_no_errors(self.controller)
720
721 orig_entries = self.do_entry_desc_stats()
722 self.assertEquals(len(orig_entries), 1)
723
724 # This will fail
725 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
726 do_barrier(self.controller)
727
728 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
729 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
730 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
731
732 # Check that the table wasn't modified
733 new_entries = self.do_entry_desc_stats()
734 self.assertEquals(len(new_entries), 1)
735 self.assertEquals(new_entries, orig_entries)
736
737 # This will succeed
738 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
739 do_barrier(self.controller)
740 verify_no_errors(self.controller)
741
Rich Lane14e4c142014-01-09 10:31:08 -0800742class BadTableIdError(BaseGenTableTest):
743 """
744 Test failure of each message when specifying a nonexistent table id
745 """
746 def runTest(self):
747 def check_error(msg):
748 reply, _ = self.controller.transact(msg)
749 self.assertIsInstance(reply, ofp.message.bad_request_error_msg)
750 self.assertEquals(reply.code, ofp.OFPBRC_BAD_TABLE_ID)
751
752 valid_table_ids = set([x.table_id for x in self.do_table_desc_stats()])
753 invalid_table_id = TABLE_ID
754 while invalid_table_id in valid_table_ids:
755 invalid_table_id = random.randrange(65536)
756
757 logging.debug("Using invalid table id %d", invalid_table_id)
758
759 check_error(ofp.message.bsn_gentable_clear_request(
760 table_id=invalid_table_id))
761
762 check_error(ofp.message.bsn_gentable_entry_add(
763 table_id=invalid_table_id))
764
765 check_error(ofp.message.bsn_gentable_entry_delete(
766 table_id=invalid_table_id))
767
768 check_error(ofp.message.bsn_gentable_entry_stats_request(
769 table_id=invalid_table_id))
770
771 check_error(ofp.message.bsn_gentable_entry_desc_stats_request(
772 table_id=invalid_table_id))
773
774 check_error(ofp.message.bsn_gentable_bucket_stats_request(
775 table_id=invalid_table_id))
776
777 check_error(ofp.message.bsn_gentable_set_buckets_size(
778 table_id=invalid_table_id))