Skip to content

Commit 2f53bd4

Browse files
[dump] implement ACL modules (sonic-net#2153)
- What I did Implemented ACL dump modules - How I did it Added dump plugins for acl_rule and acl_table. Added UT for coverage. Implemented according to sonic-net/SONiC#983 - How to verify it Run UT, run on the switch mannually. Signed-off-by: Stepan Blyschak <[email protected]>
1 parent 494dd62 commit 2f53bd4

File tree

9 files changed

+475
-8
lines changed

9 files changed

+475
-8
lines changed

dump/main.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from tabulate import tabulate
77
from sonic_py_common import multi_asic
88
from utilities_common.constants import DEFAULT_NAMESPACE
9+
from swsscommon.swsscommon import ConfigDBConnector
910
from dump.match_infra import RedisSource, JsonSource, ConnectionPool
1011
from dump import plugins
1112

@@ -82,7 +83,10 @@ def state(ctx, module, identifier, db, table, key_map, verbose, namespace):
8283
params['namespace'] = namespace
8384
for arg in ids:
8485
params[plugins.dump_modules[module].ARG_NAME] = arg
85-
collected_info[arg] = obj.execute(params)
86+
try:
87+
collected_info[arg] = obj.execute(params)
88+
except ValueError as err:
89+
click.fail(f"Failed to execute plugin: {err}")
8690

8791
if len(db) > 0:
8892
collected_info = filter_out_dbs(db, collected_info)
@@ -151,7 +155,7 @@ def populate_fv(info, module, namespace):
151155
db_cfg_file = JsonSource()
152156
db_conn = ConnectionPool().initialize_connector(namespace)
153157
for db_name in all_dbs:
154-
if db_name is "CONFIG_FILE":
158+
if db_name == "CONFIG_FILE":
155159
db_cfg_file.connect(plugins.dump_modules[module].CONFIG_FILE, namespace)
156160
else:
157161
db_conn.connect(db_name)
@@ -164,7 +168,7 @@ def populate_fv(info, module, namespace):
164168
final_info[id][db_name]["keys"] = []
165169
final_info[id][db_name]["tables_not_found"] = info[id][db_name]["tables_not_found"]
166170
for key in info[id][db_name]["keys"]:
167-
if db_name is "CONFIG_FILE":
171+
if db_name == "CONFIG_FILE":
168172
fv = db_cfg_file.get(db_name, key)
169173
else:
170174
fv = db_conn.get_all(db_name, key)
@@ -174,9 +178,13 @@ def populate_fv(info, module, namespace):
174178

175179

176180
def get_dict_str(key_obj):
181+
conn = ConfigDBConnector()
177182
table = []
178-
for pair in key_obj.items():
179-
table.append(list(pair))
183+
key_obj = conn.raw_to_typed(key_obj)
184+
for field, value in key_obj.items():
185+
if isinstance(value, list):
186+
value = "\n".join(value)
187+
table.append((field, value))
180188
return tabulate(table, headers=["field", "value"], tablefmt="psql")
181189

182190

dump/match_helper.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def fetch_vlan_oid(match_engine, vlan_name, ns):
4444
vlan_num = int(vlan_name[4:])
4545

4646
# Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:*" in which SAI_VLAN_ATTR_VLAN_ID = vlan_num
47-
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID",
47+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID",
4848
value=str(vlan_num), ns=ns)
4949
ret = match_engine.fetch(req)
5050
vlan_oid = ""
@@ -100,3 +100,15 @@ def fetch_lag_oid(match_engine, lag_name, ns):
100100
lag_oids matched {}".format(lag_name, lag_type_oids), lag_type_oids[-1])
101101
lag_type_oid = lag_type_oids[-1]
102102
return lag_type_oid
103+
104+
# ACL helpers
105+
106+
def fetch_acl_counter_oid(match_engine, acl_table_name, acl_rule_name, ns):
107+
"""
108+
Fetch ACL counter OID from COUNTERS DB for a particular rule
109+
"""
110+
counters_db = match_engine.get_redis_source_adapter()
111+
counters_db.connect("COUNTERS_DB", ns)
112+
counters = counters_db.hgetall("COUNTERS_DB", "ACL_COUNTER_RULE_MAP")
113+
counter_oid = counters.get(f"{acl_table_name}{counters_db.get_separator('COUNTERS_DB')}{acl_rule_name}")
114+
return counter_oid

dump/match_infra.py

+20-2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def hget(self, db, key, field):
154154
def get_separator(self, db):
155155
return ""
156156

157+
@abstractmethod
158+
def hgetall(self, db, key):
159+
raise NotImplementedError
160+
157161

158162
class RedisSource(SourceAdapter):
159163
""" Concrete Adaptor Class for connecting to Redis Data Sources """
@@ -182,6 +186,9 @@ def get(self, db, key):
182186
def hget(self, db, key, field):
183187
return self.conn.get(db, key, field)
184188

