Skip to content

Commit

Permalink
Merge branch 'Azure:master' into storm_control
Browse files Browse the repository at this point in the history
  • Loading branch information
mohan-selvaraj committed Nov 15, 2021
2 parents 7542172 + 00b6045 commit 4c9945f
Show file tree
Hide file tree
Showing 40 changed files with 2,125 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .azure-pipelines/test-docker-sonic-vs-template.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: timeout
type: number
default: 180
default: 240

- name: log_artifact_name
type: string
Expand Down
38 changes: 38 additions & 0 deletions config/aaa.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,44 @@ def login(auth_protocol):
add_table_kv('AAA', 'authentication', 'login', val)
authentication.add_command(login)

# cmd: aaa authorization
@click.command()
@click.argument('protocol', nargs=-1, type=click.Choice([ "tacacs+", "local", "tacacs+ local"]))
def authorization(protocol):
"""Switch AAA authorization [tacacs+ | local | '\"tacacs+ local\"']"""
if len(protocol) == 0:
click.echo('Argument "protocol" is required')
return

if len(protocol) == 1 and (protocol[0] == 'tacacs+' or protocol[0] == 'local'):
add_table_kv('AAA', 'authorization', 'login', protocol[0])
elif len(protocol) == 1 and protocol[0] == 'tacacs+ local':
add_table_kv('AAA', 'authorization', 'login', 'tacacs+,local')
else:
click.echo('Not a valid command')
aaa.add_command(authorization)

# cmd: aaa accounting
@click.command()
@click.argument('protocol', nargs=-1, type=click.Choice(["disable", "tacacs+", "local", "tacacs+ local"]))
def accounting(protocol):
"""Switch AAA accounting [disable | tacacs+ | local | '\"tacacs+ local\"']"""
if len(protocol) == 0:
click.echo('Argument "protocol" is required')
return

if len(protocol) == 1:
if protocol[0] == 'tacacs+' or protocol[0] == 'local':
add_table_kv('AAA', 'accounting', 'login', protocol[0])
elif protocol[0] == 'tacacs+ local':
add_table_kv('AAA', 'accounting', 'login', 'tacacs+,local')
elif protocol[0] == 'disable':
del_table_key('AAA', 'accounting', 'login')
else:
click.echo('Not a valid command')
else:
click.echo('Not a valid command')
aaa.add_command(accounting)

@click.group()
def tacacs():
Expand Down
44 changes: 42 additions & 2 deletions crm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def show_thresholds(self, resource):
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
"nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry",
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry", "mpls_inseg",
"mpls_nexthop"]:
"mpls_nexthop","srv6_nexthop", "srv6_my_sid_entry"]:
try:
data.append([res, crm_info[res + "_threshold_type"], crm_info[res + "_low_threshold"], crm_info[res + "_high_threshold"]])
except KeyError:
Expand Down Expand Up @@ -100,7 +100,7 @@ def get_resources(self, resource):
if resource == 'all':
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry",
"mpls_inseg", "mpls_nexthop"]:
"mpls_inseg", "mpls_nexthop","srv6_nexthop", "srv6_my_sid_entry"]:
if 'crm_stats_' + res + "_used" in crm_stats.keys() and 'crm_stats_' + res + "_available" in crm_stats.keys():
data.append([res, crm_stats['crm_stats_' + res + "_used"], crm_stats['crm_stats_' + res + "_available"]])
else:
Expand Down Expand Up @@ -460,6 +460,26 @@ def counter(ctx):
counter.add_command(low)
counter.add_command(high)

@thresholds.group()
@click.pass_context
def srv6_nexthop(ctx):
"""CRM configuration for SRV6 Nexthop resource"""
ctx.obj["crm"].res_type = 'srv6_nexthop'

srv6_nexthop.add_command(type)
srv6_nexthop.add_command(low)
srv6_nexthop.add_command(high)

@thresholds.group()
@click.pass_context
def srv6_my_sid_entry(ctx):
"""CRM configuration for SRV6 MY_SID resource"""
ctx.obj["crm"].res_type = 'srv6_my_sid_entry'

