Skip to content

Commit e1a5e9a

Browse files
vasant17Vasant
and
Vasant
authored
Add DPB-ACL scale tests (#1243)
* Add DPB ACL test cases * Move common ACL test code to dvs_common Co-authored-by: Vasant <[email protected]>
1 parent 3829053 commit e1a5e9a

File tree

6 files changed

+563
-465
lines changed

6 files changed

+563
-465
lines changed

tests/conftest.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from datetime import datetime
1515
from swsscommon import swsscommon
1616
from dvslib import dvs_database as dvs_db
17+
from dvslib import dvs_acl
1718

1819
def ensure_system(cmd):
1920
(rc, output) = commands.getstatusoutput(cmd)
@@ -243,6 +244,8 @@ def __init__(self, name=None, imgname=None, keeptb=False, fakeplatform=None):
243244
self.flex_db = None
244245
self.state_db = None
245246

247+
self.dvs_acl = None
248+
246249
def destroy(self):
247250
if self.appldb:
248251
del self.appldb
@@ -953,31 +956,39 @@ def get_asic_db(self):
953956
self.asic_db = db
954957

955958
return self.asic_db
956-
959+
957960
def get_counters_db(self):
958961
if not self.counters_db:
959962
self.counters_db = dvs_db.DVSDatabase(self.COUNTERS_DB_ID, self.redis_sock)
960963

961964
return self.counters_db
962-
965+
963966
def get_config_db(self):
964967
if not self.config_db:
965968
self.config_db = dvs_db.DVSDatabase(self.CONFIG_DB_ID, self.redis_sock)
966969

967970
return self.config_db
968-
971+
969972
def get_flex_db(self):
970973
if not self.flex_db:
971974
self.flex_db = dvs_db.DVSDatabase(self.FLEX_COUNTER_DB_ID, self.redis_sock)
972975

973976
return self.flex_db
974-
977+
975978
def get_state_db(self):
976979
if not self.state_db:
977980
self.state_db = dvs_db.DVSDatabase(self.STATE_DB_ID, self.redis_sock)
978981

979982
return self.state_db
980983

984+
def get_dvs_acl(self):
985+
if not self.dvs_acl:
986+
self.dvs_acl = dvs_acl.DVSAcl(self.get_asic_db(),
987+
self.get_config_db(),
988+
self.get_state_db(),
989+
self.get_counters_db())
990+
return self.dvs_acl
991+
981992
@pytest.yield_fixture(scope="module")
982993
def dvs(request):
983994
name = request.config.getoption("--dvsname")
@@ -998,6 +1009,13 @@ def testlog(request, dvs):
9981009
yield testlog
9991010
dvs.runcmd("logger === finish test %s ===" % request.node.name)
10001011

1012+
@pytest.yield_fixture(scope="class")
1013+
def dvs_acl_manager(request, dvs):
1014+
request.cls.dvs_acl = dvs_acl.DVSAcl(dvs.get_asic_db(),
1015+
dvs.get_config_db(),
1016+
dvs.get_state_db(),
1017+
dvs.get_counters_db())
1018+
10011019
##################### DPB fixtures ###########################################
10021020
@pytest.yield_fixture(scope="module")
10031021
def create_dpb_config_file(dvs):

tests/dvslib/dvs_acl.py

+231
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
class DVSAcl(object):
2+
def __init__(self, adb, cdb, sdb, cntrdb):
3+
self.asic_db = adb
4+
self.config_db = cdb
5+
self.state_db = sdb
6+
self.counters_db = cntrdb
7+
8+
def create_acl_table(self, table_name, table_type, ports, stage=None):
9+
table_attrs = {
10+
"policy_desc": "DVS acl table test",
11+
"type": table_type,
12+
"ports": ",".join(ports)
13+
}
14+
15+
if stage:
16+
table_attrs["stage"] = stage
17+
18+
self.config_db.create_entry("ACL_TABLE", table_name, table_attrs)
19+
20+
def update_acl_table(self, acl_table_name, ports):
21+
table_attrs = {
22+
"ports": ",".join(ports)
23+
}
24+
self.config_db.update_entry("ACL_TABLE", acl_table_name, table_attrs)
25+
26+
def remove_acl_table(self, table_name):
27+
self.config_db.delete_entry("ACL_TABLE", table_name)
28+
29+
def get_acl_table_group_ids(self, expt):
30+
acl_table_groups = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP", expt)
31+
return acl_table_groups
32+
33+
def get_acl_table_ids(self, expt=1):
34+
num_keys = len(self.asic_db.default_acl_tables) + expt
35+
keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", num_keys)
36+
for k in self.asic_db.default_acl_tables:
37+
assert k in keys
38+
39+
acl_tables = [k for k in keys if k not in self.asic_db.default_acl_tables]
40+
41+
return acl_tables
42+
43+
def get_acl_table_id(self):
44+
acl_tables = self.get_acl_table_ids()
45+
return acl_tables[0]
46+
47+
def verify_acl_table_count(self, expt):
48+
num_keys = len(self.asic_db.default_acl_tables) + expt
49+
keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", num_keys)
50+
for k in self.asic_db.default_acl_tables:
51+
assert k in keys
52+
53+
acl_tables = [k for k in keys if k not in self.asic_db.default_acl_tables]
54+
55+
assert len(acl_tables) == expt
56+
57+
def verify_acl_group_num(self, expt):
58+
acl_table_groups = self.get_acl_table_group_ids(expt)
59+
60+
for group in acl_table_groups:
61+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP", group)
62+
for k, v in fvs.items():
63+
if k == "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE":
64+
assert v == "SAI_ACL_STAGE_INGRESS"
65+
elif k == "SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST":
66+
assert v == "1:SAI_ACL_BIND_POINT_TYPE_PORT"
67+
elif k == "SAI_ACL_TABLE_GROUP_ATTR_TYPE":
68+
assert v == "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL"
69+
else:
70+
assert False
71+
72+
def verify_acl_table_group_member(self, acl_table_group_id, acl_table_id):
73+
self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP", acl_table_group_id)
74+
self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", acl_table_id)
75+
members = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER")
76+
for m in members:
77+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER", m)
78+
fvs = dict(fvs)
79+
if (fvs.pop("SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID") == acl_table_group_id and
80+
fvs.pop("SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID") == acl_table_id) :
81+
return True
82+
assert False
83+
84+
def verify_acl_group_member(self, acl_group_ids, acl_table_id):
85+
members = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER", len(acl_group_ids))
86+
87+
member_groups = []
88+
for member in members:
89+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER", member)
90+
for k, v in fvs.items():
91+
if k == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID":
92+
assert v in acl_group_ids
93+
member_groups.append(v)
94+
elif k == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID":
95+
assert v == acl_table_id
96+
elif k == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY":
97+
assert True
98+
else:
99+
assert False
100+
101+
assert set(member_groups) == set(acl_group_ids)
102+
103+
def verify_acl_table_ports_binding(self, ports, acl_table_id):
104+
for p in ports:
105+
# TBD: Introduce new API in dvs_databse.py to read by field
106+
fvs = self.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "")
107+
fvs = dict(fvs)
108+
port_oid = fvs.pop(p)
109+
#port_oid = self.counters_db.hget_entry("COUNTERS_PORT_NAME_MAP", "", p)
110+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid)
111+
fvs = dict(fvs)
112+
acl_table_group_id = fvs.pop("SAI_PORT_ATTR_INGRESS_ACL")
113+
self.verify_acl_table_group_member(acl_table_group_id, acl_table_id)
114+
115+
def verify_acl_port_binding(self, bind_ports):
116+
acl_table_groups = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP", len(bind_ports))
117+
118+
port_groups = []
119+
for port in [self.asic_db.port_name_map[p] for p in bind_ports]:
120+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port)
121+
acl_table_group = fvs.pop("SAI_PORT_ATTR_INGRESS_ACL", None)
122+
assert acl_table_group in acl_table_groups
123+
port_groups.append(acl_table_group)
124+
125+
assert len(port_groups) == len(bind_ports)
126+
assert set(port_groups) == set(acl_table_groups)
127+
128+
def create_acl_rule(self, table_name, rule_name, qualifiers, action="FORWARD", priority="2020"):
129+
fvs = {
130+
"priority": priority,
131+
"PACKET_ACTION": action
132+
}
133+
134+
for k, v in qualifiers.items():
135+
fvs[k] = v
136+
137+
self.config_db.create_entry("ACL_RULE", "{}|{}".format(table_name, rule_name), fvs)
138+
139+
def remove_acl_rule(self, table_name, rule_name):
140+
self.config_db.delete_entry("ACL_RULE", "{}|{}".format(table_name, rule_name))
141+
142+
def get_acl_rule_id(self):
143+
num_keys = len(self.asic_db.default_acl_entries) + 1
144+
keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", num_keys)
145+
146+
acl_entries = [k for k in keys if k not in self.asic_db.default_acl_entries]
147+
return acl_entries[0]
148+
149+
def verify_no_acl_rules(self):
150+
num_keys = len(self.asic_db.default_acl_entries)
151+
keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", num_keys)
152+
assert set(keys) == set(self.asic_db.default_acl_entries)
153+
154+
def verify_acl_rule(self, qualifiers, action="FORWARD", priority="2020"):
155+
acl_rule_id = self.get_acl_rule_id()
156+
157+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", acl_rule_id)
158+
self._check_acl_entry(fvs, qualifiers, action, priority)
159+
160+
def verify_acl_rule_set(self, priorities, in_actions, expected):
161+
num_keys = len(self.asic_db.default_acl_entries) + len(priorities)
162+
keys = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", num_keys)
163+
164+
acl_entries = [k for k in keys if k not in self.asic_db.default_acl_entries]
165+
for entry in acl_entries:
166+
rule = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", entry)
167+
priority = rule.get("SAI_ACL_ENTRY_ATTR_PRIORITY", None)
168+
assert priority in priorities
169+
self._check_acl_entry(rule, expected[priority],
170+
action=in_actions[priority], priority=priority)
171+
172+
def _check_acl_entry(self, entry, qualifiers, action, priority):
173+
acl_table_id = self.get_acl_table_id()
174+
175+
for k, v in entry.items():
176+
if k == "SAI_ACL_ENTRY_ATTR_TABLE_ID":
177+
assert v == acl_table_id
178+
elif k == "SAI_ACL_ENTRY_ATTR_ADMIN_STATE":
179+
assert v == "true"
180+
elif k == "SAI_ACL_ENTRY_ATTR_PRIORITY":
181+
assert v == priority
182+
elif k == "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER":
183+
assert True
184+
elif k == "SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION":
185+
if action == "FORWARD":
186+
assert v == "SAI_PACKET_ACTION_FORWARD"
187+
elif action == "DROP":
188+
assert v == "SAI_PACKET_ACTION_DROP"
189+
else:
190+
assert False
191+
elif k == "SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT":
192+
if "REDIRECT" not in action:
193+
assert False
194+
elif k in qualifiers:
195+
assert qualifiers[k](v)
196+
else:
197+
assert False
198+
199+
def get_simple_qualifier_comparator(self, expected_qualifier):
200+
def _match_qualifier(sai_qualifier):
201+
return expected_qualifier == sai_qualifier
202+
203+
return _match_qualifier
204+
205+
def get_port_list_comparator(self, expected_ports):
206+
def _match_port_list(sai_port_list):
207+
if not sai_port_list.startswith("{}:".format(len(expected_ports))):
208+
return False
209+
for port in expected_ports:
210+
if self.asic_db.port_name_map[port] not in sai_port_list:
211+
return False
212+
213+
return True
214+
215+
return _match_port_list
216+
217+
def get_acl_range_comparator(self, expected_type, expected_ports):
218+
def _match_acl_range(sai_acl_range):
219+
range_id = sai_acl_range.split(":", 1)[1]
220+
fvs = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_ACL_RANGE", range_id)
221+
for k, v in fvs.items():
222+
if k == "SAI_ACL_RANGE_ATTR_TYPE" and v == expected_type:
223+
continue
224+
elif k == "SAI_ACL_RANGE_ATTR_LIMIT" and v == expected_ports:
225+
continue
226+
else:
227+
return False
228+
229+
return True
230+
231+
return _match_acl_range

