Skip to content

Commit

Permalink
[test_route_flap] Route flap multi-dut fix if the selected duthost ha…
Browse files Browse the repository at this point in the history
…s downstream neighbors (sonic-net#11677)

* route-flap: Generic fix for issue-11460

* flake8 fix
  • Loading branch information
sanjair-git authored Feb 23, 2024
1 parent b5d63cf commit 466bbfa
Showing 1 changed file with 105 additions and 6 deletions.
111 changes: 105 additions & 6 deletions tests/route/test_route_flap.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,96 @@ def get_ptf_recv_ports(duthost, tbinfo):
return recv_ports


def get_neighbor_info(duthost, dev_port, tbinfo):
"""
This function returns the neighbor type of
the chosen dev_port based on route info
Args:
duthost: DUT belong to the testbed.
dev_port: Chosen dev_port based on route info
tbinfo: A fixture to gather information about the testbed.
"""
neighbor_type = ''
config_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts']
neighs = config_facts['BGP_NEIGHBOR']
dev_neigh_mdata = config_facts['DEVICE_NEIGHBOR_METADATA'] if 'DEVICE_NEIGHBOR_METADATA' in config_facts else {}
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
nbr_port_map = mg_facts['minigraph_port_name_to_alias_map'] \
if 'minigraph_port_name_to_alias_map' in mg_facts else {}
for neighbor in neighs:
local_ip = neighs[neighbor]['local_addr']
nbr_port = get_port_by_ip(config_facts, local_ip)
if 'Ethernet' in nbr_port:
for p_key, p_value in nbr_port_map.items():
if p_value == nbr_port:
nbr_port = p_key
if dev_port == nbr_port:
neighbor_name = neighs[neighbor]['name']
for k, v in dev_neigh_mdata.items():
if k == neighbor_name:
neighbor_type = v['type']
return neighbor_type


def get_port_by_ip(config_facts, ipaddr):
"""
This function returns port name based on ip address
"""
if ':' in ipaddr:
iptype = "ipv6"
else:
iptype = "ipv4"

intf = {}
intf.update(config_facts.get('INTERFACE', {}))
if "PORTCHANNEL_INTERFACE" in config_facts:
intf.update(config_facts['PORTCHANNEL_INTERFACE'])
for a_intf in intf:
for addrs in intf[a_intf]:
intf_ip = addrs.split('/')
if iptype == 'ipv6' and ':' in intf_ip[0] and intf_ip[0].lower() == ipaddr.lower():
return a_intf
elif iptype == 'ipv4' and ':' not in intf_ip[0] and intf_ip[0] == ipaddr:
return a_intf

raise Exception("Did not find port for IP %s" % ipaddr)


def get_all_ptf_recv_ports(duthosts, tbinfo, recv_neigh_list):
"""
This function returns all the ptf ports of
all the duts w.r.t received neighbors' list, even for multi dut chassis
"""
recv_ports = []
for duthost in duthosts:
if duthost.is_supervisor_node():
continue
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
for interface, neighbor in mg_facts["minigraph_neighbors"].items():
if neighbor['name'] in recv_neigh_list and interface in mg_facts["minigraph_ptf_indices"]:
ptf_idx = mg_facts["minigraph_ptf_indices"][interface]
recv_ports.append(ptf_idx)
return recv_ports


def get_all_recv_neigh(duthosts, neigh_type):
"""
This function returns all the neighbors of
same type for dut, including multi dut chassis
"""
recv_neigh_list = []
for duthost in duthosts:
if duthost.is_supervisor_node():
continue
config_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts']
device_neighbor_metadata = config_facts['DEVICE_NEIGHBOR_METADATA']
for k, v in device_neighbor_metadata.items():
if v['type'] == neigh_type:
recv_neigh_list.append(k)
return recv_neigh_list


def get_ptf_send_ports(duthost, tbinfo, dev_port):
if tbinfo['topo']['name'] in ['t0', 't1-lag', 'm0']:
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
Expand Down Expand Up @@ -132,7 +222,7 @@ def check_route(duthost, route, dev_port, operation):
"Route {} was not announced {}".format(route, result))


def send_recv_ping_packet(ptfadapter, ptf_send_port, ptf_recv_ports, dst_mac, exp_src_mac, src_ip, dst_ip):
def send_recv_ping_packet(ptfadapter, ptf_send_port, ptf_recv_ports, dst_mac, exp_src_mac, src_ip, dst_ip, tbinfo):
# use ptf sender interface mac for easy identify testing packets
src_mac = ptfadapter.dataplane.get_mac(0, ptf_send_port)
pkt = testutils.simple_icmp_packet(
Expand All @@ -142,6 +232,9 @@ def send_recv_ping_packet(ptfadapter, ptf_send_port, ptf_recv_ports, dst_mac, ex
ext_pkt['Ether'].src = exp_src_mac

masked_exp_pkt = Mask(ext_pkt)
# Mask src_mac for T2 multi-dut chassis, since the packet can be received on any of the dut's ptf-ports
if 't2' in tbinfo["topo"]["name"]:
masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src")
masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst")
masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "tos")
masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "len")
Expand Down Expand Up @@ -227,7 +320,7 @@ def get_internal_interfaces(duthost):

# 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])
internal_intfs += voq_inband_interfaces

return internal_intfs

Expand Down Expand Up @@ -339,7 +432,13 @@ def test_route_flap(duthosts, tbinfo, ptfhost, ptfadapter,

# choose one ptf port to send msg
ptf_send_port = get_ptf_send_ports(duthost, tbinfo, dev_port)
ptf_recv_ports = get_ptf_recv_ports(duthost, tbinfo)

# Get the list of ptf ports to receive msg, even for multi-dut scenario
neighbor_type = get_neighbor_info(duthost, dev_port, tbinfo)
recv_neigh_list = get_all_recv_neigh(duthosts, neighbor_type)
logger.info("Receiving ports neighbor list : {}".format(recv_neigh_list))
ptf_recv_ports = get_all_ptf_recv_ports(duthosts, tbinfo, recv_neigh_list)
logger.info("Receiving ptf ports list : {}".format(ptf_recv_ports))

exabgp_port = get_exabgp_port(duthost, tbinfo, dev_port)
logger.info("exabgp_port = %d" % exabgp_port)
Expand Down Expand Up @@ -367,23 +466,23 @@ def switch(x):

# test link status
send_recv_ping_packet(
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip)
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip, tbinfo)

withdraw_route(ptf_ip, dst_prefix, nexthop, exabgp_port, aspath)
# Check if route is withdraw with first 3 routes
if route_index < 4:
time.sleep(1)
check_route(duthost, dst_prefix, dev_port, WITHDRAW)
send_recv_ping_packet(
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip)
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip, tbinfo)

announce_route(ptf_ip, dst_prefix, nexthop, exabgp_port, aspath)
# Check if route is announced with first 3 routes
if route_index < 4:
time.sleep(1)
check_route(duthost, dst_prefix, dev_port, ANNOUNCE)
send_recv_ping_packet(
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip)
ptfadapter, ptf_send_port, ptf_recv_ports, vlan_mac, dut_mac, ptf_ip, ping_ip, tbinfo)

route_index += 1

Expand Down

0 comments on commit 466bbfa

Please sign in to comment.