srv6_my_sid_entry.add_command(type)
srv6_my_sid_entry.add_command(low)
srv6_my_sid_entry.add_command(high)

@cli.group()
@click.pass_context
def show(ctx):
Expand Down Expand Up @@ -644,6 +664,24 @@ def dnat(ctx):
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('dnat_entry')

@resources.command()
@click.pass_context
def srv6_nexthop(ctx):
"""Show CRM information for SRV6 Nexthop"""
if ctx.obj["crm"].cli_mode == 'thresholds':
ctx.obj["crm"].show_thresholds('srv6_nexthop')
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('srv6_nexthop')

@resources.command()
@click.pass_context
def srv6_my_sid_entry(ctx):
"""Show CRM information for SRV6 MY_SID entry"""
if ctx.obj["crm"].cli_mode == 'thresholds':
ctx.obj["crm"].show_thresholds('srv6_my_sid_entry')
elif ctx.obj["crm"].cli_mode == 'resources':
ctx.obj["crm"].show_resources('srv6_my_sid_entry')

thresholds.add_command(acl)
thresholds.add_command(all)
thresholds.add_command(fdb)
Expand All @@ -654,6 +692,8 @@ def dnat(ctx):
thresholds.add_command(ipmc)
thresholds.add_command(snat)
thresholds.add_command(dnat)
thresholds.add_command(srv6_nexthop)
thresholds.add_command(srv6_my_sid_entry)


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion dump/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def populate_fv(info, module, namespace):
final_info[id][db_name]["tables_not_found"] = info[id][db_name]["tables_not_found"]
for key in info[id][db_name]["keys"]:
if db_name is "CONFIG_FILE":
fv = db_dict[db_name].get(db_name, key)
fv = db_cfg_file.get(db_name, key)
else:
fv = db_conn.get_all(db_name, key)
final_info[id][db_name]["keys"].append({key: fv})
Expand Down
113 changes: 113 additions & 0 deletions dump/plugins/portchannel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from dump.match_infra import MatchRequest
from dump.helper import create_template_dict
from .executor import Executor


class Portchannel(Executor):
"""
Debug Dump Plugin for PortChannel/LAG Module
"""
ARG_NAME = "portchannel_name"

def __init__(self, match_engine=None):
super().__init__(match_engine)
self.ret_temp = {}
self.ns = ''
self.lag_members = set()

def get_all_args(self, ns=""):
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL", key_pattern="*", ns=ns)
ret = self.match_engine.fetch(req)
all_lags = ret["keys"]
return [key.split("|")[-1] for key in all_lags]

def execute(self, params_dict):
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
self.lag_name = params_dict[Portchannel.ARG_NAME]
self.ns = params_dict["namespace"]
# CONFIG_DB
lag_found = self.init_lag_config_info()
if lag_found:
self.init_lag_member_config_info()
# APPL_DB
self.init_lag_appl_info()
# STATE_DB
self.init_lag_state_info()
# ASIC_DB
lag_type_objs_asic = self.init_lag_member_type_obj_asic_info()
self.init_lag_asic_info(lag_type_objs_asic)
return self.ret_temp

def add_to_ret_template(self, table, db, keys, err):
if not err and keys:
self.ret_temp[db]["keys"].extend(keys)
return True
else:
self.ret_temp[db]["tables_not_found"].extend([table])
return False

def init_lag_config_info(self):
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL", key_pattern=self.lag_name, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_member_config_info(self):
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=self.lag_name + "|*", ns=self.ns)
ret = self.match_engine.fetch(req)
for key in ret["keys"]:
self.lag_members.add(key.split("|")[-1])