189+
def hgetall(self, db, key):
190+
return self.conn.get_all(db, key)
191+
185192

186193
class JsonSource(SourceAdapter):
187194
""" Concrete Adaptor Class for connecting to JSON Data Sources """
@@ -219,6 +226,11 @@ def hget(self, db, key, field):
219226
table, key = key.split(sep, 1)
220227
return self.json_data.get(table, "").get(key, "").get(field, "")
221228

229+
def hgetall(self, db, key):
230+
sep = self.get_separator(db)
231+
table, key = key.split(sep, 1)
232+
return self.json_data.get(table, {}).get(key)
233+
222234

223235
class ConnectionPool:
224236
""" Caches SonicV2Connector objects for effective reuse """
@@ -271,15 +283,21 @@ def __init__(self, pool=None):
271283
def clear_cache(self, ns):
272284
self.conn_pool(ns)
273285

286+
def get_redis_source_adapter(self):
287+
return RedisSource(self.conn_pool)
288+
289+
def get_json_source_adapter(self):
290+
return JsonSource()
291+
274292
def __get_source_adapter(self, req):
275293
src = None
276294
d_src = ""
277295
if req.db:
278296
d_src = req.db
279-
src = RedisSource(self.conn_pool)
297+
src = self.get_redis_source_adapter()
280298
else:
281299
d_src = req.file
282-
src = JsonSource()
300+
src = self.get_json_source_adapter()
283301
return d_src, src
284302

285303
def __create_template(self):

dump/plugins/acl_rule.py

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from dump.helper import create_template_dict
2+
from dump.match_infra import MatchRequest
3+
from swsscommon.swsscommon import SonicDBConfig
4+
5+
from dump.match_helper import fetch_acl_counter_oid
6+
from .executor import Executor
7+
8+
9+
CFG_DB_SEPARATOR = SonicDBConfig.getSeparator("CONFIG_DB")
10+
ASIC_DB_SEPARATOR = SonicDBConfig.getSeparator("ASIC_DB")
11+
12+
13+
class Acl_Rule(Executor):
14+
"""
15+
Debug Dump Plugin for ACL Rule Module
16+
"""
17+
ARG_NAME = "acl_rule_name"
18+
19+
def __init__(self, match_engine=None):
20+
super().__init__(match_engine)
21+
22+
def get_all_args(self, ns=""):
23+
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE", key_pattern="*", ns=ns)
24+
ret = self.match_engine.fetch(req)
25+
acl_rules = ret["keys"]
26+
return [key.split(CFG_DB_SEPARATOR, 1)[-1] for key in acl_rules]
27+
28+
def execute(self, params):
29+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "ASIC_DB"])
30+
31+
try:
32+
acl_table_name, acl_rule_name = params[self.ARG_NAME].split(CFG_DB_SEPARATOR, 1)
33+
except ValueError:
34+
raise ValueError(f"Invalid rule name passed {params[self.ARG_NAME]}")
35+
36+
self.ns = params["namespace"]
37+
self.init_acl_rule_config_info(acl_table_name, acl_rule_name)
38+
self.init_acl_rule_asic_info(acl_table_name, acl_rule_name)
39+
return self.ret_temp
40+
41+
def init_acl_rule_config_info(self, acl_table_name, acl_rule_name):
42+
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE",
43+
key_pattern=CFG_DB_SEPARATOR.join([acl_table_name, acl_rule_name]), ns=self.ns)
44+
ret = self.match_engine.fetch(req)
45+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
46+
47+
def init_acl_rule_asic_info(self, acl_table_name, acl_rule_name):
48+
counter_oid = fetch_acl_counter_oid(self.match_engine, acl_table_name, acl_rule_name, self.ns)
49+
if not counter_oid:
50+
return
51+
52+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_COUNTER"]),
53+
key_pattern=counter_oid, return_fields=["SAI_ACL_COUNTER_ATTR_TABLE_ID"], ns=self.ns)
54+
ret = self.match_engine.fetch(req)
55+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
56+
57+
return_values = ret["return_values"]
58+
counter_object = return_values.get(ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_COUNTER", counter_oid]), {})
59+
table_oid = counter_object.get("SAI_ACL_COUNTER_ATTR_TABLE_ID")
60+
if not table_oid:
61+
raise Exception("Invalid counter object without table OID in ASIC_DB")
62+
63+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_ENTRY"]), key_pattern="*",
64+
field="SAI_ACL_ENTRY_ATTR_TABLE_ID", value=table_oid,
65+
return_fields=["SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE"], ns=self.ns)
66+
ret = self.match_engine.fetch(req)
67+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
68+
69+
range_oids = set()
70+
for _, entry in ret["return_values"].items():
71+
range_attr_value = entry.get("SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE")
72+
if not range_attr_value:
73+
continue
74+
ranges_attr_value = range_attr_value.split(ASIC_DB_SEPARATOR, 1)
75+
if len(range_attr_value) < 2:
76+
raise Exception("Invalid SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE field format")
77+
for oid in ranges_attr_value[1].split(','):
78+
range_oids.add(oid)
79+
80+
for range_oid in range_oids:
81+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_RANGE"]),
82+
key_pattern=range_oid, ns=self.ns)
83+
ret = self.match_engine.fetch(req)
84+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