tests/dvslib/dvs_database.py

+14
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ def create_entry(self, table_name, key, entry):
4343
formatted_entry = swsscommon.FieldValuePairs(entry.items())
4444
table.set(key, formatted_entry)
4545

46+
def update_entry(self, table_name, key, entry):
47+
"""
48+
Updates entries of an existing key in the specified table.
49+
50+
Args:
51+
table_name (str): The name of the table.
52+
key (str): The key that needs to be updated.
53+
entry (Dict[str, str]): A set of key-value pairs to be updated.
54+
"""
55+
56+
table = swsscommon.Table(self.db_connection, table_name)
57+
formatted_entry = swsscommon.FieldValuePairs(entry.items())
58+
table.set(key, formatted_entry)
59+
4660
def get_entry(self, table_name, key):
4761
"""
4862
Gets the entry stored at `key` in the specified table.

tests/port_dpb.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def write_to_config_db(self):
154154
("speed", speed_str),
155155
("index", index_str)])
156156
self._cfg_db_ptbl.set(self.get_name(), fvs)
157-
time.sleep(1)
157+
time.sleep(2)
158158

159159
def get_fvs_dict(self, fvs):
160160
fvs_dict = {}
@@ -221,8 +221,6 @@ def breakin(self, dvs, port_names):
221221
#dvs.runcmd("ip link delete " + cp.get_name())
222222
#print "Deleted child ports:%s from config DB"%port_names
223223

224-
time.sleep(6)
225-
226224
for cp in child_ports:
227225
assert(cp.exists_in_config_db() == False)
228226
for cp in child_ports:
@@ -235,7 +233,6 @@ def breakin(self, dvs, port_names):
235233
p.port_merge(child_ports)
236234
p.write_to_config_db()
237235
#print "Added port:%s to config DB"%p.get_name()
238-
time.sleep(2)
239236

240237
p.verify_config_db()
241238
#print "Config DB verification passed!"
@@ -254,7 +251,6 @@ def create_child_ports(self, dvs, p, num_child_ports):
254251
cp.write_to_config_db()
255252
child_port_names.append(cp.get_name())
256253
#print "Added child ports:%s to config DB"%child_port_names
257-
time.sleep(6)
258254

259255
for cp in child_ports:
260256
assert(cp.exists_in_config_db() == True)
@@ -279,7 +275,7 @@ def breakout(self, dvs, port_name, num_child_ports):
279275
# TBD, need vs lib to support hostif removal
280276
#dvs.runcmd("ip link delete " + p.get_name())
281277
#print "Deleted port:%s from config DB"%port_name
282-
time.sleep(6)
278+
time.sleep(2)
283279

284280
# Verify port is deleted from all DBs
285281
assert(p.exists_in_config_db() == False)

0 commit comments

Comments
 (0)