Skip to content

Commit 4c9945f

Browse files
Merge branch 'Azure:master' into storm_control
2 parents 7542172 + 00b6045 commit 4c9945f

40 files changed

+2125
-67
lines changed

.azure-pipelines/test-docker-sonic-vs-template.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
parameters:
22
- name: timeout
33
type: number
4-
default: 180
4+
default: 240
55

66
- name: log_artifact_name
77
type: string

config/aaa.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,44 @@ def login(auth_protocol):
137137
add_table_kv('AAA', 'authentication', 'login', val)
138138
authentication.add_command(login)
139139

140+
# cmd: aaa authorization
141+
@click.command()
142+
@click.argument('protocol', nargs=-1, type=click.Choice([ "tacacs+", "local", "tacacs+ local"]))
143+
def authorization(protocol):
144+
"""Switch AAA authorization [tacacs+ | local | '\"tacacs+ local\"']"""
145+
if len(protocol) == 0:
146+
click.echo('Argument "protocol" is required')
147+
return
148+
149+
if len(protocol) == 1 and (protocol[0] == 'tacacs+' or protocol[0] == 'local'):
150+
add_table_kv('AAA', 'authorization', 'login', protocol[0])
151+
elif len(protocol) == 1 and protocol[0] == 'tacacs+ local':
152+
add_table_kv('AAA', 'authorization', 'login', 'tacacs+,local')
153+
else:
154+
click.echo('Not a valid command')
155+
aaa.add_command(authorization)
156+
157+
# cmd: aaa accounting
158+
@click.command()
159+
@click.argument('protocol', nargs=-1, type=click.Choice(["disable", "tacacs+", "local", "tacacs+ local"]))
160+
def accounting(protocol):
161+
"""Switch AAA accounting [disable | tacacs+ | local | '\"tacacs+ local\"']"""
162+
if len(protocol) == 0:
163+
click.echo('Argument "protocol" is required')
164+
return
165+
166+
if len(protocol) == 1:
167+
if protocol[0] == 'tacacs+' or protocol[0] == 'local':
168+
add_table_kv('AAA', 'accounting', 'login', protocol[0])
169+
elif protocol[0] == 'tacacs+ local':
170+
add_table_kv('AAA', 'accounting', 'login', 'tacacs+,local')
171+
elif protocol[0] == 'disable':
172+
del_table_key('AAA', 'accounting', 'login')
173+
else:
174+
click.echo('Not a valid command')
175+
else:
176+
click.echo('Not a valid command')
177+
aaa.add_command(accounting)
140178

141179
@click.group()
142180
def tacacs():

crm/main.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def show_thresholds(self, resource):
7272
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
7373
"nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry",
7474
"acl_counter", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry", "mpls_inseg",
75-
"mpls_nexthop"]:
75+
"mpls_nexthop","srv6_nexthop", "srv6_my_sid_entry"]:
7676
try:
7777
data.append([res, crm_info[res + "_threshold_type"], crm_info[res + "_low_threshold"], crm_info[res + "_high_threshold"]])
7878
except KeyError:
@@ -100,7 +100,7 @@ def get_resources(self, resource):
100100
if resource == 'all':
101101
for res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor",
102102
"nexthop_group_member", "nexthop_group", "fdb_entry", "ipmc_entry", "snat_entry", "dnat_entry",
103-
"mpls_inseg", "mpls_nexthop"]:
103+
"mpls_inseg", "mpls_nexthop","srv6_nexthop", "srv6_my_sid_entry"]:
104104
if 'crm_stats_' + res + "_used" in crm_stats.keys() and 'crm_stats_' + res + "_available" in crm_stats.keys():
105105
data.append([res, crm_stats['crm_stats_' + res + "_used"], crm_stats['crm_stats_' + res + "_available"]])
106106
else:
@@ -460,6 +460,26 @@ def counter(ctx):
460460
counter.add_command(low)
461461
counter.add_command(high)
462462

