Skip to content
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

[ACL] Display rule and table info written to APP DB #3713

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions acl_loader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ class AclLoader(object):
ACL_TABLE = "ACL_TABLE"
ACL_RULE = "ACL_RULE"
CFG_ACL_TABLE = "ACL_TABLE"
APPL_ACL_TABLE = "ACL_TABLE_TABLE"
STATE_ACL_TABLE = "ACL_TABLE_TABLE"
CFG_ACL_RULE = "ACL_RULE"
APPL_ACL_RULE = "ACL_RULE_TABLE"
STATE_ACL_RULE = "ACL_RULE_TABLE"
ACL_TABLE_TYPE_MIRROR = "MIRROR"
ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE"
Expand Down Expand Up @@ -135,6 +137,8 @@ def __init__(self):
self.configdb.connect()
self.statedb = SonicV2Connector(host="127.0.0.1")
self.statedb.connect(self.statedb.STATE_DB)
self.appldb = SonicV2Connector(host="127.0.0.1")
self.appldb.connect(self.statedb.APPL_DB)

# For multi-npu architecture we will have both global and per front asic namespace.
# Global namespace will be used for Control plane ACL which are via IPTables.
Expand Down Expand Up @@ -165,8 +169,8 @@ def __init__(self):
self.read_rules_info()
self.read_sessions_info()
self.read_policers_info()
self.acl_table_status = self.read_acl_object_status_info(self.CFG_ACL_TABLE, self.STATE_ACL_TABLE)
self.acl_rule_status = self.read_acl_object_status_info(self.CFG_ACL_RULE, self.STATE_ACL_RULE)
self.acl_table_status = self.read_acl_object_status_info(self.tables_db_info.keys(), self.STATE_ACL_TABLE)
self.acl_rule_status = self.read_acl_object_status_info(self.rules_db_info.keys(), self.STATE_ACL_RULE)

