Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chassis] [MA] Route flap fix #10206

Merged
merged 8 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions tests/common/devices/multi_asic.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,28 @@ def get_voq_inband_interfaces(self):
)
return voq_inband_interfaces.keys()

def get_portchannel_member(self):
"""
This Function is applicable on packet Chassis, or
any dut that has PORTCHANNEL_MEMBER in config dbs.
Get PORTCHANNEL_MEMBER from config db of all asics.
Returns:
List of [portchannel]. e.g. ["PortChannel101|Ethernet104", "PortChannel01|EthernetBPxx", ...]
{} if VOQ chassis or other dut that doesn't have PORTCHANNEL_MEMBER
"""
if not self.sonichost.is_multi_asic:
return {}
pcs = {}
for asic in self.frontend_asics:
config_facts = self.config_facts(
host=self.hostname, source="running",
namespace=asic.namespace
)['ansible_facts']
pcs.update(
config_facts.get("PORTCHANNEL_MEMBER", {})
)
return pcs.keys()

def run_redis_cmd(self, argv=[], asic_index=DEFAULT_ASIC_ID):
"""
Wrapper function to call run_redis_cmd on sonic_asic.py
Expand Down
46 changes: 35 additions & 11 deletions tests/route/test_route_flap.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,35 @@ def is_dualtor(tbinfo):
return "dualtor" in tbinfo["topo"]["name"]


def get_dev_port_and_route(duthost, asichost, dst_prefix_set):
# Get internal bgp ips for later filtering
internal_bgp_ips = duthost.get_internal_bgp_peers().keys()
# Get voq inband interface for later filtering
def get_internal_interfaces(duthost):
"""
This function returns internal interfaces for any
multi-asic dut, including voq/packet chassis
"""
internal_intfs = []

# First check for packet chassis, or any dut that has PORTCHANNEL_MEMBER in config db
pcs = duthost.get_portchannel_member()
for pc in pcs:
"""
For packet chassis, 'pcs' looks like:
["PortChannel101|Ethernet104", "PortChannel01|Ethernet-BPxx",...]
"""
if 'IB' in pc or 'BP' in pc:
internal_intfs.append(pc)

# Then check for voq chassis: get voq inband interface for later filtering
voq_inband_interfaces = duthost.get_voq_inband_interfaces()
internal_intfs.append([voq_inband_interfaces])

return internal_intfs


def get_dev_port_and_route(duthost, asichost, dst_prefix_set):
dev_port = None
route_to_ping = None
# Get internal interfaces for later filtering
internal_intfs = get_internal_interfaces(duthost)
for dst_prefix in dst_prefix_set:
if dev_port:
break
Expand All @@ -230,20 +252,22 @@ def get_dev_port_and_route(duthost, asichost, dst_prefix_set):
continue
if 'ip' not in per_hop.keys():
continue
if per_hop['ip'] in internal_bgp_ips:
continue
if per_hop['interfaceName'] in voq_inband_interfaces:
continue
if 'IB' in per_hop['interfaceName'] or 'BP' in per_hop['interfaceName']:
if per_hop['interfaceName'] in internal_intfs:
continue
dev_port = per_hop['interfaceName']
port = per_hop['interfaceName']
neigh = duthost.shell("show ip int | grep -w {}".format(port))['stdout']
if neigh == '':
logger.info("{} is still internal interface, skipping".format(port))
else:
dev_port = port
break
else:
dev = json.loads(asichost.run_vtysh(cmd)['stdout'])
for per_hop in dev[route_to_ping][0]['nexthops']:
if 'interfaceName' not in per_hop.keys():
continue
if per_hop['interfaceName'] in voq_inband_interfaces:
# For chassis, even single-asic linecard could have internal interface
if per_hop['interfaceName'] in internal_intfs:
continue
if 'IB' in per_hop['interfaceName'] or 'BP' in per_hop['interfaceName']:
continue
Expand Down