463+
@thresholds.group()
464+
@click.pass_context
465+
def srv6_nexthop(ctx):
466+
"""CRM configuration for SRV6 Nexthop resource"""
467+
ctx.obj["crm"].res_type = 'srv6_nexthop'
468+
469+
srv6_nexthop.add_command(type)
470+
srv6_nexthop.add_command(low)
471+
srv6_nexthop.add_command(high)
472+
473+
@thresholds.group()
474+
@click.pass_context
475+
def srv6_my_sid_entry(ctx):
476+
"""CRM configuration for SRV6 MY_SID resource"""
477+
ctx.obj["crm"].res_type = 'srv6_my_sid_entry'
478+
479+
srv6_my_sid_entry.add_command(type)
480+
srv6_my_sid_entry.add_command(low)
481+
srv6_my_sid_entry.add_command(high)
482+
463483
@cli.group()
464484
@click.pass_context
465485
def show(ctx):
@@ -644,6 +664,24 @@ def dnat(ctx):
644664
elif ctx.obj["crm"].cli_mode == 'resources':
645665
ctx.obj["crm"].show_resources('dnat_entry')
646666

667+
@resources.command()
668+
@click.pass_context
669+
def srv6_nexthop(ctx):
670+
"""Show CRM information for SRV6 Nexthop"""
671+
if ctx.obj["crm"].cli_mode == 'thresholds':
672+
ctx.obj["crm"].show_thresholds('srv6_nexthop')
673+
elif ctx.obj["crm"].cli_mode == 'resources':
674+
ctx.obj["crm"].show_resources('srv6_nexthop')
675+
676+
@resources.command()
677+
@click.pass_context
678+
def srv6_my_sid_entry(ctx):
679+
"""Show CRM information for SRV6 MY_SID entry"""
680+
if ctx.obj["crm"].cli_mode == 'thresholds':
681+
ctx.obj["crm"].show_thresholds('srv6_my_sid_entry')
682+
elif ctx.obj["crm"].cli_mode == 'resources':
683+
ctx.obj["crm"].show_resources('srv6_my_sid_entry')
684+
647685
thresholds.add_command(acl)
648686
thresholds.add_command(all)
649687
thresholds.add_command(fdb)
@@ -654,6 +692,8 @@ def dnat(ctx):
654692
thresholds.add_command(ipmc)
655693
thresholds.add_command(snat)
656694
thresholds.add_command(dnat)
695+
thresholds.add_command(srv6_nexthop)
696+
thresholds.add_command(srv6_my_sid_entry)
657697

658698

659699
if __name__ == '__main__':

dump/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def populate_fv(info, module, namespace):
165165
final_info[id][db_name]["tables_not_found"] = info[id][db_name]["tables_not_found"]
166166
for key in info[id][db_name]["keys"]:
167167
if db_name is "CONFIG_FILE":
168-
fv = db_dict[db_name].get(db_name, key)
168+
fv = db_cfg_file.get(db_name, key)
169169
else:
170170
fv = db_conn.get_all(db_name, key)
171171
final_info[id][db_name]["keys"].append({key: fv})

