Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into route_check_ipv6

Signed-off-by: Stepan Blyschak <stepanb@nvidia.com>
  • Loading branch information
stepanblyschak committed Mar 9, 2023
2 parents ac227a0 + 7a604c5 commit 05f590a
Show file tree
Hide file tree
Showing 26 changed files with 804 additions and 69 deletions.
75 changes: 62 additions & 13 deletions acl_loader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class AclLoader(object):

ACL_TABLE = "ACL_TABLE"
ACL_RULE = "ACL_RULE"
CFG_ACL_TABLE = "ACL_TABLE"
STATE_ACL_TABLE = "ACL_TABLE_TABLE"
CFG_ACL_RULE = "ACL_RULE"
STATE_ACL_RULE = "ACL_RULE_TABLE"
ACL_TABLE_TYPE_MIRROR = "MIRROR"
ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE"
CFG_MIRROR_SESSION_TABLE = "MIRROR_SESSION"
Expand Down Expand Up @@ -117,11 +121,16 @@ def __init__(self):
self.tables_db_info = {}
self.rules_db_info = {}
self.rules_info = {}
self.tables_state_info = None
self.rules_state_info = None

# Load database config files
load_db_config()

self.sessions_db_info = {}
self.acl_table_status = {}
self.acl_rule_status = {}

self.configdb = ConfigDBConnector()
self.configdb.connect()
self.statedb = SonicV2Connector(host="127.0.0.1")
Expand Down Expand Up @@ -156,6 +165,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)

def read_tables_info(self):
"""
Expand Down Expand Up @@ -210,7 +221,7 @@ def read_sessions_info(self):
for key in self.sessions_db_info:
if self.per_npu_statedb:
# For multi-npu platforms we will read from all front asic name space
# statedb as the monitor port will be differnt for each asic
# statedb as the monitor port will be different for each asic
# and it's status also might be different (ideally should not happen)
# We will store them as dict of 'asic' : value
self.sessions_db_info[key]["status"] = {}
Expand All @@ -224,6 +235,35 @@ 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):
"""
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)
if isinstance(key, tuple):
state_db_key = key[0] + "|" + key[1]
else:
state_db_key = key
status[key] = {}
if self.per_npu_statedb:
status[key]['status'] = {}
for namespace_key, namespace_statedb in self.per_npu_statedb.items():
state_db_info = namespace_statedb.get_all(self.statedb.STATE_DB, "{}|{}".format(state_db_table_name, state_db_key))
status[key]['status'][namespace_key] = state_db_info.get("status", "N/A") if state_db_info else "N/A"
else:
state_db_info = self.statedb.get_all(self.statedb.STATE_DB, "{}|{}".format(state_db_table_name, state_db_key))
status[key]['status'] = state_db_info.get("status", "N/A") if state_db_info else "N/A"

return status

def get_sessions_db_info(self):
return self.sessions_db_info

Expand Down Expand Up @@ -786,32 +826,36 @@ def show_table(self, table_name):
:param table_name: Optional. ACL table name. Filter tables by specified name.
:return:
"""
header = ("Name", "Type", "Binding", "Description", "Stage")
header = ("Name", "Type", "Binding", "Description", "Stage", "Status")

data = []
for key, val in self.get_tables_db_info().items():
if table_name and key != table_name:
continue

stage = val.get("stage", Stage.INGRESS).lower()

# Get ACL table status from STATE_DB
if key in self.acl_table_status:
status = self.acl_table_status[key]['status']
else:
status = 'N/A'
if val["type"] == AclLoader.ACL_TABLE_TYPE_CTRLPLANE:
services = natsorted(val["services"])
data.append([key, val["type"], services[0], val["policy_desc"], stage])
data.append([key, val["type"], services[0], val["policy_desc"], stage, status])

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

if len(ports) > 1:
for port in ports[1:]:
data.append(["", "", port, "", ""])
data.append(["", "", port, "", "", ""])

print(tabulate.tabulate(data, headers=header, tablefmt="simple", missingval=""))

Expand Down Expand Up @@ -873,7 +917,7 @@ def show_rule(self, table_name, rule_id):
:param rule_id: Optional. ACL rule name. Filter rule by specified rule name.
:return:
"""
header = ("Table", "Rule", "Priority", "Action", "Match")
header = ("Table", "Rule", "Priority", "Action", "Match", "Status")

def pop_priority(val):
priority = "N/A"
Expand Down Expand Up @@ -919,11 +963,16 @@ def pop_matches(val):
priority = pop_priority(val)
action = pop_action(val)
matches = pop_matches(val)

rule_data = [[tname, rid, priority, action, matches[0]]]
# Get ACL rule status from STATE_DB
status_key = (tname, rid)
if status_key in self.acl_rule_status:
status = self.acl_rule_status[status_key]['status']
else:
status = "N/A"
rule_data = [[tname, rid, priority, action, matches[0], status]]
if len(matches) > 1:
for m in matches[1:]:
rule_data.append(["", "", "", "", m])
rule_data.append(["", "", "", "", m, ""])

raw_data.append([priority, rule_data])

