Skip to content

Commit 1fa5387

Browse files
cherry pick #9523 and #9312 (#9591)
1 parent 8918907 commit 1fa5387

File tree

5 files changed

+187
-98
lines changed

5 files changed

+187
-98
lines changed

tests/cacl/test_cacl_function.py

Lines changed: 76 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
from tests.common.helpers.assertions import pytest_assert
44
from tests.common.helpers.snmp_helpers import get_snmp_facts
5+
from tests.common.utilities import get_data_acl, recover_acl_rule
56

67
try:
78
import ntplib
@@ -25,6 +26,7 @@ def test_cacl_function(duthosts, enum_rand_one_per_hwsku_hostname, localhost, cr
2526
"""Test control plane ACL functionality on a SONiC device"""
2627

2728
duthost = duthosts[enum_rand_one_per_hwsku_hostname]
29+
data_acl = get_data_acl(duthost)
2830
dut_mgmt_ip = duthost.mgmt_ip
2931

3032
# Start an NTP client
@@ -48,76 +50,79 @@ def test_cacl_function(duthosts, enum_rand_one_per_hwsku_hostname, localhost, cr
4850
ntp_client.request(dut_mgmt_ip)
4951
except ntplib.NTPException:
5052
pytest.fail("NTP did timed out when expected to succeed!")
51-
52-
# Copy config_service_acls.sh to the DuT (this also implicitly verifies we can successfully SSH to the DuT)
53-
duthost.copy(src="scripts/config_service_acls.sh", dest="/tmp/config_service_acls.sh", mode="0755")
54-
55-
# We run the config_service_acls.sh script in the background because it
56-
# will install ACL rules which will only allow control plane traffic
57-
# to an unused IP range. Thus, if it works properly, it will sever our
58-
# SSH session, but we don't want the script itself to get killed,
59-
# because it is also responsible for resetting the control plane ACLs
60-
# back to their previous, working state
61-
duthost.shell("nohup /tmp/config_service_acls.sh < /dev/null > /dev/null 2>&1 &")
62-
63-
# Wait until we are unable to SSH into the DuT
64-
res = localhost.wait_for(host=dut_mgmt_ip,
65-
port=SONIC_SSH_PORT,
66-
state='stopped',
67-
search_regex=SONIC_SSH_REGEX,
68-
delay=30,
69-
timeout=40,
70-
module_ignore_errors=True)
71-
72-
pytest_assert(not res.is_failed, "SSH port did not stop. {}".format(res.get('msg', '')))
73-
74-
# Try to SSH back into the DuT, it should time out
75-
res = localhost.wait_for(host=dut_mgmt_ip,
76-
port=SONIC_SSH_PORT,
77-
state='started',
78-
search_regex=SONIC_SSH_REGEX,
79-
delay=0,
80-
timeout=10,
81-
module_ignore_errors=True)
82-
83-
pytest_assert(res.is_failed, "SSH did not timeout when expected. {}".format(res.get('msg', '')))
84-
85-
# Ensure we CANNOT gather basic SNMP facts from the device
86-
res = get_snmp_facts(localhost, host=dut_mgmt_ip, version='v2c', community=creds['snmp_rocommunity'],
87-
module_ignore_errors=True)
88-
89-
pytest_assert('ansible_facts' not in res and "No SNMP response received before timeout" in res.get('msg', ''))
90-
91-
# Ensure we cannot send an NTP request to the DUT
92-
if NTPLIB_INSTALLED:
93-
try:
94-
ntp_client.request(dut_mgmt_ip)
95-
pytest.fail("NTP did not time out when expected")
96-
except ntplib.NTPException:
97-
pass
98-
99-
# Wait until the original service ACLs are reinstated and the SSH port on the
100-
# DUT is open to us once again. Note that the timeout here should be set sufficiently
101-
# long enough to allow config_service_acls.sh to reset the ACLs to their original
102-
# configuration.
103-
res = localhost.wait_for(host=dut_mgmt_ip,
104-
port=SONIC_SSH_PORT,
105-
state='started',
106-
search_regex=SONIC_SSH_REGEX,
107-
delay=0,
108-
timeout=90,
53+
try:
54+
# Copy config_service_acls.sh to the DuT (this also implicitly verifies we can successfully SSH to the DuT)
55+
duthost.copy(src="scripts/config_service_acls.sh", dest="/tmp/config_service_acls.sh", mode="0755")
56+
57+
# We run the config_service_acls.sh script in the background because it
58+
# will install ACL rules which will only allow control plane traffic
59+
# to an unused IP range. Thus, if it works properly, it will sever our
60+
# SSH session, but we don't want the script itself to get killed,
61+
# because it is also responsible for resetting the control plane ACLs
62+
# back to their previous, working state
63+
duthost.shell("nohup /tmp/config_service_acls.sh < /dev/null > /dev/null 2>&1 &")
64+
65+
# Wait until we are unable to SSH into the DuT
66+
res = localhost.wait_for(host=dut_mgmt_ip,
67+
port=SONIC_SSH_PORT,
68+
state='stopped',
69+
search_regex=SONIC_SSH_REGEX,
70+
delay=30,
71+
timeout=40,
72+
module_ignore_errors=True)
73+
74+
pytest_assert(not res.is_failed, "SSH port did not stop. {}".format(res.get('msg', '')))
75+
76+
# Try to SSH back into the DuT, it should time out
77+
res = localhost.wait_for(host=dut_mgmt_ip,
78+
port=SONIC_SSH_PORT,
79+
state='started',
80+
search_regex=SONIC_SSH_REGEX,
81+
delay=0,
82+
timeout=10,
83+
module_ignore_errors=True)
84+
85+
pytest_assert(res.is_failed, "SSH did not timeout when expected. {}".format(res.get('msg', '')))
86+
87+
# Ensure we CANNOT gather basic SNMP facts from the device
88+
res = get_snmp_facts(localhost, host=dut_mgmt_ip, version='v2c', community=creds['snmp_rocommunity'],
10989
module_ignore_errors=True)
11090

111-
pytest_assert(not res.is_failed, "SSH did not start working when expected. {}".format(res.get('msg', '')))
112-
113-
# Delete config_service_acls.sh from the DuT
114-
duthost.file(path="/tmp/config_service_acls.sh", state="absent")
115-
116-
# Ensure we can gather basic SNMP facts from the device once again. Should fail on timeout
117-
get_snmp_facts(localhost,
118-
host=dut_mgmt_ip,
119-
version="v2c",
120-
community=creds['snmp_rocommunity'],
121-
wait=True,
122-
timeout = 20,
123-
interval=20)
91+
pytest_assert('ansible_facts' not in res and "No SNMP response received before timeout" in res.get('msg', ''))
92+
93+
# Ensure we cannot send an NTP request to the DUT
94+
if NTPLIB_INSTALLED:
95+
try:
96+
ntp_client.request(dut_mgmt_ip)
97+
pytest.fail("NTP did not time out when expected")
98+
except ntplib.NTPException:
99+
pass
100+
101+
# Wait until the original service ACLs are reinstated and the SSH port on the
102+
# DUT is open to us once again. Note that the timeout here should be set sufficiently
103+
# long enough to allow config_service_acls.sh to reset the ACLs to their original
104+
# configuration.
105+
res = localhost.wait_for(host=dut_mgmt_ip,
106+
port=SONIC_SSH_PORT,
107+
state='started',
108+
search_regex=SONIC_SSH_REGEX,
109+
delay=0,
110+
timeout=90,
111+
module_ignore_errors=True)
112+
113+
pytest_assert(not res.is_failed, "SSH did not start working when expected. {}".format(res.get('msg', '')))
114+
115+
# Delete config_service_acls.sh from the DuT
116+
duthost.file(path="/tmp/config_service_acls.sh", state="absent")
117+
118+
# Ensure we can gather basic SNMP facts from the device once again. Should fail on timeout
119+
get_snmp_facts(localhost,
120+
host=dut_mgmt_ip,
121+
version="v2c",
122+
community=creds['snmp_rocommunity'],
123+
wait=True,
124+
timeout = 20,
125+
interval=20)
126+
finally:
127+
if data_acl:
128+
recover_acl_rule(duthost, data_acl)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"acl": {
3+
"acl-sets": {
4+
"acl-set": {
5+
"dataacl": {
6+
"acl-entries": {
7+
"acl-entry": {
8+
"1": {
9+
"actions": {
10+
"config": {
11+
"forwarding-action": "ACCEPT"
12+
}
13+
},
14+
"config": {
15+
"sequence-id": 1
16+
},
17+
"l2": {
18+
"config": {
19+
"ethertype": "2048",
20+
"vlan_id": "1000"
21+
}
22+
},
23+
"input_interface": {
24+
"interface_ref":
25+
{
26+
"config": {
27+
"interface": "Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet4,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet8"
28+
}
29+
}
30+
}
31+
}
32+
}
33+
}
34+
}
35+
}
36+
}
37+
}
38+
}

tests/common/utilities.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import threading
1616
import time
1717
import traceback
18+
import copy
19+
import tempfile
1820
from io import BytesIO
1921

2022
import pytest
@@ -863,3 +865,39 @@ def delete_running_config(config_entry, duthost, is_json=True):
863865
duthost.copy(src=config_entry, dest="/tmp/del_config_entry.json")
864866
duthost.shell("configlet -d -j {}".format("/tmp/del_config_entry.json"))
865867
duthost.shell("rm -f {}".format("/tmp/del_config_entry.json"))
868+
869+
def get_data_acl(duthost):
870+
acl_facts = duthost.acl_facts()["ansible_facts"]["ansible_acl_facts"]
871+
pre_acl_rules = acl_facts.get("DATAACL", {}).get("rules", None)
872+
return pre_acl_rules
873+
874+
875+
def recover_acl_rule(duthost, data_acl):
876+
base_dir = os.path.dirname(os.path.realpath(__file__))
877+
template_dir = os.path.join(base_dir, "templates")
878+
acl_rules_template = "default_acl_rules.json"
879+
dut_tmp_dir = "/tmp"
880+
dut_conf_file_path = os.path.join(dut_tmp_dir, acl_rules_template)
881+
882+
for key, value in data_acl.items():
883+
if key != "DEFAULT_RULE":
884+
seq_id = key.split('_')[1]
885+
acl_config = json.loads(open(os.path.join(template_dir, acl_rules_template)).read())
886+
acl_entry_template = \
887+
acl_config["acl"]["acl-sets"]["acl-set"]["dataacl"]["acl-entries"]["acl-entry"]["1"]
888+
acl_entry_config = acl_config["acl"]["acl-sets"]["acl-set"]["dataacl"]["acl-entries"]["acl-entry"]
889+
890+
acl_entry_config[seq_id] = copy.deepcopy(acl_entry_template)
891+
acl_entry_config[seq_id]["config"]["sequence-id"] = seq_id
892+
acl_entry_config[seq_id]["l2"]["config"]["ethertype"] = value["ETHER_TYPE"]
893+
acl_entry_config[seq_id]["l2"]["config"]["vlan_id"] = value["VLAN_ID"]
894+
acl_entry_config[seq_id]["input_interface"]["interface_ref"]["config"]["interface"] = value["IN_PORTS"]
895+
896+
with tempfile.NamedTemporaryFile(suffix=".json", prefix="acl_config", mode="w") as fp:
897+
json.dump(acl_config, fp)
898+
fp.flush()
899+
logger.info("Generating config for ACL rule, ACL table - DATAACL")
900+
duthost.template(src=fp.name, dest=dut_conf_file_path, force=True)
901+
902+
logger.info("Applying {}".format(dut_conf_file_path))
903+
duthost.command("acl-loader update full {}".format(dut_conf_file_path))

tests/crm/conftest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from test_crm import RESTORE_CMDS, CRM_POLLING_INTERVAL
88
from tests.common.errors import RunAnsibleModuleFail
9+
from tests.common.utilities import recover_acl_rule
910

1011
logger = logging.getLogger(__name__)
1112

@@ -52,7 +53,10 @@ def pytest_runtest_teardown(item, nextitem):
5253
for cmd in RESTORE_CMDS[test_name]:
5354
logger.info(cmd)
5455
try:
55-
dut.shell(cmd)
56+
if isinstance(cmd, dict):
57+
recover_acl_rule(dut, cmd["data_acl"])
58+
else:
59+
dut.shell(cmd)
5660
except RunAnsibleModuleFail as err:
5761
failures.append("Failure during command execution '{command}':\n{error}".format(command=cmd,
5862
error=str(err)))

tests/crm/test_crm.py

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from collections import OrderedDict
1616
from tests.common.fixtures.duthost_utils import disable_route_checker
1717
from tests.common.fixtures.duthost_utils import disable_fdb_aging
18-
from tests.common.utilities import wait_until
18+
from tests.common.utilities import wait_until, get_data_acl
1919

2020

2121
pytestmark = [
@@ -912,37 +912,41 @@ def recover_acl_rule(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_f
912912

913913

914914
def test_acl_entry(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_frontend_asic_index,
915-
collector, tbinfo, recover_acl_rule):
915+
collector, tbinfo):
916916
duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
917+
data_acl = get_data_acl(duthost)
917918
asichost = duthost.asic_instance(enum_frontend_asic_index)
918919
asic_collector = collector[asichost.asic_index]
919-
920-
if duthost.facts["asic_type"] == "marvell":
921-
# Remove DATA ACL Table and add it again with ports in same port group
922-
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
923-
tmp_ports = mg_facts["minigraph_ports"].keys()
924-
tmp_ports.sort(key=lambda x: int(x[8:]))
925-
for i in range(4):
926-
if i == 0:
927-
ports = ",".join(tmp_ports[17:19])
928-
elif i == 1:
929-
ports = ",".join(tmp_ports[24:26])
930-
elif i == 2:
931-
ports = ",".join([tmp_ports[20], tmp_ports[25]])
932-
recreate_acl_table(duthost, ports)
920+
try:
921+
if duthost.facts["asic_type"] == "marvell":
922+
# Remove DATA ACL Table and add it again with ports in same port group
923+
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
924+
tmp_ports = mg_facts["minigraph_ports"].keys()
925+
tmp_ports.sort(key=lambda x: int(x[8:]))
926+
for i in range(4):
927+
if i == 0:
928+
ports = ",".join(tmp_ports[17:19])
929+
elif i == 1:
930+
ports = ",".join(tmp_ports[24:26])
931+
elif i == 2:
932+
ports = ",".join([tmp_ports[20], tmp_ports[25]])
933+
recreate_acl_table(duthost, ports)
934+
verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hostname,
935+
enum_frontend_asic_index, asic_collector, tbinfo)
936+
# Rebind DATA ACL at end to recover original config
937+
recreate_acl_table(duthost, ports)
938+
apply_acl_config(duthost, asichost, "test_acl_entry", asic_collector)
939+
duthost.command("acl-loader delete")
940+
else:
933941
verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hostname,
934942
enum_frontend_asic_index, asic_collector, tbinfo)
935-
# Rebind DATA ACL at end to recover original config
936-
recreate_acl_table(duthost, ports)
937-
apply_acl_config(duthost, asichost, "test_acl_entry", asic_collector)
938-
duthost.command("acl-loader delete")
939-
else:
940-
verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hostname,
941-
enum_frontend_asic_index, asic_collector, tbinfo)
942943

943-
pytest_assert(crm_stats_checker,
944-
"\"crm_stats_acl_entry_used\" counter was not decremented or "
945-
"\"crm_stats_acl_entry_available\" counter was not incremented")
944+
pytest_assert(crm_stats_checker,
945+
"\"crm_stats_acl_entry_used\" counter was not decremented or "
946+
"\"crm_stats_acl_entry_available\" counter was not incremented")
947+
finally:
948+
if data_acl:
949+
RESTORE_CMDS["test_acl_entry"].append({"data_acl": data_acl})
946950

947951

948952
def verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hostname,

0 commit comments

Comments
 (0)