From 36f8ba7141ba4696ef67b4c16f2f804cd65d4cb7 Mon Sep 17 00:00:00 2001 From: Stephen Sun <5379172+stephenxs@users.noreply.github.com> Date: Sun, 19 Jun 2022 19:36:39 +0800 Subject: [PATCH] Optimize the logic to compare the routing entries between ASIC_DB and the prefixes pushed to DUT (#5769) - What is the motivation for this PR? Optimize the logic to compare the routing entries between ASIC_DB and the prefixes pushed to DUT - How did you do it? The idea is to extract the prefixes from the output of the DUT and to avoid using json.load for each routing entry to use set instead of list to check difference. O(n*n) => O(n*lg(n)) How did you verify/test it? Run the test. Signed-off-by: Stephen Sun --- tests/route/test_route_perf.py | 41 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/tests/route/test_route_perf.py b/tests/route/test_route_perf.py index 10f4b2c63ab..29ae1227983 100644 --- a/tests/route/test_route_perf.py +++ b/tests/route/test_route_perf.py @@ -160,6 +160,7 @@ def exec_routes(duthost, prefixes, str_intf_nexthop, op): # Generate json file for routes generate_route_file(duthost, prefixes, str_intf_nexthop, route_file_dir, op) + logger.info('Route file generated and copied') # Check the number of routes in ASIC_DB start_num_route = count_routes(duthost) @@ -176,36 +177,44 @@ def exec_routes(duthost, prefixes, str_intf_nexthop, op): pytest.fail('Operation {} not supported'.format(op)) start_time = datetime.now() + logger.info('Before pushing route to swssconfig') # Apply routes with swssconfig result = duthost.shell('docker exec -i swss swssconfig /dev/stdin < {}'.format(route_file_dir), module_ignore_errors=True) if result['rc'] != 0: pytest.fail('Failed to apply route configuration file: {}'.format(result['stderr'])) - - # Wait until the routes set/del applys to ASIC_DB - def _check_num_routes(expected_num_routes): - # Check the number of routes in ASIC_DB - return count_routes(duthost) == expected_num_routes - - if not wait_until(route_timeout, 0.5, 0, _check_num_routes, expected_num_routes): - pytest.fail('failed to add routes within time limit') + logger.info('All route entries have been pushed') + + total_delay = 0 + actual_num_routes = count_routes(duthost) + while actual_num_routes != expected_num_routes: + diff = abs(expected_num_routes - actual_num_routes) + delay = max(diff / 5000, 1) + now = datetime.now() + total_delay = (now - start_time).total_seconds() + logger.info('Current {} expected {} delayed {} will delay {}'.format(actual_num_routes, expected_num_routes, total_delay, delay)) + time.sleep(delay) + actual_num_routes = count_routes(duthost) + if total_delay >= route_timeout: + break # Record time when all routes show up in ASIC_DB end_time = datetime.now() + logger.info('All route entries have been installed in ASIC_DB in {} seconds'.format((end_time - start_time).total_seconds())) # Check route entries are correct asic_route_keys = duthost.shell('sonic-db-cli ASIC_DB eval "return redis.call(\'keys\', \'{}*\')" 0'\ .format(ROUTE_TABLE_NAME), verbose=False)['stdout_lines'] - asic_prefixes = [] - for key in asic_route_keys: - json_obj = key[len(ROUTE_TABLE_NAME) + 1 : ] - asic_prefixes.append(json.loads(json_obj)['dest']) + table_name_length = len(ROUTE_TABLE_NAME) + asic_route_keys_set = set([re.search("\"dest\":\"([0-9a-f:/\.]*)\"", x[table_name_length:]).group(1) for x in asic_route_keys]) + prefixes_set = set(prefixes) + diff = prefixes_set - asic_route_keys_set if op == 'SET': - assert all(prefix in asic_prefixes for prefix in prefixes) + if diff: + pytest.fail("The following entries have not been installed into ASIC {}".format(diff)) elif op == 'DEL': - assert all(prefix not in asic_prefixes for prefix in prefixes) - else: - pytest.fail('Operation {} not supported'.format(op)) + if diff != prefixes_set: + pytest.fail("The following entries have not been withdrawn from ASIC {}".format(prefixes_set - diff)) # Retuen time used for set/del routes return (end_time - start_time).total_seconds()