Expand Down
66 changes: 46 additions & 20 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2354,25 +2354,35 @@ def add_erspan(session_name, src_ip, dst_ip, dscp, ttl, gre_type, queue, policer
session_info['gre_type'] = gre_type

session_info = gather_session_info(session_info, policer, queue, src_port, direction)
ctx = click.get_current_context()

"""
For multi-npu platforms we need to program all front asic namespaces
"""
namespaces = multi_asic.get_all_namespaces()
if not namespaces['front_ns']:
config_db = ConfigDBConnector()
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
config_db.connect()
if validate_mirror_session_config(config_db, session_name, None, src_port, direction) is False:
return
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
if ADHOC_VALIDATION:
if validate_mirror_session_config(config_db, session_name, None, src_port, direction) is False:
return
try:
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
except ValueError as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))

else:
per_npu_configdb = {}
for front_asic_namespaces in namespaces['front_ns']:
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
per_npu_configdb[front_asic_namespaces].connect()
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, None, src_port, direction) is False:
return
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
if ADHOC_VALIDATION:
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, None, src_port, direction) is False:
return
try:
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
except ValueError as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))

@mirror_session.group(cls=clicommon.AbbreviationGroup, name='span')
@click.pass_context
Expand Down Expand Up @@ -2404,25 +2414,34 @@ def add_span(session_name, dst_port, src_port, direction, queue, policer):
}

session_info = gather_session_info(session_info, policer, queue, src_port, direction)
ctx = click.get_current_context()

"""
For multi-npu platforms we need to program all front asic namespaces
"""
namespaces = multi_asic.get_all_namespaces()
if not namespaces['front_ns']:
config_db = ConfigDBConnector()
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
config_db.connect()
if validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction) is False:
return
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
if ADHOC_VALIDATION:
if validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction) is False:
return
try:
config_db.set_entry("MIRROR_SESSION", session_name, session_info)
except ValueError as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
else:
per_npu_configdb = {}
for front_asic_namespaces in namespaces['front_ns']:
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
per_npu_configdb[front_asic_namespaces].connect()
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, dst_port, src_port, direction) is False:
return
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
if ADHOC_VALIDATION:
if validate_mirror_session_config(per_npu_configdb[front_asic_namespaces], session_name, dst_port, src_port, direction) is False:
return
try:
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, session_info)
except ValueError as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))


@mirror_session.command()
Expand All @@ -2434,16 +2453,23 @@ def remove(session_name):
For multi-npu platforms we need to program all front asic namespaces
"""
namespaces = multi_asic.get_all_namespaces()
ctx = click.get_current_context()
if not namespaces['front_ns']:
config_db = ConfigDBConnector()
config_db = ValidatedConfigDBConnector(ConfigDBConnector())
config_db.connect()
config_db.set_entry("MIRROR_SESSION", session_name, None)
try:
config_db.set_entry("MIRROR_SESSION", session_name, None)
except JsonPatchConflict as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
else:
per_npu_configdb = {}
for front_asic_namespaces in namespaces['front_ns']:
per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces)
per_npu_configdb[front_asic_namespaces] = ValidatedConfigDBConnector(ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces))
per_npu_configdb[front_asic_namespaces].connect()
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, None)
try:
per_npu_configdb[front_asic_namespaces].set_entry("MIRROR_SESSION", session_name, None)
except JsonPatchConflict as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))

#
# 'pfcwd' group ('config pfcwd ...')
Expand Down
2 changes: 1 addition & 1 deletion generic_config_updater/change_applier.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .gu_common import genericUpdaterLogging

SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
UPDATER_CONF_FILE = f"{SCRIPT_DIR}/generic_config_updater.conf.json"
UPDATER_CONF_FILE = f"{SCRIPT_DIR}/gcu_services_validator.conf.json"
logger = genericUpdaterLogging.get_logger(title="Change Applier")

print_to_console = False
Expand Down
26 changes: 26 additions & 0 deletions generic_config_updater/field_operation_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from sonic_py_common import device_info
import re

def rdma_config_update_validator():
version_info = device_info.get_sonic_version_info()
build_version = version_info.get('build_version')
asic_type = version_info.get('asic_type')

if (asic_type != 'mellanox' and asic_type != 'broadcom' and asic_type != 'cisco-8000'):
return False

version_substrings = build_version.split('.')
branch_version = None

for substring in version_substrings:
if substring.isdigit() and re.match(r'^\d{8}$', substring):
branch_version = substring
break

if branch_version is None:
return False

if asic_type == 'cisco-8000':
return branch_version >= "20201200"
else:
return branch_version >= "20181100"
20 changes: 20 additions & 0 deletions generic_config_updater/gcu_field_operation_validators.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"README": [
"field_operation_validators provides, module & method name as ",
" <module name>.<method name>",
"NOTE: module name could have '.'",
" ",
"The last element separated by '.' is considered as ",
"method name",
"",
"e.g. 'show.acl.test_acl'",
"",
"field_operation_validators for a given table defines a list of validators that all must pass for modification to the specified field and table to be allowed",
""
],
"tables": {
"PFC_WD": {
"field_operation_validators": [ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
},
"NTP_SERVER": {
"services_to_validate": [ "ntp-service" ]
},
"VLAN_INTERFACE": {
"services_to_validate": [ "vlanintf-service" ]
}
},
"services": {
Expand All @@ -71,6 +74,9 @@
},
"ntp-service": {
"validate_commands": [ "generic_config_updater.services_validator.ntp_validator" ]
},
"vlanintf-service": {
"validate_commands": [ "generic_config_updater.services_validator.vlanintf_validator" ]
}
}
}
Expand Down
Loading

0 comments on commit 05f590a

Please sign in to comment.