Skip to content

Commit 7f0bbd9

Browse files
authored
[debug dump util] Portchannel module added (sonic-net#1853)
What I did Added the PortChannel and PortChannel_Member Modules to the Debug Dump Utility Added the Corresponding UT's Note: Portchannel member accepts the keys of PORTCHANNEL_MEMBER table as the Identifier and since the key contains this character ("|"), this should be escaped using single quotes while using the utility i.e. dump state portchannel_member 'PortChannel001|Ethernet4,PortChannel001|Ethernet8'
1 parent 50bbfa0 commit 7f0bbd9

File tree

8 files changed

+567
-0
lines changed

8 files changed

+567
-0
lines changed

dump/plugins/portchannel.py

+113
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

+84
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
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"LAG_TABLE:PortChannel002": {
3+
"oper_status": "up",
4+
"mtu": "9100",
5+
"admin_status": "up"
6+
},
7+
"LAG_TABLE:PortChannel001": {
8+
"oper_status": "up",
9+
"mtu": "9100",
10+
"admin_status": "up"
11+
},
12+
"LAG_MEMBER_TABLE:PortChannel001:Ethernet4": {
13+
"status": "enabled"
14+
},
15+
"LAG_MEMBER_TABLE:PortChannel001:Ethernet0": {
16+
"status": "enabled"
17+
}
18+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x2000000000d17":{
3+
"SAI_LAG_ATTR_PORT_VLAN_ID": "1"
4+
},
5+
"ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x20000000004d3": {
6+
"NULL": "NULL"
7+
},
8+
"ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER:oid:0x1b000000000d18": {
9+
"SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE": "false",
10+
"SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE": "false",
11+
"SAI_LAG_MEMBER_ATTR_LAG_ID": "oid:0x2000000000d17",
12+
"SAI_LAG_MEMBER_ATTR_PORT_ID": "oid:0x10000000002cc"
13+
},
14+
"ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER:oid:0x1b000000000d1a": {
15+
"SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE": "false",
16+
"SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE": "false",
17+
"SAI_LAG_MEMBER_ATTR_LAG_ID": "oid:0x2000000000d17",
18+
"SAI_LAG_MEMBER_ATTR_PORT_ID": "oid:0x100000000093e"
19+
},
20+
"ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd000000000cdf": {
21+
"SAI_HOSTIF_ATTR_NAME": "Ethernet0",
22+
"SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x10000000002cc",
23+
"SAI_HOSTIF_ATTR_OPER_STATUS": "true",
24+
"SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV",
25+
"SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_STRIP"
26+
},
27+
"ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd000000000acd": {
28+
"SAI_HOSTIF_ATTR_NAME": "Ethernet4",
29+
"SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x100000000093e",
30+
"SAI_HOSTIF_ATTR_OPER_STATUS": "true",
31+
"SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV",
32+
"SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_STRIP"
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"PORTCHANNEL|PortChannel001": {
3+
"admin_status": "up",
4+
"lacp_key": "auto",
5+
"min_links": "1",
6+
"mtu": "9100"
7+
},
8+
"PORTCHANNEL|PortChannel002": {
9+
"admin_status": "up",
10+
"lacp_key": "auto",
11+
"min_links": "1",
12+
"mtu": "9100"
13+
},
14+
"PORTCHANNEL|PortChannel003": {
15+
"admin_status": "up",
16+
"lacp_key": "auto",
17+
"min_links": "1",
18+
"mtu": "9100"
19+
},
20+
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet0": {
21+
"NULL" : "NULL"
22+
},
23+
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet4": {
24+
"NULL" : "NULL"
25+
},
26+
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet8": {
27+
"NULL" : "NULL"
28+
}
29+
}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"LAG_TABLE|PortChannel001":{
3+
"runner.active": "true",
4+
"runner.fallback": "false",
5+
"runner.fast_rate": "false",
6+
"setup.kernel_team_mode_name": "loadbalance",
7+
"setup.pid": "27",
8+
"state": "ok",
9+
"team_device.ifinfo.dev_addr": "1c:34:da:1c:9f:00",
10+
"team_device.ifinfo.ifindex": "137"
11+
},
12+
"LAG_TABLE|PortChannel002":{
13+
"runner.active": "true",
14+
"runner.fallback": "false",
15+
"runner.fast_rate": "false",
16+
"setup.kernel_team_mode_name": "loadbalance",
17+
"setup.pid": "35",
18+
"state": "ok",
19+
"team_device.ifinfo.dev_addr": "1c:34:da:1c:9f:00",
20+
"team_device.ifinfo.ifindex": "138"
21+
},
22+
"LAG_MEMBER_TABLE|PortChannel001|Ethernet4":{
23+
"ifinfo.dev_addr": "1c:34:da:1c:9f:00",
24+
"ifinfo.ifindex": "203",
25+
"link.up": "true",
26+
"link_watches.list.link_watch_0.up": "true",
27+
"runner.actor_lacpdu_info.port": "5",
28+
"runner.actor_lacpdu_info.state": "69",
29+
"runner.actor_lacpdu_info.system": "1c:34:da:1c:9f:00",
30+
"runner.aggregator.id": "0",
31+
"runner.aggregator.selected": "false",
32+
"runner.partner_lacpdu_info.port": "0",
33+
"runner.partner_lacpdu_info.state": "2",
34+
"runner.partner_lacpdu_info.system": "00:00:00:00:00:00",
35+
"runner.selected": "false",
36+
"runner.state": "defaulted"
37+
},
38+
"LAG_MEMBER_TABLE|PortChannel001|Ethernet0":{
39+
"ifinfo.dev_addr": "1c:34:da:1c:9f:00",
40+
"ifinfo.ifindex": "202",
41+
"link.up": "true",
42+
"link_watches.list.link_watch_0.up": "true",
43+
"runner.actor_lacpdu_info.port": "0",
44+
"runner.actor_lacpdu_info.state": "69",
45+
"runner.actor_lacpdu_info.system": "1c:34:da:1c:9f:00",
46+
"runner.aggregator.id": "0",
47+
"runner.aggregator.selected": "false",
48+
"runner.partner_lacpdu_info.port": "0",
49+
"runner.partner_lacpdu_info.state": "2",
50+
"runner.partner_lacpdu_info.system": "00:00:00:00:00:00",
51+
"runner.selected": "false",
52+
"runner.state": "defaulted"
53+
}
54+
}

0 commit comments

Comments
 (0)