blob: 71d69158bb1f107dd0734c4f150b5eb127fa843b [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
540class SetBucketsSize(BaseGenTableTest):
541 """
542 Test setting the checksum buckets size
543 """
544 def setUp(self):
545 BaseGenTableTest.setUp(self)
546 self.do_set_buckets_size(64)
547 do_barrier(self.controller)
548
549 def tearDown(self):
550 self.do_set_buckets_size(64)
551 do_barrier(self.controller)
552 BaseGenTableTest.tearDown(self)
553
554 def runTest(self):
555 # Verify initial state
556 entries = self.do_bucket_stats()
557 self.assertEquals(len(entries), 64)
558 for entry in entries:
559 self.assertEquals(entry.checksum, 0)
560
561 buckets32 = [0] * 32
562 buckets64 = [0] * 64
563
564 def update_bucket(checksum):
565 buckets32[checksum >> (128 - int(math.log(32, 2)))] ^= checksum
566 buckets64[checksum >> (128 - int(math.log(64, 2)))] ^= checksum
567
568 # Add a bunch of entries, spread among the checksum buckets
569 for i in range(0, 256):
570 update_bucket(make_checksum(i, i*31))
571 self.do_add(vlan_vid=i, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, i),
572 checksum=make_checksum(i, i*31))
573
574 entries = self.do_bucket_stats()
575 self.assertEquals(len(entries), 64)
576 for i, entry in enumerate(entries):
577 self.assertEquals(entry.checksum, buckets64[i])
578
579 self.do_set_buckets_size(32)
580 do_barrier(self.controller)
581
582 entries = self.do_bucket_stats()
583 self.assertEquals(len(entries), 32)
584 for i, entry in enumerate(entries):
585 self.assertEquals(entry.checksum, buckets32[i])
586
587 self.do_set_buckets_size(64)
588 do_barrier(self.controller)
589
590 entries = self.do_bucket_stats()
591 self.assertEquals(len(entries), 64)
592 for i, entry in enumerate(entries):
593 self.assertEquals(entry.checksum, buckets64[i])
Rich Lane55408072014-01-09 10:12:36 -0800594
Rich Laneeda1a4a2014-01-09 12:26:27 -0800595class SetBucketsSizeError(BaseGenTableTest):
596 """
597 Test error cases in setting the checksum buckets size
598 """
599 def setUp(self):
600 BaseGenTableTest.setUp(self)
601 self.do_set_buckets_size(64)
602 do_barrier(self.controller)
603
604 def tearDown(self):
605 self.do_set_buckets_size(64)
606 do_barrier(self.controller)
607 BaseGenTableTest.tearDown(self)
608
609 def runTest(self):
610 # Zero buckets size
611 self.do_set_buckets_size(0)
612 do_barrier(self.controller)
613
614 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
615 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
616 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
617
618 # Non power of 2 buckets size
619 self.do_set_buckets_size(7)
620 do_barrier(self.controller)
621
622 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
623 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
624 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
625
Rich Lane55408072014-01-09 10:12:36 -0800626class AddError(BaseGenTableTest):
627 """
628 Test failure adding entries
629 """
630 def runTest(self):
631 # Invalid key
632 self.do_add(vlan_vid=10000, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
633 do_barrier(self.controller)
634
635 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
636 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
637 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
638
639 self.assertEquals(len(self.do_entry_desc_stats()), 0)
640
641 # Invalid value
642 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(1, 1, 2, 3, 4, 5))
643 do_barrier(self.controller)
644
645 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
646 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
647 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
648
649 self.assertEquals(len(self.do_entry_desc_stats()), 0)
650
651class ModifyError(BaseGenTableTest):
652 """
653 Test failure modifying entries
654 """
655 def runTest(self):
656 # Add a valid entry we'll try to modify
657 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(0, 1, 2, 3, 4, 5))
658 do_barrier(self.controller)
659 verify_no_errors(self.controller)
660
661 orig_entries = self.do_entry_desc_stats()
662 self.assertEquals(len(orig_entries), 1)
663
664 # Invalid value
665 self.do_add(vlan_vid=100, ipv4=0x12345678, mac=(1, 1, 2, 3, 4, 5))
666 do_barrier(self.controller)
667
668 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
669 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
670 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
671
672 # Check that the table wasn't modified
673 new_entries = self.do_entry_desc_stats()
674 self.assertEquals(len(new_entries), 1)
675 self.assertEquals(new_entries, orig_entries)
Rich Lane14e4c142014-01-09 10:31:08 -0800676
Rich Laneb1186cc2014-01-09 11:20:26 -0800677class DeleteNonexistentError(BaseGenTableTest):
678 """
679 Test failure deleting a nonexistent entry
680 """
681 def runTest(self):
682 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
683 do_barrier(self.controller)
684
685 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
686 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
687 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
688
Rich Lane9f6c6272014-01-09 12:16:08 -0800689class DeleteFailureError(BaseGenTableTest):
690 """
691 Test failure deleting a nonexistent entry
692
693 The very special idle_notification TLV will cause the entry to fail
694 being deleted the first time. This behavior is only there to help
695 test this error path.
696 """
697 def runTest(self):
698 self.do_add(vlan_vid=1000, ipv4=0x12345678,
699 mac=(0, 1, 2, 3, 4, 5), idle_notification=True)
700 do_barrier(self.controller)
701 verify_no_errors(self.controller)
702
703 orig_entries = self.do_entry_desc_stats()
704 self.assertEquals(len(orig_entries), 1)
705
706 # This will fail
707 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
708 do_barrier(self.controller)
709
710 error, _ = self.controller.poll(ofp.OFPT_ERROR, 0)
711 self.assertIsInstance(error, ofp.message.bad_request_error_msg)
712 self.assertEquals(error.code, ofp.OFPBRC_EPERM)
713
714 # Check that the table wasn't modified
715 new_entries = self.do_entry_desc_stats()
716 self.assertEquals(len(new_entries), 1)
717 self.assertEquals(new_entries, orig_entries)
718
719 # This will succeed
720 self.do_delete(vlan_vid=1000, ipv4=0x12345678)
721 do_barrier(self.controller)
722 verify_no_errors(self.controller)
723
Rich Lane14e4c142014-01-09 10:31:08 -0800724class BadTableIdError(BaseGenTableTest):
725 """
726 Test failure of each message when specifying a nonexistent table id
727 """
728 def runTest(self):
729 def check_error(msg):
730 reply, _ = self.controller.transact(msg)
731 self.assertIsInstance(reply, ofp.message.bad_request_error_msg)
732 self.assertEquals(reply.code, ofp.OFPBRC_BAD_TABLE_ID)
733
734 valid_table_ids = set([x.table_id for x in self.do_table_desc_stats()])
735 invalid_table_id = TABLE_ID
736 while invalid_table_id in valid_table_ids:
737 invalid_table_id = random.randrange(65536)
738
739 logging.debug("Using invalid table id %d", invalid_table_id)
740
741 check_error(ofp.message.bsn_gentable_clear_request(
742 table_id=invalid_table_id))
743
744 check_error(ofp.message.bsn_gentable_entry_add(
745 table_id=invalid_table_id))
746
747 check_error(ofp.message.bsn_gentable_entry_delete(
748 table_id=invalid_table_id))
749
750 check_error(ofp.message.bsn_gentable_entry_stats_request(
751 table_id=invalid_table_id))
752
753 check_error(ofp.message.bsn_gentable_entry_desc_stats_request(
754 table_id=invalid_table_id))
755
756 check_error(ofp.message.bsn_gentable_bucket_stats_request(
757 table_id=invalid_table_id))
758
759 check_error(ofp.message.bsn_gentable_set_buckets_size(
760 table_id=invalid_table_id))