Skip to content

Commit

Permalink
[debug dump util] Portchannel module added (#1853)
Browse files Browse the repository at this point in the history
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'
  • Loading branch information
vivekrnv authored Nov 10, 2021
1 parent 50bbfa0 commit 7f0bbd9
Show file tree
Hide file tree
Showing 8 changed files with 567 additions and 0 deletions.
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
18 changes: 18 additions & 0 deletions tests/dump_input/portchannel/appl_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"LAG_TABLE:PortChannel002": {
"oper_status": "up",
"mtu": "9100",
"admin_status": "up"
},
"LAG_TABLE:PortChannel001": {
"oper_status": "up",
"mtu": "9100",
"admin_status": "up"
},
"LAG_MEMBER_TABLE:PortChannel001:Ethernet4": {
"status": "enabled"
},
"LAG_MEMBER_TABLE:PortChannel001:Ethernet0": {
"status": "enabled"
}
}
34 changes: 34 additions & 0 deletions tests/dump_input/portchannel/asic_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x2000000000d17":{
"SAI_LAG_ATTR_PORT_VLAN_ID": "1"
},
"ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x20000000004d3": {
"NULL": "NULL"
},
"ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER:oid:0x1b000000000d18": {
"SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE": "false",
"SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE": "false",
"SAI_LAG_MEMBER_ATTR_LAG_ID": "oid:0x2000000000d17",
"SAI_LAG_MEMBER_ATTR_PORT_ID": "oid:0x10000000002cc"
},
"ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER:oid:0x1b000000000d1a": {
"SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE": "false",
"SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE": "false",
"SAI_LAG_MEMBER_ATTR_LAG_ID": "oid:0x2000000000d17",
"SAI_LAG_MEMBER_ATTR_PORT_ID": "oid:0x100000000093e"
},
"ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd000000000cdf": {
"SAI_HOSTIF_ATTR_NAME": "Ethernet0",
"SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x10000000002cc",
"SAI_HOSTIF_ATTR_OPER_STATUS": "true",
"SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV",
"SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_STRIP"
},
"ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF:oid:0xd000000000acd": {
"SAI_HOSTIF_ATTR_NAME": "Ethernet4",
"SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x100000000093e",
"SAI_HOSTIF_ATTR_OPER_STATUS": "true",
"SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV",
"SAI_HOSTIF_ATTR_VLAN_TAG": "SAI_HOSTIF_VLAN_TAG_STRIP"
}
}
29 changes: 29 additions & 0 deletions tests/dump_input/portchannel/config_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"PORTCHANNEL|PortChannel001": {
"admin_status": "up",
"lacp_key": "auto",
"min_links": "1",
"mtu": "9100"
},
"PORTCHANNEL|PortChannel002": {
"admin_status": "up",
"lacp_key": "auto",
"min_links": "1",
"mtu": "9100"
},
"PORTCHANNEL|PortChannel003": {
"admin_status": "up",
"lacp_key": "auto",
"min_links": "1",
"mtu": "9100"
},
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet0": {
"NULL" : "NULL"
},
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet4": {
"NULL" : "NULL"
},
"PORTCHANNEL_MEMBER|PortChannel001|Ethernet8": {
"NULL" : "NULL"
}
}
54 changes: 54 additions & 0 deletions tests/dump_input/portchannel/state_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"LAG_TABLE|PortChannel001":{
"runner.active": "true",
"runner.fallback": "false",
"runner.fast_rate": "false",
"setup.kernel_team_mode_name": "loadbalance",
"setup.pid": "27",
"state": "ok",
"team_device.ifinfo.dev_addr": "1c:34:da:1c:9f:00",
"team_device.ifinfo.ifindex": "137"
},
"LAG_TABLE|PortChannel002":{
"runner.active": "true",
"runner.fallback": "false",
"runner.fast_rate": "false",
"setup.kernel_team_mode_name": "loadbalance",
"setup.pid": "35",
"state": "ok",
"team_device.ifinfo.dev_addr": "1c:34:da:1c:9f:00",
"team_device.ifinfo.ifindex": "138"
},
"LAG_MEMBER_TABLE|PortChannel001|Ethernet4":{
"ifinfo.dev_addr": "1c:34:da:1c:9f:00",
"ifinfo.ifindex": "203",
"link.up": "true",
"link_watches.list.link_watch_0.up": "true",
"runner.actor_lacpdu_info.port": "5",
"runner.actor_lacpdu_info.state": "69",
"runner.actor_lacpdu_info.system": "1c:34:da:1c:9f:00",
"runner.aggregator.id": "0",
"runner.aggregator.selected": "false",
"runner.partner_lacpdu_info.port": "0",
"runner.partner_lacpdu_info.state": "2",
"runner.partner_lacpdu_info.system": "00:00:00:00:00:00",
"runner.selected": "false",
"runner.state": "defaulted"
},
"LAG_MEMBER_TABLE|PortChannel001|Ethernet0":{
"ifinfo.dev_addr": "1c:34:da:1c:9f:00",
"ifinfo.ifindex": "202",
"link.up": "true",
"link_watches.list.link_watch_0.up": "true",
"runner.actor_lacpdu_info.port": "0",
"runner.actor_lacpdu_info.state": "69",
"runner.actor_lacpdu_info.system": "1c:34:da:1c:9f:00",
"runner.aggregator.id": "0",
"runner.aggregator.selected": "false",
"runner.partner_lacpdu_info.port": "0",
"runner.partner_lacpdu_info.state": "2",
"runner.partner_lacpdu_info.system": "00:00:00:00:00:00",
"runner.selected": "false",
"runner.state": "defaulted"
}
}
Loading

0 comments on commit 7f0bbd9

Please sign in to comment.