-
Notifications
You must be signed in to change notification settings - Fork 1k
[pytest] Convert FDB MAC Expire Test #1741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tahmed-dev
merged 2 commits into
sonic-net:master
from
tahmed-dev:taahme/convert-fdb-mac-expire
Jun 12, 2020
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../tests/fdb/files/fdb.j2 |
Empty file.
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # FDB MAC Expire Args file | ||
|
|
||
| def add_fdb_mac_expire_args(parser): | ||
| """ | ||
| Adding arguments required for FDB MAC expire test cases | ||
|
|
||
| Args: | ||
| parser: pytest parser object | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| fdb_group = parser.getgroup("FDB test suite options") | ||
|
|
||
| fdb_group.addoption( | ||
| "--fdb_aging_time", | ||
| action="store", | ||
| type=int, | ||
| default=60, | ||
| help="FDB aging time in seconds", | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| from args.fdb_args import add_fdb_mac_expire_args | ||
|
|
||
| # FDB pytest arguments | ||
| def pytest_addoption(parser): | ||
| ''' | ||
| Adds option to FDB pytest | ||
|
|
||
| Args: | ||
| parser: pytest parser object | ||
|
|
||
| Returns: | ||
| None | ||
| ''' | ||
| add_fdb_mac_expire_args(parser) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| {% for vlan in minigraph_vlan_interfaces %} | ||
| {{ vlan['subnet'] }} {% for ifname in minigraph_vlans[vlan['attachto']]['members'] %} {{ minigraph_port_indices[ifname] }} {% endfor %} | ||
| {% endfor %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,259 @@ | ||
| import logging | ||
| import pytest | ||
| import time | ||
|
|
||
| from common.helpers.assertions import pytest_assert | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| class TestFdbMacExpire: | ||
| """ | ||
| TestFdbMacExpire Verifies FDb aging timer is respected | ||
|
|
||
| The test updates fdb_aging_time value, restarts swssconfig in order to pickup the new value, | ||
| populated the FDB table with dummy MAC entry, and then waits for fdb_aging_time and makes sure | ||
| FDB entry with dummy MAC is cleared. | ||
| """ | ||
| DUMMY_MAC_PREFIX = "00:11:22:33:44" | ||
| FDB_INFO_FILE = "/root/fdb_info.txt" | ||
| POLLING_INTERVAL_SEC = 15 | ||
|
|
||
| def __getFdbTableCount(self, duthost, mac): | ||
| """ | ||
| Gets number of FDB table entries containing mac entry. | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
| mac (str): MAC value to search for in the FDB table | ||
|
|
||
| Returns: | ||
| (int) representing the number of the FDB entries containing th eMAC address | ||
| """ | ||
| return int(duthost.shell("show mac | grep {0} | wc -l".format(mac))["stdout"]) | ||
|
|
||
| def __loadSwssConfig(self, duthost): | ||
| """ | ||
| Load SWSS configuration on DUT | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
|
|
||
| Raises: | ||
| asserts if the load SWSS config failed | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| duthost.shell(argv=[ | ||
| "docker", | ||
| "exec", | ||
| "swss", | ||
| "bash", | ||
| "-c", | ||
| "swssconfig /etc/swss/config.d/switch.json" | ||
| ]) | ||
|
|
||
| def __deleteTmpSwitchConfig(self, duthost): | ||
| """ | ||
| Delete temporary switch.json cofiguration files | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| result = duthost.find(path=["/tmp"], patterns=["switch.json*"]) | ||
| for file in result["files"]: | ||
| duthost.file(path=file["path"], state="absent") | ||
|
|
||
| def __runPtfTest(self, ptfhost, testCase='', testParams={}): | ||
| """ | ||
| Runs FDB MAC Expire test case on PTF host | ||
|
|
||
| Args: | ||
| ptfhost (AnsibleHost): Packet Test Framework (PTF) | ||
| testCase (str): FDB tests test case name | ||
| testParams (dict): Map of test params required by testCase | ||
|
|
||
| Returns: | ||
| None | ||
|
|
||
| Raises: | ||
| RunAnsibleModuleFail if ptf test fails | ||
| """ | ||
| logger.info("Running PTF test case '{0}' on '{1}'".format(testCase, ptfhost.hostname)) | ||
| ptfhost.shell(argv=[ | ||
| "ptf", | ||
| "--test-dir", | ||
| "ptftests", | ||
| testCase, | ||
| "--platform-dir", | ||
| "ptftests", | ||
| "--platform", | ||
| "remote", | ||
| "-t", | ||
| ";".join(["{0}={1}".format(k, repr(v)) for k, v in testParams.items()]), | ||
| "--relax", | ||
| "--debug", | ||
| "info", | ||
| "--log-file", | ||
| "/tmp/{0}".format(testCase) | ||
| ], | ||
| chdir = "/root", | ||
| ) | ||
tahmed-dev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| @pytest.fixture(scope="class", autouse=True) | ||
| def copyFdbInfo(self, duthost, ptfhost): | ||
| """ | ||
| Compies FDB info file to PTF host | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
| ptfhost (AnsibleHost): Packet Test Framework (PTF) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| mgFacts = duthost.minigraph_facts(host=duthost.hostname)["ansible_facts"] | ||
| ptfhost.host.options['variable_manager'].extra_vars.update({ | ||
| "minigraph_vlan_interfaces": mgFacts["minigraph_vlan_interfaces"], | ||
| "minigraph_port_indices": mgFacts["minigraph_port_indices"], | ||
| "minigraph_vlans": mgFacts["minigraph_vlans"], | ||
| }) | ||
|
|
||
| logger.info("Copying fdb_info.txt config file to {0}".format(ptfhost.hostname)) | ||
| ptfhost.template(src="fdb/files/fdb.j2", dest=self.FDB_INFO_FILE) | ||
|
|
||
| @pytest.fixture(scope="class", autouse=True) | ||
| def copyPtfDirectory(self, ptfhost): | ||
| """ | ||
| Copys PTF directory to PTF host. | ||
|
|
||
| Args: | ||
| ptfhost (AnsibleHost): Packet Test Framework (PTF) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| ptfhost.copy(src="ptftests", dest="/root") | ||
|
|
||
| @pytest.fixture(scope="class", autouse=True) | ||
| def clearSonicFdbEntries(self, duthost): | ||
| """ | ||
| Clears SONiC FDB entries before and after test | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| duthost.shell(argv=["sonic-clear", "fdb", "all"]) | ||
|
|
||
| yield | ||
|
|
||
| duthost.shell(argv=["sonic-clear", "fdb", "all"]) | ||
|
|
||
| @pytest.fixture(scope="class", autouse=True) | ||
| def validateDummyMacAbsent(self, duthost): | ||
| """ | ||
| Validates that test/dummy MAC entry is absent before the test runs | ||
|
|
||
| Args: | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| pytest_assert(self.__getFdbTableCount(duthost, self.DUMMY_MAC_PREFIX) == 0, "Test dummy MAC is already present") | ||
|
|
||
| @pytest.fixture(scope="class", autouse=True) | ||
| def prepareDut(self, request, duthost): | ||
| """ | ||
| Prepare DUT for FDB test | ||
|
|
||
| It update the fdb_aging_time value, update the swss configuration, and restore SWSS configuration afer | ||
| test completes | ||
|
|
||
| Args: | ||
| request (Fixture): pytest request object | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| fdbAgingTime = request.config.getoption('--fdb_aging_time') | ||
|
|
||
| self.__deleteTmpSwitchConfig(duthost) | ||
| duthost.shell(argv=["docker", "cp", "swss:/etc/swss/config.d/switch.json", "/tmp"]) | ||
| duthost.replace( | ||
| dest='/tmp/switch.json', | ||
| regexp='"fdb_aging_time": ".*"', | ||
| replace='"fdb_aging_time": "{0}"'.format(fdbAgingTime), | ||
| backup=True | ||
| ) | ||
| duthost.shell(argv=["docker", "cp", "/tmp/switch.json", "swss:/etc/swss/config.d/switch.json"]) | ||
| self.__loadSwssConfig(duthost) | ||
|
|
||
| yield | ||
|
|
||
| result = duthost.find(path=["/tmp"], patterns=["switch.json.*"]) | ||
| if result["matched"] > 0: | ||
| duthost.shell(argv=["docker", "cp", result["files"][0]["path"], "swss:/etc/swss/config.d/switch.json"]) | ||
| self.__loadSwssConfig(duthost) | ||
| self.__deleteTmpSwitchConfig(duthost) | ||
|
|
||
| def testFdbMacExpire(self, request, testbed, duthost, ptfhost): | ||
| """ | ||
| TestFdbMacExpire Verifies FDb aging timer is respected | ||
|
|
||
| The test updates fdb_aging_time value, restarts swssconfig in order to pickup the new value, | ||
| populated the FDB table with dummy MAC entry, and then waits for fdb_aging_time and makes sure | ||
| FDB entry with dummy MAC is cleared. | ||
|
|
||
| Args: | ||
| request (Fixture): pytest request object | ||
| testbed (Fixture, dict): Map containing testbed information | ||
| duthost (AnsibleHost): Device Under Test (DUT) | ||
| ptfhost (AnsibleHost): Packet Test Framework (PTF) | ||
|
|
||
| Returns: | ||
| None | ||
| """ | ||
| if "t0" not in testbed["topo"]["type"]: | ||
| pytest.skip( | ||
| "FDB MAC Expire test case is not supported on this DUT topology '{0}'".format(testbed["topo"]["type"]) | ||
| ) | ||
|
|
||
| fdbAgingTime = request.config.getoption('--fdb_aging_time') | ||
| hostFacts = duthost.setup()['ansible_facts'] | ||
|
|
||
| testParams = { | ||
| "testbed_type": testbed["topo"]["name"], | ||
| "router_mac": hostFacts['ansible_Ethernet0']['macaddress'], | ||
| "fdb_info": self.FDB_INFO_FILE, | ||
| "dummy_mac_prefix": self.DUMMY_MAC_PREFIX, | ||
| } | ||
| self.__runPtfTest(ptfhost, "fdb_mac_expire_test.FdbMacExpireTest", testParams) | ||
|
|
||
| logger.info("wait for FDB aging time of '{0}' secs".format(fdbAgingTime)) | ||
| time.sleep(fdbAgingTime) | ||
|
|
||
| count = 0 | ||
| dummyMacCount = self.__getFdbTableCount(duthost, self.DUMMY_MAC_PREFIX) | ||
| while count * self.POLLING_INTERVAL_SEC < fdbAgingTime and dummyMacCount != 0: | ||
| time.sleep(self.POLLING_INTERVAL_SEC) | ||
| dummyMacCount = self.__getFdbTableCount(duthost, self.DUMMY_MAC_PREFIX) | ||
| count += 1 | ||
| logger.info( | ||
| "MAC table entries count: {0}, after {1} sec".format( | ||
| dummyMacCount, | ||
| fdbAgingTime + count * self.POLLING_INTERVAL_SEC | ||
| ) | ||
| ) | ||
|
|
||
| pytest_assert( | ||
| dummyMacCount == 0, | ||
| "Failed! MAC did not expire after expected FDB aging time expired" | ||
| ) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.