dump/plugins/portchannel.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from dump.match_infra import MatchRequest
2+
from dump.helper import create_template_dict
3+
from .executor import Executor
4+
5+
6+
class Portchannel(Executor):
7+
"""
8+
Debug Dump Plugin for PortChannel/LAG Module
9+
"""
10+
ARG_NAME = "portchannel_name"
11+
12+
def __init__(self, match_engine=None):
13+
super().__init__(match_engine)
14+
self.ret_temp = {}
15+
self.ns = ''
16+
self.lag_members = set()
17+
18+
def get_all_args(self, ns=""):
19+
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL", key_pattern="*", ns=ns)
20+
ret = self.match_engine.fetch(req)
21+
all_lags = ret["keys"]
22+
return [key.split("|")[-1] for key in all_lags]
23+
24+
def execute(self, params_dict):
25+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
26+
self.lag_name = params_dict[Portchannel.ARG_NAME]
27+
self.ns = params_dict["namespace"]
28+
# CONFIG_DB
29+
lag_found = self.init_lag_config_info()
30+
if lag_found:
31+
self.init_lag_member_config_info()
32+
# APPL_DB
33+
self.init_lag_appl_info()
34+
# STATE_DB
35+
self.init_lag_state_info()
36+
# ASIC_DB
37+
lag_type_objs_asic = self.init_lag_member_type_obj_asic_info()
38+
self.init_lag_asic_info(lag_type_objs_asic)
39+
return self.ret_temp
40+
41+
def add_to_ret_template(self, table, db, keys, err):
42+
if not err and keys:
43+
self.ret_temp[db]["keys"].extend(keys)
44+
return True
45+
else:
46+
self.ret_temp[db]["tables_not_found"].extend([table])
47+
return False
48+
49+
def init_lag_config_info(self):
50+
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL", key_pattern=self.lag_name, ns=self.ns)
51+
ret = self.match_engine.fetch(req)
52+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
53+
54+
def init_lag_member_config_info(self):
55+
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=self.lag_name + "|*", ns=self.ns)
56+
ret = self.match_engine.fetch(req)
57+
for key in ret["keys"]:
58+
self.lag_members.add(key.split("|")[-1])
59+
60+
def init_lag_appl_info(self):
61+
req = MatchRequest(db="APPL_DB", table="LAG_TABLE", key_pattern=self.lag_name, ns=self.ns)
62+
ret = self.match_engine.fetch(req)
63+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
64+
65+
def init_lag_state_info(self):
66+
req = MatchRequest(db="STATE_DB", table="LAG_TABLE", key_pattern=self.lag_name, ns=self.ns)
67+
ret = self.match_engine.fetch(req)
68+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
69+
70+
def init_lag_asic_info(self, lag_type_objs_asic):
71+
if len(lag_type_objs_asic) == 0:
72+
self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG"])
73+
return
74+
for lag_asic_obj in lag_type_objs_asic:
75+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG", key_pattern=lag_asic_obj, ns=self.ns)
76+
ret = self.match_engine.fetch(req)
77+
self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
78+
79+
def init_lag_member_type_obj_asic_info(self):
80+
"""
81+
Finding the relevant SAI_OBJECT_TYPE_LAG key directly from the ASIC is not possible given a LAG name
82+
Thus, using the members to find SAI_LAG_MEMBER_ATTR_LAG_ID
83+
"""
84+
lag_type_objs_asic = set()
85+
for port_name in self.lag_members:
86+
port_asic_obj = self.get_port_asic_obj(port_name)
87+
if port_asic_obj:
88+
lag_member_key, lag_oid = self.get_lag_and_member_obj(port_asic_obj)
89+
lag_type_objs_asic.add(lag_oid)
90+
return lag_type_objs_asic
91+
92+
def get_port_asic_obj(self, port_name):
93+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME",
94+
value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns)
95+
ret = self.match_engine.fetch(req)
96+
asic_port_obj_id = ""
97+
if not ret["error"] and ret["keys"]:
98+
sai_hostif_obj_key = ret["keys"][-1]
99+
if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]:
100+
asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"]
101+
return asic_port_obj_id
102+
103+
def get_lag_and_member_obj(self, port_asic_obj):
104+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID",
105+
value=port_asic_obj, return_fields=["SAI_LAG_MEMBER_ATTR_LAG_ID"], ns=self.ns)
106+
ret = self.match_engine.fetch(req)
107+
lag_member_key = ""
108+
lag_oid = ""
109+
if not ret["error"] and ret["keys"]:
110+
lag_member_key = ret["keys"][-1]
111+
if lag_member_key in ret["return_values"] and "SAI_LAG_MEMBER_ATTR_LAG_ID" in ret["return_values"][lag_member_key]:
112+
lag_oid = ret["return_values"][lag_member_key]["SAI_LAG_MEMBER_ATTR_LAG_ID"]
113+
return lag_member_key, lag_oid

