Skip to content

Commit 5e95fc3

Browse files
[debug dump util] Vlan Module Added (sonic-net#1877)
What I did Implemented vlan and vlan_member modules for debug dump utility. How I did it Used infrastructure and followed examples in sonic-net#1666 sonic-net#1667 sonic-net#1668 sonic-net#1669 sonic-net#1670 How to verify it On switch: dump state vlan <vlan_name> dump state vlan_member '<vlan_name|<member_name>' Unit test: pytest-3 dump_tests/module_tests/vlan_test.py (same test file covers both vlan and vlan_member)
1 parent 7f0bbd9 commit 5e95fc3

File tree

7 files changed

+901
-0
lines changed

7 files changed

+901
-0
lines changed

dump/plugins/vlan.py

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from .executor import Executor
2+
from dump.match_infra import MatchRequest
3+
from dump.helper import create_template_dict
4+
5+
class Vlan(Executor):
6+
7+
ARG_NAME = "vlan_name"
8+
9+
def __init__(self, match_engine=None):
10+
super().__init__(match_engine)
11+
self.ret_temp = {}
12+
self.ns = ''
13+
14+
def get_all_args(self, ns=""):
15+
req = MatchRequest(db="CONFIG_DB", table="VLAN", key_pattern="*", ns=ns)
16+
ret = self.match_engine.fetch(req)
17+
all_vlans = ret["keys"]
18+
return [key.split("|")[-1] for key in all_vlans]
19+
20+
def execute(self, params_dict):
21+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
22+
vlan_name = params_dict[Vlan.ARG_NAME]
23+
self.ns = params_dict["namespace"]
24+
self.init_vlan_config_info(vlan_name)
25+
self.init_vlan_appl_info(vlan_name)
26+
self.init_state_vlan_info(vlan_name)
27+
self.init_asic_vlan_info(vlan_name)
28+
return self.ret_temp
29+
30+
def init_vlan_config_info(self, vlan_name):
31+
req = MatchRequest(db="CONFIG_DB", table="VLAN", key_pattern=vlan_name, ns=self.ns)
32+
ret = self.match_engine.fetch(req)
33+
if not ret["error"] and len(ret["keys"]) != 0:
34+
self.ret_temp[req.db]["keys"] = ret["keys"]
35+
else:
36+
self.ret_temp[req.db]["tables_not_found"] = [req.table]
37+
38+
def init_vlan_appl_info(self, vlan_name):
39+
req = MatchRequest(db="APPL_DB", table="VLAN_TABLE", key_pattern=vlan_name, ns=self.ns)
40+
ret = self.match_engine.fetch(req)
41+
if not ret["error"] and len(ret["keys"]) != 0:
42+
self.ret_temp[req.db]["keys"] = ret["keys"]
43+
else:
44+
self.ret_temp[req.db]["tables_not_found"] = [req.table]
45+
46+
def init_state_vlan_info(self, vlan_name):
47+
req = MatchRequest(db="STATE_DB", table="VLAN_TABLE", key_pattern=vlan_name, ns=self.ns)
48+
ret = self.match_engine.fetch(req)
49+
if not ret["error"] and len(ret["keys"]) != 0:
50+
self.ret_temp[req.db]["keys"] = ret["keys"]
51+
else:
52+
self.ret_temp[req.db]["tables_not_found"] = [req.table]
53+
54+
def init_asic_vlan_info(self, vlan_name):
55+
# Convert 'Vlanxxx' to 'xxx'
56+
if vlan_name[0:4] != "Vlan" or not vlan_name[4:].isnumeric():
57+
self.ret_temp["ASIC_DB"]["tables_not_found"] =["ASIC_STATE:SAI_OBJECT_TYPE_VLAN"]
58+
return {}, {}
59+
vlan_num = int(vlan_name[4:])
60+
61+
# Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:*" in which SAI_VLAN_ATTR_VLAN_ID = vlan_num
62+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID",
63+
value=str(vlan_num), ns=self.ns)
64+
ret = self.match_engine.fetch(req)
65+
if not ret["error"] and len(ret["keys"]) != 0:
66+
self.ret_temp[req.db]["keys"] = ret["keys"]
67+
else:
68+
self.ret_temp[req.db]["tables_not_found"] = [req.table]
69+