def init_lag_appl_info(self):
req = MatchRequest(db="APPL_DB", table="LAG_TABLE", key_pattern=self.lag_name, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_state_info(self):
req = MatchRequest(db="STATE_DB", table="LAG_TABLE", key_pattern=self.lag_name, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_asic_info(self, lag_type_objs_asic):
if len(lag_type_objs_asic) == 0:
self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG"])
return
for lag_asic_obj in lag_type_objs_asic:
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns)
ret = self.match_engine.fetch(req)
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_member_type_obj_asic_info(self):
"""
Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name
Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID
"""
lag_type_objs_asic = set()
for port_name in self.lag_members:
port_asic_obj = self.get_port_asic_obj(port_name)
if port_asic_obj:
lag_member_key, lag_oid = self.get_lag_and_member_obj(port_asic_obj)
lag_type_objs_asic.add(lag_oid)
return lag_type_objs_asic

def get_port_asic_obj(self, port_name):
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME",
value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns)
ret = self.match_engine.fetch(req)
asic_port_obj_id = ""
if not ret["error"] and ret["keys"]:
sai_hostif_obj_key = ret["keys"][-1]
if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]:
asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"]
return asic_port_obj_id

def get_lag_and_member_obj(self, port_asic_obj):
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID",
value=port_asic_obj, return_fields=["SAI_LAG_MEMBER_ATTR_LAG_ID"], ns=self.ns)
ret = self.match_engine.fetch(req)
lag_member_key = ""
lag_oid = ""
if not ret["error"] and ret["keys"]:
lag_member_key = ret["keys"][-1]
if lag_member_key in ret["return_values"] and "SAI_LAG_MEMBER_ATTR_LAG_ID" in ret["return_values"][lag_member_key]:
lag_oid = ret["return_values"][lag_member_key]["SAI_LAG_MEMBER_ATTR_LAG_ID"]
return lag_member_key, lag_oid
84 changes: 84 additions & 0 deletions dump/plugins/portchannel_member.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from dump.match_infra import MatchRequest
from dump.helper import create_template_dict
from .executor import Executor

class Portchannel_Member(Executor):
"""
Debug Dump Plugin for PortChannel/LAG Module
"""
ARG_NAME = "portchannel_member"

def __init__(self, match_engine=None):
super().__init__(match_engine)
self.ret_temp = {}
self.ns = ''
self.lag_member_key = ''
self.lag = ''
self.port_name = ''

def get_all_args(self, ns=""):
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern="*", ns=ns)
ret = self.match_engine.fetch(req)
all_lag_members = ret["keys"]
return [key.split("|", 1)[-1] for key in all_lag_members]

def execute(self, params_dict):
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
self.lag_member_key = params_dict[Portchannel_Member.ARG_NAME]
if "|" not in self.lag_member_key:
return self.ret_temp
self.lag, self.port_name = self.lag_member_key.split("|", 1)
self.ns = params_dict["namespace"]
# CONFIG_DB
self.init_lag_member_config_info()
# APPL_DB
self.init_lag_member_appl_info()
# STATE_DB
self.init_lag_member_state_info()
# ASIC_DB
self.init_lag_member_type_obj_asic_info()
return self.ret_temp

def add_to_ret_template(self, table, db, keys, err):
if not err and keys:
self.ret_temp[db]["keys"].extend(keys)
return True
else:
self.ret_temp[db]["tables_not_found"].extend([table])
return False

def init_lag_member_config_info(self):
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=self.lag_member_key, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_member_appl_info(self):
req = MatchRequest(db="APPL_DB", table="LAG_MEMBER_TABLE", key_pattern=self.lag + ":" + self.port_name, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_member_state_info(self):
req = MatchRequest(db="STATE_DB", table="LAG_MEMBER_TABLE", key_pattern=self.lag_member_key, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def init_lag_member_type_obj_asic_info(self):
port_asic_obj = self.get_port_asic_obj(self.port_name)
if not port_asic_obj:
self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER"])
return False
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID",
value=port_asic_obj, ns=self.ns)
ret = self.match_engine.fetch(req)
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])

def get_port_asic_obj(self, port_name):
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME",
value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns)
ret = self.match_engine.fetch(req)
asic_port_obj_id = ""
if not ret["error"] and ret["keys"]:
sai_hostif_obj_key = ret["keys"][-1]
if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]:
asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"]
return asic_port_obj_id
Loading

0 comments on commit 4c9945f

Please sign in to comment.