dump/plugins/acl_table.py

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from dump.helper import create_template_dict
2+
from dump.match_infra import MatchRequest
3+
from swsscommon.swsscommon import SonicDBConfig
4+
5+
from dump.match_helper import fetch_acl_counter_oid
6+
from .executor import Executor
7+
8+
9+
CFG_DB_SEPARATOR = SonicDBConfig.getSeparator("CONFIG_DB")
10+
ASIC_DB_SEPARATOR = SonicDBConfig.getSeparator("ASIC_DB")
11+
12+
13+
class Acl_Table(Executor):
14+
"""
15+
Debug Dump Plugin for ACL Table Module
16+
"""
17+
ARG_NAME = "acl_table_name"
18+
19+
def __init__(self, match_engine=None):
20+
super().__init__(match_engine)
21+
22+
def get_all_args(self, ns=""):
23+
req = MatchRequest(db="CONFIG_DB", table="ACL_TABLE", key_pattern="*", ns=ns)
24+
ret = self.match_engine.fetch(req)
25+
acl_tables = ret["keys"]
26+
return [key.split(CFG_DB_SEPARATOR)[-1] for key in acl_tables]
27+
28+
def execute(self, params):
29+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "ASIC_DB"])
30+
acl_table_name = params[self.ARG_NAME]
31+
self.ns = params["namespace"]
32+
self.init_acl_table_config_info(acl_table_name)
33+
self.init_acl_table_asic_info(acl_table_name)
34+
return self.ret_temp
35+
36+
def init_acl_table_config_info(self, acl_table_name):
37+
req = MatchRequest(db="CONFIG_DB", table="ACL_TABLE", key_pattern=acl_table_name, return_fields=["type"], ns=self.ns)
38+
ret = self.match_engine.fetch(req)
39+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
40+
41+
# Find corresponding ACL table type in CONFIG DB
42+
return_values = ret["return_values"]
43+
acl_table_type_name = return_values.get(CFG_DB_SEPARATOR.join(["ACL_TABLE", acl_table_name]), {}).get("type")
44+
req = MatchRequest(db="CONFIG_DB", table="ACL_TABLE_TYPE", key_pattern=acl_table_type_name, ns=self.ns)
45+
ret = self.match_engine.fetch(req)
46+
# If not found don't add it to the table, it might be a default table type
47+
if ret["keys"]:
48+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
49+
50+
def init_acl_table_asic_info(self, acl_table_name):
51+
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE", key_pattern=CFG_DB_SEPARATOR.join([acl_table_name, "*"]), ns=self.ns)
52+
ret = self.match_engine.fetch(req)
53+
acl_rules = ret["keys"]
54+
if not acl_rules:
55+
return
56+
acl_rule_name = acl_rules[0].split(CFG_DB_SEPARATOR)[-1]
57+
58+
counter_oid = fetch_acl_counter_oid(self.match_engine, acl_table_name, acl_rule_name, self.ns)
59+
if not counter_oid:
60+
return
61+
62+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_COUNTER"]),
63+
key_pattern=counter_oid, return_fields=["SAI_ACL_COUNTER_ATTR_TABLE_ID"], ns=self.ns)
64+
ret = self.match_engine.fetch(req)
65+
66+
return_values = ret["return_values"]
67+
counter_object = return_values.get(ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_COUNTER", counter_oid]), {})
68+
table_oid = counter_object.get("SAI_ACL_COUNTER_ATTR_TABLE_ID")
69+
if not table_oid:
70+
raise Exception("Invalid counter object without table OID in ASIC_DB")
71+
72+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_TABLE"]),
73+
key_pattern=table_oid, ns=self.ns)
74+
ret = self.match_engine.fetch(req)
75+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
76+
77+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER"]),
78+
key_pattern="*", field="SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID",
79+
value=table_oid, return_fields=["SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID"], ns=self.ns)
80+
ret = self.match_engine.fetch(req)
81+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
82+
83+
group_oids = set()
84+
for _, entry in ret["return_values"].items():
85+
group_oids.add(entry.get("SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID"))
86+
87+
for group_oid in group_oids:
88+
req = MatchRequest(db="ASIC_DB", table=ASIC_DB_SEPARATOR.join(["ASIC_STATE", "SAI_OBJECT_TYPE_ACL_TABLE_GROUP"]),
89+
key_pattern=group_oid, ns=self.ns)
90+
ret = self.match_engine.fetch(req)
91+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