dump/plugins/portchannel_member.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from dump.match_infra import MatchRequest
2+
from dump.helper import create_template_dict
3+
from .executor import Executor
4+
5+
class Portchannel_Member(Executor):
6+
"""
7+
Debug Dump Plugin for PortChannel/LAG Module
8+
"""
9+
ARG_NAME = "portchannel_member"
10+
11+
def __init__(self, match_engine=None):
12+
super().__init__(match_engine)
13+
self.ret_temp = {}
14+
self.ns = ''
15+
self.lag_member_key = ''
16+
self.lag = ''
17+
self.port_name = ''
18+
19+
def get_all_args(self, ns=""):
20+
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern="*", ns=ns)
21+
ret = self.match_engine.fetch(req)
22+
all_lag_members = ret["keys"]
23+
return [key.split("|", 1)[-1] for key in all_lag_members]
24+
25+
def execute(self, params_dict):
26+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
27+
self.lag_member_key = params_dict[Portchannel_Member.ARG_NAME]
28+
if "|" not in self.lag_member_key:
29+
return self.ret_temp
30+
self.lag, self.port_name = self.lag_member_key.split("|", 1)
31+
self.ns = params_dict["namespace"]
32+
# CONFIG_DB
33+
self.init_lag_member_config_info()
34+
# APPL_DB
35+
self.init_lag_member_appl_info()
36+
# STATE_DB
37+
self.init_lag_member_state_info()
38+
# ASIC_DB
39+
self.init_lag_member_type_obj_asic_info()
40+
return self.ret_temp
41+
42+
def add_to_ret_template(self, table, db, keys, err):
43+
if not err and keys:
44+
self.ret_temp[db]["keys"].extend(keys)
45+
return True
46+
else:
47+
self.ret_temp[db]["tables_not_found"].extend([table])
48+
return False
49+
50+
def init_lag_member_config_info(self):
51+
req = MatchRequest(db="CONFIG_DB", table="PORTCHANNEL_MEMBER", key_pattern=self.lag_member_key, ns=self.ns)
52+
ret = self.match_engine.fetch(req)
53+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
54+
55+
def init_lag_member_appl_info(self):
56+
req = MatchRequest(db="APPL_DB", table="LAG_MEMBER_TABLE", key_pattern=self.lag + ":" + self.port_name, ns=self.ns)
57+
ret = self.match_engine.fetch(req)
58+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
59+
60+
def init_lag_member_state_info(self):
61+
req = MatchRequest(db="STATE_DB", table="LAG_MEMBER_TABLE", key_pattern=self.lag_member_key, ns=self.ns)
62+
ret = self.match_engine.fetch(req)
63+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
64+
65+
def init_lag_member_type_obj_asic_info(self):
66+
port_asic_obj = self.get_port_asic_obj(self.port_name)
67+
if not port_asic_obj:
68+
self.ret_temp["ASIC_DB"]["tables_not_found"].extend(["ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER"])
69+
return False
70+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", key_pattern="*", field="SAI_LAG_MEMBER_ATTR_PORT_ID",
71+
value=port_asic_obj, ns=self.ns)
72+
ret = self.match_engine.fetch(req)
73+
return self.add_to_ret_template(req.table, req.db, ret["keys"], ret["error"])
74+
75+
def get_port_asic_obj(self, port_name):
76+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME",
77+
value=port_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns)
78+
ret = self.match_engine.fetch(req)
79+
asic_port_obj_id = ""
80+
if not ret["error"] and ret["keys"]:
81+
sai_hostif_obj_key = ret["keys"][-1]
82+
if sai_hostif_obj_key in ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in ret["return_values"][sai_hostif_obj_key]:
83+
asic_port_obj_id = ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"]
84+
return asic_port_obj_id

0 commit comments

Comments
 (0)