def read_tables_info(self):
"""
Expand Down Expand Up @@ -199,16 +203,51 @@ def read_tables_info(self):
self.tables_db_info[table]['ports'] += entry.get(
'ports', [])

if self.per_npu_configdb:
# Note: Ability to read table information from APPL_DB is not yet supported for masic devices
return

appl_db_keys = self.appldb.keys(self.appldb.APPL_DB, "{}:*".format(self.APPL_ACL_TABLE))
if not appl_db_keys:
return

for app_acl_tbl in appl_db_keys:
key = app_acl_tbl.split(":")[-1]
if key in self.tables_db_info:
# Shouldn't be hit, table is either programmed to APPL or CONFIG DB
continue
self.tables_db_info[key] = dict()
for f, v in self.appldb.get_all(self.appldb.APPL_DB, app_acl_tbl).items():
if f.lower() == "ports":
v = v.split(",")
self.tables_db_info[key][f.lower()] = v
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved

def get_tables_db_info(self):
return self.tables_db_info

def read_rules_info(self):
"""
Read ACL_RULE table from configuration database
Read ACL_RULE table from CFG_DB and APPL_DB database
:return:
"""
self.rules_db_info = self.configdb.get_table(self.ACL_RULE)

if self.per_npu_configdb:
# Note: Ability to read table information from APPL_DB is not yet supported for masic devices
return

# Read rule information from APPL_DB
appl_db_keys = self.appldb.keys(self.appldb.APPL_DB, "{}:*".format(self.APPL_ACL_RULE))
if not appl_db_keys:
return

for app_acl_rule in appl_db_keys:
_, tid, rid = app_acl_rule.split(":")
if (tid, rid) in self.rules_db_info:
# Shouldn't be hit, table is either programmed to APPL or CONFIG DB
continue
self.rules_db_info[(tid, rid)] = self.appldb.get_all(self.appldb.APPL_DB, app_acl_rule)

def get_rules_db_info(self):
return self.rules_db_info

Expand Down Expand Up @@ -259,16 +298,10 @@ def read_sessions_info(self):
self.sessions_db_info[key]["status"] = state_db_info.get("status", "inactive") if state_db_info else "error"
self.sessions_db_info[key]["monitor_port"] = state_db_info.get("monitor_port", "") if state_db_info else ""

def read_acl_object_status_info(self, cfg_db_table_name, state_db_table_name):
def read_acl_object_status_info(self, keys, state_db_table_name):
"""
Read ACL_TABLE status or ACL_RULE status from STATE_DB
"""
if self.per_npu_configdb:
namespace_configdb = list(self.per_npu_configdb.values())[0]
keys = namespace_configdb.get_table(cfg_db_table_name).keys()
else:
keys = self.configdb.get_table(cfg_db_table_name).keys()

status = {}
for key in keys:
# For ACL_RULE, the key is (acl_table_name, acl_rule_name)
Expand Down Expand Up @@ -922,19 +955,19 @@ def show_table(self, table_name):
status = self.acl_table_status[key]['status']
else:
status = 'N/A'
if val["type"] == AclLoader.ACL_TABLE_TYPE_CTRLPLANE:
if val.get("type", "N/A") == AclLoader.ACL_TABLE_TYPE_CTRLPLANE:
services = natsorted(val["services"])
data.append([key, val["type"], services[0], val["policy_desc"], stage, status])
data.append([key, val.get("type", "N/A"), services[0], val.get("policy_desc", ""), stage, status])

if len(services) > 1:
for service in services[1:]:
data.append(["", "", service, "", "", ""])
else:
if not val["ports"]:
data.append([key, val["type"], "", val["policy_desc"], stage, status])
if not val.get("ports", []):
data.append([key, val["type"], "", val.get("policy_desc", ""), stage, status])
else:
ports = natsorted(val["ports"])
data.append([key, val["type"], ports[0], val["policy_desc"], stage, status])
data.append([key, val["type"], ports[0], val.get("policy_desc", ""), stage, status])

if len(ports) > 1:
for port in ports[1:]:
Expand Down
31 changes: 25 additions & 6 deletions dump/plugins/acl_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

CFG_DB_SEPARATOR = SonicDBConfig.getSeparator("CONFIG_DB")
ASIC_DB_SEPARATOR = SonicDBConfig.getSeparator("ASIC_DB")
APP_DB_SEPARATOR = SonicDBConfig.getSeparator("APPL_DB")
APP_RULE_NAME = "ACL_RULE_TABLE"


class Acl_Rule(Executor):
Expand All @@ -22,27 +24,44 @@ def __init__(self, match_engine=None):
def get_all_args(self, ns=""):
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE", key_pattern="*", ns=ns)
ret = self.match_engine.fetch(req)
acl_rules = ret["keys"]
return [key.split(CFG_DB_SEPARATOR, 1)[-1] for key in acl_rules]
req_app = MatchRequest(db="APPL_DB", table=APP_RULE_NAME, key_pattern="*", ns=ns)
ret_app = self.match_engine.fetch(req_app)
return [f"{CFG_DB_SEPARATOR}".join(key.split(CFG_DB_SEPARATOR)[1:]) for key in ret.get("keys")] + \
[f"{APP_DB_SEPARATOR}".join(key.split(APP_DB_SEPARATOR)[1:]) for key in ret_app.get("keys")]

def execute(self, params):
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "ASIC_DB"])

self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"])
invalid = False
try:
acl_table_name, acl_rule_name = params[self.ARG_NAME].split(CFG_DB_SEPARATOR, 1)
except ValueError:
raise ValueError(f"Invalid rule name passed {params[self.ARG_NAME]}")
invalid = True

if invalid:
try:
acl_table_name, acl_rule_name = params[self.ARG_NAME].split(APP_DB_SEPARATOR, 1)
except ValueError:
raise ValueError(f"Invalid rule name passed {params[self.ARG_NAME]}")

self.ns = params["namespace"]
self.init_acl_rule_config_info(acl_table_name, acl_rule_name)
self.init_acl_rule_appl_info(acl_table_name, acl_rule_name)
self.init_acl_rule_asic_info(acl_table_name, acl_rule_name)
return self.ret_temp

def init_acl_rule_config_info(self, acl_table_name, acl_rule_name):
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE",
key_pattern=CFG_DB_SEPARATOR.join([acl_table_name, acl_rule_name]), ns=self.ns)
ret = self.match_engine.fetch(req)
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_acl_rule_appl_info(self, acl_table_name, acl_rule_name):
req = MatchRequest(db="APPL_DB", table=APP_RULE_NAME,
key_pattern=APP_DB_SEPARATOR.join([acl_table_name, acl_rule_name]), ns=self.ns)
ret = self.match_engine.fetch(req)
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_acl_rule_asic_info(self, acl_table_name, acl_rule_name):
counter_oid = fetch_acl_counter_oid(self.match_engine, acl_table_name, acl_rule_name, self.ns)
Expand Down
50 changes: 43 additions & 7 deletions dump/plugins/acl_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

CFG_DB_SEPARATOR = SonicDBConfig.getSeparator("CONFIG_DB")
ASIC_DB_SEPARATOR = SonicDBConfig.getSeparator("ASIC_DB")
APP_DB_SEPARATOR = SonicDBConfig.getSeparator("APPL_DB")
APP_TABLE_TYPE_NAME = "ACL_TABLE_TYPE_TABLE"
APP_TABLE_NAME = "ACL_TABLE_TABLE"
APP_RULE_NAME = "ACL_RULE_TABLE"


class Acl_Table(Executor):
Expand All @@ -22,21 +26,25 @@ def __init__(self, match_engine=None):
def get_all_args(self, ns=""):
req = MatchRequest(db="CONFIG_DB", table="ACL_TABLE", key_pattern="*", ns=ns)
ret = self.match_engine.fetch(req)
acl_tables = ret["keys"]
return [key.split(CFG_DB_SEPARATOR)[-1] for key in acl_tables]
req_app = MatchRequest(db="APPL_DB", table=APP_TABLE_NAME, key_pattern="*", ns=ns)
ret_app = self.match_engine.fetch(req_app)
return [key.split(CFG_DB_SEPARATOR)[-1] for key in ret.get("keys")] + \
[key.split(APP_DB_SEPARATOR)[-1] for key in ret_app.get("keys")]

def execute(self, params):
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "ASIC_DB"])
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB"])
acl_table_name = params[self.ARG_NAME]
self.ns = params["namespace"]
self.init_acl_table_config_info(acl_table_name)
self.init_acl_table_appl_info(acl_table_name)
self.init_acl_table_asic_info(acl_table_name)
return self.ret_temp

def init_acl_table_config_info(self, acl_table_name):
req = MatchRequest(db="CONFIG_DB", table="ACL_TABLE", key_pattern=acl_table_name, return_fields=["type"], ns=self.ns)
ret = self.match_engine.fetch(req)
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

# Find corresponding ACL table type in CONFIG DB
return_values = ret["return_values"]
Expand All @@ -47,13 +55,41 @@ def init_acl_table_config_info(self, acl_table_name):
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_acl_table_asic_info(self, acl_table_name):
def init_acl_table_appl_info(self, acl_table_name):
req = MatchRequest(db="APPL_DB", table=APP_TABLE_NAME, key_pattern=acl_table_name,
return_fields=["type"], ns=self.ns)
ret = self.match_engine.fetch(req)
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

# Find corresponding ACL table type in CONFIG DB
return_values = ret["return_values"]
acl_table_type_name = return_values.get(APP_DB_SEPARATOR.join([APP_TABLE_NAME, acl_table_name]), {}).get("type")
req = MatchRequest(db="APPL_DB", table=APP_TABLE_TYPE_NAME, key_pattern=acl_table_type_name, ns=self.ns)
ret = self.match_engine.fetch(req)
# If not found don't add it to the table, it might be a default table type
if ret["keys"]:
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def find_any_rule(self, acl_table_name):
req = MatchRequest(db="CONFIG_DB", table="ACL_RULE", key_pattern=CFG_DB_SEPARATOR.join([acl_table_name, "*"]), ns=self.ns)
ret = self.match_engine.fetch(req)
acl_rules = ret["keys"]
if not acl_rules:
if acl_rules:
return acl_rules[0].split(CFG_DB_SEPARATOR)[-1]

# Check in APPL_DB
req = MatchRequest(db="APPL_DB", table=APP_RULE_NAME,
key_pattern=APP_DB_SEPARATOR.join([acl_table_name, "*"]), ns=self.ns)
ret = self.match_engine.fetch(req)
acl_rules = ret["keys"]
if acl_rules:
return acl_rules[0].split(APP_DB_SEPARATOR)[-1]

def init_acl_table_asic_info(self, acl_table_name):
acl_rule_name = self.find_any_rule(acl_table_name)
if not acl_rule_name:
return
acl_rule_name = acl_rules[0].split(CFG_DB_SEPARATOR)[-1]

counter_oid = fetch_acl_counter_oid(self.match_engine, acl_table_name, acl_rule_name, self.ns)
if not counter_oid:
Expand Down
18 changes: 18 additions & 0 deletions tests/dump_input/acl/appl_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"ACL_TABLE_TYPE_TABLE:MY_TYPE": {
"matches": "ETHER_TYPE,L4_DST_PORT_RANGE,L4_SRC_PORT_RANGE ",
"bind_point_types": "port"
},
"ACL_TABLE_TABLE:DATAACL2": {
"policy_desc": "Some ACL table",
"ports": "Ethernet0,Ethernet4",
"stage": "ingress",
"type": "MY_TYPE"
},
"ACL_RULE_TABLE:DATAACL2:R0": {
"L4_SRC_PORT_RANGE ": "90-95",
"L4_DST_PORT_RANGE ": "90-95",
"PACKET_ACTION": "FORWARD",
"PRIORITY": "999"
}
}
16 changes: 0 additions & 16 deletions tests/dump_input/acl/config_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
"stage": "ingress",
"type": "CTRLPLANE"
},
"ACL_TABLE_TYPE|MY_TYPE": {
"matches": "ETHER_TYPE,L4_DST_PORT_RANGE,L4_SRC_PORT_RANGE ",
"bind_point_types": "port"
},
"ACL_TABLE|DATAACL": {
"policy_desc": "Some ACL table",
"ports": "Ethernet0,Ethernet4",
Expand All @@ -23,21 +19,9 @@
"stage": "ingress",
"type": "L3"
},
"ACL_TABLE|DATAACL2": {
"policy_desc": "Some ACL table",
"ports": "Ethernet0,Ethernet4",
"stage": "ingress",
"type": "MY_TYPE"
},
"ACL_RULE|DATAACL|R0": {
"ETHER_TYPE": "2048",
"PACKET_ACTION": "FORWARD",
"PRIORITY": "999"
},
"ACL_RULE|DATAACL2|R0": {
"L4_SRC_PORT_RANGE ": "90-95",
"L4_DST_PORT_RANGE ": "90-95",
"PACKET_ACTION": "FORWARD",
"PRIORITY": "999"
}
}
Loading
Loading