tests/dump_input/acl/asic_db.json

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE:oid:0x7000000000600": {
3+
"SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": "2:SAI_ACL_BIND_POINT_TYPE_PORT,SAI_ACL_BIND_POINT_TYPE_LAG",
4+
"SAI_ACL_TABLE_ATTR_ACL_STAGE": "SAI_ACL_STAGE_INGRESS",
5+
"SAI_ACL_TABLE_ATTR_FIELD_ACL_ETHER_TYPE": "true"
6+
},
7+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER:oid:0xc000000000601": {
8+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": "oid:0xb0000000005f5",
9+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": "oid:0x7000000000600",
10+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": "100"
11+
},
12+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER:oid:0xc000000000602": {
13+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": "oid:0xb0000000005f7",
14+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": "oid:0x7000000000600",
15+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": "100"
16+
},
17+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP:oid:0xb0000000005f5": {
18+
"SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST": "1:SAI_ACL_BIND_POINT_TYPE_PORT",
19+
"SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE": "SAI_ACL_STAGE_INGRESS",
20+
"SAI_ACL_TABLE_GROUP_ATTR_TYPE": "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL"
21+
},
22+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP:oid:0xb0000000005f7": {
23+
"SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST": "1:SAI_ACL_BIND_POINT_TYPE_PORT",
24+
"SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE": "SAI_ACL_STAGE_INGRESS",
25+
"SAI_ACL_TABLE_GROUP_ATTR_TYPE": "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL"
26+
},
27+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000609": {
28+
"SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": "oid:0x9000000000606",
29+
"SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION": "SAI_PACKET_ACTION_FORWARD",
30+
"SAI_ACL_ENTRY_ATTR_ADMIN_STATE": "true",
31+
"SAI_ACL_ENTRY_ATTR_PRIORITY": "9995",
32+
"SAI_ACL_ENTRY_ATTR_TABLE_ID": "oid:0x7000000000600"
33+
},
34+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_COUNTER:oid:0x9000000000606": {
35+
"SAI_ACL_COUNTER_ATTR_TABLE_ID": "oid:0x7000000000600",
36+
"SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT": "true",
37+
"SAI_ACL_COUNTER_ATTR_ENABLE_BYTES_COUNT": "true"
38+
},
39+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE:oid:0x7100000000600": {
40+
"SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": "2:SAI_ACL_BIND_POINT_TYPE_PORT,SAI_ACL_BIND_POINT_TYPE_LAG",
41+
"SAI_ACL_TABLE_ATTR_ACL_STAGE": "SAI_ACL_STAGE_INGRESS",
42+
"SAI_ACL_TABLE_ATTR_FIELD_ACL_ETHER_TYPE": "true"
43+
},
44+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER:oid:0xc100000000601": {
45+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": "oid:0xb0000000005f5",
46+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": "oid:0x7100000000600",
47+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": "100"
48+
},
49+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER:oid:0xc100000000602": {
50+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": "oid:0xb0000000005f7",
51+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": "oid:0x7100000000600",
52+
"SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": "100"
53+
},
54+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8100000000609": {
55+
"SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": "oid:0x9100000000606",
56+
"SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION": "SAI_PACKET_ACTION_FORWARD",
57+
"SAI_ACL_ENTRY_ATTR_ADMIN_STATE": "true",
58+
"SAI_ACL_ENTRY_ATTR_PRIORITY": "9995",
59+
"SAI_ACL_ENTRY_ATTR_TABLE_ID": "oid:0x7100000000600",
60+
"SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": "2:oid:0xa100000000607,oid:0xa100000000608"
61+
},
62+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_COUNTER:oid:0x9100000000606": {
63+
"SAI_ACL_COUNTER_ATTR_TABLE_ID": "oid:0x7100000000600",
64+
"SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT": "true",
65+
"SAI_ACL_COUNTER_ATTR_ENABLE_BYTES_COUNT": "true"
66+
},
67+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_RANGE:oid:0xa100000000607": {
68+
"SAI_ACL_RANGE_ATTR_LIMIT": "90,95",
69+
"SAI_ACL_RANGE_ATTR_TYPE": "SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE"
70+
},
71+
"ASIC_STATE:SAI_OBJECT_TYPE_ACL_RANGE:oid:0xa100000000608": {
72+
"SAI_ACL_RANGE_ATTR_LIMIT": "90,95",
73+
"SAI_ACL_RANGE_ATTR_TYPE": "SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE"
74+
}
75+
}

0 commit comments

Comments
 (0)