|
| 1 | +import logging |
| 2 | +import pytest |
| 3 | +import random |
| 4 | + |
| 5 | +from ptf import testutils |
| 6 | +from tests.common.dualtor.dual_tor_mock import * |
| 7 | +from tests.common.dualtor.dual_tor_utils import get_t1_ptf_ports |
| 8 | +from tests.common.dualtor.dual_tor_utils import crm_neighbor_checker |
| 9 | +from tests.common.dualtor.dual_tor_utils import build_packet_to_server |
| 10 | +from tests.common.dualtor.dual_tor_utils import mux_cable_server_ip |
| 11 | +from tests.common.dualtor.server_traffic_utils import ServerTrafficMonitor |
| 12 | +from tests.common.dualtor.tunnel_traffic_utils import tunnel_traffic_monitor |
| 13 | +from tests.common.fixtures.ptfhost_utils import run_icmp_responder |
| 14 | +from tests.common.fixtures.ptfhost_utils import run_garp_service |
| 15 | +from tests.common.fixtures.ptfhost_utils import change_mac_addresses |
| 16 | +from tests.common.utilities import dump_scapy_packet_show_output |
| 17 | + |
| 18 | + |
| 19 | +pytestmark = [ |
| 20 | + pytest.mark.topology('t0'), |
| 21 | + pytest.mark.usefixtures('apply_mock_dual_tor_tables', |
| 22 | + 'apply_mock_dual_tor_kernel_configs', |
| 23 | + 'run_garp_service', |
| 24 | + 'run_icmp_responder') |
| 25 | +] |
| 26 | + |
| 27 | + |
| 28 | +NEW_NEIGHBOR_IPV4_ADDR = "192.168.0.100" |
| 29 | +NEW_NEIGHBOR_HWADDR = "02:AA:BB:CC:DD:EE" |
| 30 | + |
| 31 | + |
| 32 | +@pytest.fixture(scope="function") |
| 33 | +def announce_new_neighbor(ptfadapter, rand_selected_dut, tbinfo): |
| 34 | + """Utility fixture to announce new neighbor from a mux port.""" |
| 35 | + |
| 36 | + def _announce_new_neighbor_gen(): |
| 37 | + """Generator to announce the neighbor to a different interface at each iteration.""" |
| 38 | + for dut_iface in dut_ifaces: |
| 39 | + update_iface_func = yield dut_iface |
| 40 | + if callable(update_iface_func): |
| 41 | + update_iface_func(dut_iface) |
| 42 | + ptf_iface = dut_to_ptf_intf_map[dut_iface] |
| 43 | + ptf_iface_mac = ptfadapter.dataplane.ports[(0, ptf_iface)].mac() |
| 44 | + garp_packet = testutils.simple_arp_packet( |
| 45 | + eth_src=NEW_NEIGHBOR_HWADDR, |
| 46 | + hw_snd=NEW_NEIGHBOR_HWADDR, |
| 47 | + ip_snd=NEW_NEIGHBOR_IPV4_ADDR, |
| 48 | + ip_tgt=NEW_NEIGHBOR_IPV4_ADDR, |
| 49 | + arp_op=2 |
| 50 | + ) |
| 51 | + logging.info( |
| 52 | + "GARP packet to announce new neighbor %s to mux interface %s:\n%s", |
| 53 | + NEW_NEIGHBOR_IPV4_ADDR, dut_iface, dump_scapy_packet_show_output(garp_packet) |
| 54 | + ) |
| 55 | + testutils.send(ptfadapter, int(ptf_iface), garp_packet, count=5) |
| 56 | + # let the generator stops here to allow the caller to execute testings |
| 57 | + yield |
| 58 | + |
| 59 | + dut_to_ptf_intf_map = rand_selected_dut.get_extended_minigraph_facts(tbinfo)['minigraph_ptf_indices'] |
| 60 | + mux_configs = mux_cable_server_ip(rand_selected_dut) |
| 61 | + dut_ifaces = mux_configs.keys() |
| 62 | + random.shuffle(dut_ifaces) |
| 63 | + return _announce_new_neighbor_gen() |
| 64 | + |
| 65 | + |
| 66 | +@pytest.fixture(autouse=True) |
| 67 | +def cleanup_arp(duthosts): |
| 68 | + """Cleanup arp entries after test.""" |
| 69 | + yield |
| 70 | + for duthost in duthosts: |
| 71 | + duthost.shell("sonic-clear arp") |
| 72 | + |
| 73 | + |
| 74 | +def test_mac_move( |
| 75 | + announce_new_neighbor, apply_active_state_to_orchagent, |
| 76 | + conn_graph_facts, ptfadapter, |
| 77 | + rand_selected_dut, set_crm_polling_interval, |
| 78 | + tbinfo, tunnel_traffic_monitor, vmhost |
| 79 | +): |
| 80 | + tor = rand_selected_dut |
| 81 | + ptf_t1_intf = random.choice(get_t1_ptf_ports(tor, tbinfo)) |
| 82 | + ptf_t1_intf_index = int(ptf_t1_intf.strip("eth")) |
| 83 | + |
| 84 | + # new neighbor learnt on an active port |
| 85 | + test_port = next(announce_new_neighbor) |
| 86 | + announce_new_neighbor.send(None) |
| 87 | + logging.info("let new neighbor learnt on active port %s", test_port) |
| 88 | + pkt, exp_pkt = build_packet_to_server(tor, ptfadapter, NEW_NEIGHBOR_IPV4_ADDR) |
| 89 | + tunnel_monitor = tunnel_traffic_monitor(tor, existing=False) |
| 90 | + server_traffic_monitor = ServerTrafficMonitor( |
| 91 | + tor, vmhost, test_port, |
| 92 | + conn_graph_facts, exp_pkt, existing=True |
| 93 | + ) |
| 94 | + with crm_neighbor_checker(tor), tunnel_monitor, server_traffic_monitor: |
| 95 | + testutils.send(ptfadapter, ptf_t1_intf_index, pkt, count=10) |
| 96 | + |
| 97 | + # mac move to a standby port |
| 98 | + test_port = next(announce_new_neighbor) |
| 99 | + announce_new_neighbor.send(lambda iface: set_dual_tor_state_to_orchagent(tor, "standby", [iface])) |
| 100 | + logging.info("mac move to a standby port %s", test_port) |
| 101 | + pkt, exp_pkt = build_packet_to_server(tor, ptfadapter, NEW_NEIGHBOR_IPV4_ADDR) |
| 102 | + tunnel_monitor = tunnel_traffic_monitor(tor, existing=True) |
| 103 | + server_traffic_monitor = ServerTrafficMonitor( |
| 104 | + tor, vmhost, test_port, |
| 105 | + conn_graph_facts, exp_pkt, existing=False |
| 106 | + ) |
| 107 | + with crm_neighbor_checker(tor), tunnel_monitor, server_traffic_monitor: |
| 108 | + testutils.send(ptfadapter, ptf_t1_intf_index, pkt, count=10) |
| 109 | + |
| 110 | + # standby forwarding check after fdb ageout/flush |
| 111 | + tor.shell("fdbclear") |
| 112 | + server_traffic_monitor = ServerTrafficMonitor( |
| 113 | + tor, vmhost, test_port, |
| 114 | + conn_graph_facts, exp_pkt, existing=False |
| 115 | + ) |
| 116 | + with crm_neighbor_checker(tor), tunnel_monitor, server_traffic_monitor: |
| 117 | + testutils.send(ptfadapter, ptf_t1_intf_index, pkt, count=10) |
| 118 | + |
| 119 | + # mac move to another active port |
| 120 | + test_port = next(announce_new_neighbor) |
| 121 | + announce_new_neighbor.send(None) |
| 122 | + logging.info("mac move to another active port %s", test_port) |
| 123 | + pkt, exp_pkt = build_packet_to_server(tor, ptfadapter, NEW_NEIGHBOR_IPV4_ADDR) |
| 124 | + tunnel_monitor = tunnel_traffic_monitor(tor, existing=False) |
| 125 | + server_traffic_monitor = ServerTrafficMonitor( |
| 126 | + tor, vmhost, test_port, |
| 127 | + conn_graph_facts, exp_pkt, existing=True |
| 128 | + ) |
| 129 | + with crm_neighbor_checker(tor), tunnel_monitor, server_traffic_monitor: |
| 130 | + testutils.send(ptfadapter, ptf_t1_intf_index, pkt, count=10) |
| 131 | + |
| 132 | + # active forwarding check after fdb ageout/flush |
| 133 | + tor.shell("fdbclear") |
| 134 | + server_traffic_monitor = ServerTrafficMonitor( |
| 135 | + tor, vmhost, test_port, |
| 136 | + conn_graph_facts, exp_pkt, existing=False |
| 137 | + ) |
| 138 | + with crm_neighbor_checker(tor), tunnel_monitor, server_traffic_monitor: |
| 139 | + testutils.send(ptfadapter, ptf_t1_intf_index, pkt, count=10) |
0 commit comments