dump/plugins/vlan_member.py

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
from .executor import Executor
2+
from dump.match_infra import MatchRequest
3+
from dump.helper import create_template_dict
4+
5+
class Vlan_Member(Executor):
6+
7+
ARG_NAME = "vlan_member_name"
8+
9+
def __init__(self, match_engine=None):
10+
super().__init__(match_engine)
11+
self.ret_temp = {}
12+
self.ns = ''
13+
14+
def get_all_args(self, ns=""):
15+
req = MatchRequest(db="CONFIG_DB", table="VLAN_MEMBER", key_pattern="*", ns=ns)
16+
ret = self.match_engine.fetch(req)
17+
all_vlans = ret["keys"]
18+
return [key.split("|",1)[-1] for key in all_vlans]
19+
20+
def execute(self, params_dict):
21+
self.ret_temp = create_template_dict(dbs=["CONFIG_DB", "APPL_DB", "ASIC_DB", "STATE_DB"])
22+
vlan_member_name = params_dict[Vlan_Member.ARG_NAME]
23+
vlan_member_name_list = vlan_member_name.split('|', 1)
24+
if len(vlan_member_name_list) < 2:
25+
self.ret_temp["CONFIG_DB"]["tables_not_found"].append("VLAN_MEMBER")
26+
self.ret_temp["APPL_DB"]["tables_not_found"].append("VLAN_MEMBER_TABLE")
27+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT")
28+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER")
29+
self.ret_temp["STATE_DB"]["tables_not_found"].append("VLAN_MEMBER_TABLE")
30+
return self.ret_temp
31+
vlan_name = vlan_member_name_list[0]
32+
member_name = vlan_member_name_list[1]
33+
self.ns = params_dict["namespace"]
34+
self.init_vlan_member_config_info(vlan_name, member_name)
35+
self.init_vlan_member_appl_info(vlan_name, member_name)
36+
self.init_state_vlan_member_info(vlan_name, member_name)
37+
self.init_asic_vlan_member_info(vlan_name, member_name)
38+
return self.ret_temp
39+
40+
def init_vlan_member_config_info(self, vlan_name, member_name):
41+
req = MatchRequest(db="CONFIG_DB", table="VLAN_MEMBER", key_pattern=vlan_name+'|'+member_name+"*", ns=self.ns)
42+
ret = self.match_engine.fetch(req)
43+
if not ret["error"] and len(ret["keys"]) != 0:
44+
for mem in ret["keys"]:
45+
self.ret_temp[req.db]["keys"].append(mem)
46+
else:
47+
self.ret_temp[req.db]["tables_not_found"].append(req.table)
48+
49+
def init_vlan_member_appl_info(self, vlan_name, member_name):
50+
req = MatchRequest(db="APPL_DB", table="VLAN_MEMBER_TABLE", key_pattern=vlan_name+':'+member_name+"*", ns=self.ns)
51+
ret = self.match_engine.fetch(req)
52+
if not ret["error"] and len(ret["keys"]) != 0:
53+
for mem in ret["keys"]:
54+
self.ret_temp[req.db]["keys"].append(mem)
55+
else:
56+
self.ret_temp[req.db]["tables_not_found"].append(req.table)
57+
58+
def init_state_vlan_member_info(self, vlan_name, member_name):
59+
req = MatchRequest(db="STATE_DB", table="VLAN_MEMBER_TABLE", key_pattern=vlan_name+'|'+member_name+"*", ns=self.ns)
60+
ret = self.match_engine.fetch(req)
61+
if not ret["error"] and len(ret["keys"]) != 0:
62+
for mem in ret["keys"]:
63+
self.ret_temp[req.db]["keys"].append(mem)
64+
else:
65+
self.ret_temp[req.db]["tables_not_found"].append(req.table)
66+
67+
def init_asic_vlan_member_info(self, vlan_name, member_name):
68+
69+
bridge_ret = {}
70+
member_ret = {}
71+
72+
# Convert 'Vlanxxx' to 'xxx'
73+
if vlan_name[0:4] != "Vlan" or not vlan_name[4:].isnumeric():
74+
self.ret_temp["ASIC_DB"]["tables_not_found"] =["ASIC_STATE:SAI_OBJECT_TYPE_VLAN"]
75+
return
76+
vlan_num = int(vlan_name[4:])
77+
78+
# Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN:*" in which SAI_VLAN_ATTR_VLAN_ID = vlan_num and store OID part of table name
79+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN", key_pattern="*", field="SAI_VLAN_ATTR_VLAN_ID",
80+
value=str(vlan_num), ns=self.ns)
81+
vlan_ret = self.match_engine.fetch(req)
82+
# Example contents of vlan_ret:
83+
# {'error': '', 'keys': ['ASIC_STATE:SAI_OBJECT_TYPE_VLAN:oid:0x26000000000618'], 'return_values': {}}
84+
if not vlan_ret["error"] and len(vlan_ret["keys"]) != 0:
85+
vlan_oid=vlan_ret['keys'][0].split(':',2)[2]
86+
else:
87+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT")
88+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER")
89+
return
90+
91+
# Find OID of vlan member - find a table named ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:* whose SAI_HOSTIF_ATTR_NAME is the member name,
92+
# and read the member OID from SAI_HOSTIF_ATTR_OBJ_ID in that table
93+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", key_pattern="*", field="SAI_HOSTIF_ATTR_NAME",
94+
value=member_name, return_fields=["SAI_HOSTIF_ATTR_OBJ_ID"], ns=self.ns)
95+
hostif_ret = self.match_engine.fetch(req)
96+
# Example contents of hostif_ret:
97+
# {'error': '', 'keys': ['ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd0000000003c1'],
98+
# 'return_values': {'ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd0000000003c1': {'SAI_HOSTIF_ATTR_OBJ_ID': 'oid:0x10000000002f6'}}}
99+
member_oid = ""
100+
if not hostif_ret["error"] and len(hostif_ret["keys"]) != 0:
101+
sai_hostif_obj_key = hostif_ret["keys"][-1]
102+
if sai_hostif_obj_key in hostif_ret["return_values"] and "SAI_HOSTIF_ATTR_OBJ_ID" in hostif_ret["return_values"][sai_hostif_obj_key]:
103+
member_oid = hostif_ret["return_values"][sai_hostif_obj_key]["SAI_HOSTIF_ATTR_OBJ_ID"]
104+
105+
# Find the table named "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT:oid:*" in which field SAI_BRIDGE_PORT_ATTR_PORT_ID = vlan member OID
106+
if member_oid:
107+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT", key_pattern="*",
108+
field="SAI_BRIDGE_PORT_ATTR_PORT_ID", value=member_oid, ns=self.ns)
109+
bridge_ret = self.match_engine.fetch(req)
110+
# Example contents of bridge_ret:
111+
# {'error': '', 'keys': ['ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT:oid:0x3a00000000061b'], 'return_values': {}}
112+
113+
# Find the tables named "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER:oid:*" in which field SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID = SAI object bridge port OID.
114+
# There should be one of these for each vlan in which the port is a member.
115+
if bridge_ret and not bridge_ret["error"] and len(bridge_ret["keys"]) != 0:
116+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", key_pattern="*",
117+
field="SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID", value=bridge_ret['keys'][0].split(':',2)[2], ns=self.ns)
118+
member_ret = self.match_engine.fetch(req)
119+
# Example contents of member_ret:
120+
# {'error': '', 'keys': ['ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER:oid:0x2700000000061c', 'ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER:oid:0x2700000000061d'], 'return_values': {}}
121+
122+
# Since this function is invoked for a given vlan and member, we expect that member_ret contains exactly one entry describing the port's
123+
# membership in that vlan if it is a member, and zero if it is not. Only output the vlan member and bridge port tables
124+
# if this port is a member of this vlan.
125+
if member_ret and not member_ret["error"] and len(member_ret["keys"]) != 0:
126+
is_member = False
127+
for member_with_vlan in member_ret["keys"]:
128+
req = MatchRequest(db="ASIC_DB", table="ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER", key_pattern=member_with_vlan.split(":",2)[2],
129+
field="SAI_VLAN_MEMBER_ATTR_VLAN_ID", value=vlan_oid, ns=self.ns)
130+
vlan_bridge_ret = self.match_engine.fetch(req)
131+
# Example contents of vlan_bridge_ret:
132+
# {'error': '', 'keys': ['ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER:oid:0x2700000000061c'], 'return_values': {}}
133+
if not vlan_bridge_ret["error"] and len(vlan_bridge_ret["keys"]) != 0:
134+
self.ret_temp[req.db]["keys"].append(vlan_bridge_ret["keys"][0])
135+
self.ret_temp[req.db]["keys"].append(bridge_ret["keys"][0])
136+
is_member = True
137+
if not is_member:
138+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER")
139+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT")
140+
else:
141+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER")
142+
self.ret_temp["ASIC_DB"]["tables_not_found"].append("ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT")
143+
144+

tests/dump_input/vlan/appl_db.json

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"VLAN_TABLE:Vlan2": {
3+
"admin_status": "up",
4+
"host_ifname": "",
5+
"mac": "7c:fe:90:f5:36:40",
6+
"mtu": "9100"
7+
},
8+
"VLAN_TABLE:Vlan3": {
9+
"admin_status": "up",
10+
"host_ifname": "",
11+
"mac": "7c:fe:90:f5:36:40",
12+
"mtu": "9100"
13+
},
14+
"VLAN_MEMBER_TABLE:Vlan3:Ethernet8": {
15+
"tagging_mode": "tagged"
16+
},
17+
"VLAN_MEMBER_TABLE:Vlan3:Ethernet0": {
18+
"tagging_mode": "tagged"
19+
},
20+
"VLAN_TABLE:Vlan4": {
21+
"admin_status": "up",
22+
"host_ifname": "",
23+
"mac": "7c:fe:90:f5:36:40",
24+
"mtu": "9100"
25+
},
26+
"VLAN_MEMBER_TABLE:Vlan4:Ethernet16": {
27+
"tagging_mode": "tagged"
28+
},
29+
"VLAN_MEMBER_TABLE:Vlan4:Ethernet24": {
30+
"tagging_mode": "tagged"
31+
},
32+
"VLAN_TABLE:Vlan7": {
33+
"admin_status": "up",
34+
"host_ifname": "",
35+
"mac": "7c:fe:90:f5:36:40",
36+
"mtu": "9100"
37+
},
38+
"VLAN_MEMBER_TABLE:Vlan7:Ethernet48": {
39+
"tagging_mode": "tagged"
40+
},
41+
"VLAN_MEMBER_TABLE:Vlan7:Ethernet56": {
42+
"tagging_mode": "tagged"
43+
},
44+
"VLAN_TABLE:Vlan8": {
45+
"admin_status": "up",
46+
"host_ifname": "",
47+
"mac": "7c:fe:90:f5:36:40",
48+
"mtu": "9100"
49+
},
50+
"VLAN_MEMBER_TABLE:Vlan8:Ethernet64": {
51+
"tagging_mode": "tagged"
52+
},
53+
"VLAN_MEMBER_TABLE:Vlan8:Ethernet72": {
54+
"tagging_mode": "tagged"
55+
}
56+
}

0 commit comments

Comments
 (0)