Beispiel #1
0
    def runTest(self):
        pkt = simple_ip_packet(ip_src="192.168.1.1", ip_tos=10)
        exp_pkt = simple_ip_packet(ip_src="192.168.1.1", ip_tos=255)

        mask = Mask(exp_pkt)
        mask.set_do_not_care_scapy(IP, 'chksum')

        send_packet(self, (0, 1), pkt)
        verify_packets(self, mask, device_number=0, ports=[2])
Beispiel #2
0
 def _build_tunnel_packet(outer_src_ip, outer_dst_ip, inner_packet=None):
     """Build the expected tunnel packet."""
     if inner_packet is None:
         exp_pkt = testutils.simple_ip_packet(
             ip_src=outer_src_ip,
             ip_dst=outer_dst_ip,
             pktlen=20
         )
     else:
         exp_pkt = testutils.simple_ipv4ip_packet(
             ip_src=outer_src_ip,
             ip_dst=outer_dst_ip,
             inner_frame=inner_packet
         )
     exp_pkt = mask.Mask(exp_pkt)
     exp_pkt.set_do_not_care_scapy(Ether, "dst")
     exp_pkt.set_do_not_care_scapy(Ether, "src")
     exp_pkt.set_do_not_care_scapy(IP, "ihl")
     exp_pkt.set_do_not_care_scapy(IP, "tos")
     exp_pkt.set_do_not_care_scapy(IP, "len")
     exp_pkt.set_do_not_care_scapy(IP, "id")
     exp_pkt.set_do_not_care_scapy(IP, "flags")
     exp_pkt.set_do_not_care_scapy(IP, "frag")
     exp_pkt.set_do_not_care_scapy(IP, "ttl")
     exp_pkt.set_do_not_care_scapy(IP, "proto")
     exp_pkt.set_do_not_care_scapy(IP, "chksum")
     if inner_packet is None:
         exp_pkt.set_ignore_extra_bytes()
     return exp_pkt
Beispiel #3
0
def build_encapsulated_packet(rand_selected_interface, ptfadapter, rand_selected_dut, tunnel_traffic_monitor):
    """Build the encapsulated packet sent from T1 to ToR."""
    tor = rand_selected_dut
    _, server_ips = rand_selected_interface
    server_ipv4 = server_ips["server_ipv4"].split("/")[0]
    config_facts = tor.get_running_config_facts()
    try:
        peer_ipv4_address = [_["address_ipv4"] for _ in config_facts["PEER_SWITCH"].values()][0]
    except IndexError:
        raise ValueError("Failed to get peer ToR address from CONFIG_DB")

    tor_ipv4_address = [_ for _ in config_facts["LOOPBACK_INTERFACE"]["Loopback0"]
                        if is_ipv4_address(_.split("/")[0])][0]
    tor_ipv4_address = tor_ipv4_address.split("/")[0]

    inner_dscp = random.choice(range(0, 33))
    inner_ttl = random.choice(range(3, 65))
    inner_packet = testutils.simple_ip_packet(
        ip_src="1.1.1.1",
        ip_dst=server_ipv4,
        ip_dscp=inner_dscp,
        ip_ttl=inner_ttl
    )[IP]
    packet = testutils.simple_ipv4ip_packet(
        eth_dst=tor.facts["router_mac"],
        eth_src=ptfadapter.dataplane.get_mac(0, 0),
        ip_src=peer_ipv4_address,
        ip_dst=tor_ipv4_address,
        ip_dscp=inner_dscp,
        ip_ttl=255,
        inner_frame=inner_packet
    )
    logging.info("the encapsulated packet to send:\n%s", tunnel_traffic_monitor._dump_show_str(packet))
    return packet
Beispiel #4
0
    def test_drop_ip_packet_with_wrong_0xffff_chksum(self, duthost, ptfadapter, common_param):
        # GIVEN a random normal ip packet, and manually modify checksum to 0xffff
        # WHEN send the packet to DUT
        # THEN DUT should drop it and add drop count
        (peer_ip_ifaces_pair, ptf_port_idx, pc_ports_map, ptf_indices) = common_param
        pkt = testutils.simple_ip_packet(
            eth_dst=duthost.facts["router_mac"],
            eth_src=ptfadapter.dataplane.get_mac(0, ptf_port_idx),
            ip_src=peer_ip_ifaces_pair[0][0],
            ip_dst=peer_ip_ifaces_pair[1][0])

        pkt.payload.chksum = 0xffff

        out_ifaces = TestIPPacket.parse_interfaces(
            duthost.command("show ip route %s" % peer_ip_ifaces_pair[1][0])["stdout_lines"],
            pc_ports_map)

        duthost.command("portstat -c")
        ptfadapter.dataplane.flush()
        testutils.send(ptfadapter, ptf_port_idx, pkt, self.PKT_NUM)
        time.sleep(5)

        portstat_out = parse_portstat(duthost.command("portstat")["stdout_lines"])

        rx_ok = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_ok"].replace(",", ""))
        rx_drp = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_drp"].replace(",", ""))
        tx_ok = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_ok")
        tx_drp = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_drp")

        pytest_assert(self.PKT_NUM_MIN <= rx_ok <= self.PKT_NUM_MAX, "rx_ok unexpected")
        pytest_assert(self.PKT_NUM_MIN <= rx_drp <= self.PKT_NUM_MAX, "rx_drp unexpected")
        pytest_assert(tx_ok <= self.PKT_NUM_ZERO, "tx_ok unexpected")
        pytest_assert(tx_drp <= self.PKT_NUM_ZERO, "tx_drp unexpected")
def test_non_routable_igmp_pkts(ptfadapter, duthost, setup, tx_dut_ports, pkt_fields, igmp_version, msg_type, ports_info):
    """
    @summary: Verify IGMP non-routable packets dropped by DUT and L3 drop counter incremented
    """
    # IGMP Types:
    # 0x11 = Membership Query
    # 0x12 = Version 1 Membership Report
    # 0x16 = Version 2 Membership Report
    # 0x17 = Leave Group

    # IP destination address according to the RFC 2236:
    # Message Type                  Destination Group
    # ------------                  -----------------
    # General Query                 ALL-SYSTEMS (224.0.0.1)
    # Group-Specific Query          The group being queried
    # Membership Report             The group being reported
    # Leave Message                 ALL-ROUTERS (224.0.0.2)

    # TODO: fix this workaround as of now current PTF and Scapy versions do not support creation of IGMP packets
    # Temporaly created hex of IGMP packet layer
    # Example how to get HEX of specific IGMP packets:
    # v3_membership_query = IGMPv3(type=0x11, mrcode=0, chksum=None)/scapy.contrib.igmpv3.IGMPv3mq(gaddr="224.0.0.1",
    # srcaddrs=["172.16.11.1", "10.0.0.59"], qrv=1, qqic=125, numsrc=2)
    # gr_obj = scapy.contrib.igmpv3.IGMPv3gr(rtype=1, auxdlen=0, maddr="224.2.2.4", numsrc=2, srcaddrs=["172.16.11.1",
    # "10.0.0.59"]).build()
    # v3_membership_report = IGMPv3(type=0x22, mrcode=0, chksum=None)/scapy.contrib.igmpv3.IGMPv3mr(res2=0x00, numgrp=1,
    # records=[gr_obj]).build()
    # The rest packets are build like "simple_igmp_packet" function from PTF testutils.py

    ethernet_dst = {"membership_query": "01:00:5e:00:00:01",
                    "membership_report": "01:00:5e:02:02:04",
                    "leave_group": "01:00:5e:00:00:02"}
    ip_dst = {"membership_query": "224.0.0.1",
              "membership_report": "224.2.2.4",
              "leave_group": "224.0.0.2"}
    igmp_types = {"v1": {"membership_query": "\x11\x00\x0e\xfe\xe0\x00\x00\x01",
                         "membership_report": "\x12\x00\x0b\xf9\xe0\x02\x02\x04"},
                  "v2": {"membership_report": "\x16\x00\x07\xf9\xe0\x02\x02\x04",
                         "leave_group": "\x17\x00\x08\xfd\xe0\x00\x00\x02"},
                  "v3": {"membership_query": "\x11\x00L2\xe0\x00\x00\x01\x01}\x00\x02\xac\x10\x0b\x01\n\x00\x00;",
                         "membership_report": "\"\x009\xa9\x00\x00\x00\x01\x01\x00\x00\x02\xe0\x02\x02\x04\xac\x10\x0b\x01\n\x00\x00;"}
    }

    log_pkt_params(ports_info["dut_iface"], ethernet_dst[msg_type], ports_info["src_mac"], ip_dst[msg_type], pkt_fields["ipv4_src"])

    pkt = testutils.simple_ip_packet(
        eth_dst=ethernet_dst[msg_type], # DUT port
        eth_src=ports_info["src_mac"], # PTF port
        ip_src=pkt_fields["ipv4_src"], # PTF source
        ip_dst=ip_dst[msg_type],
        ip_ttl=1,
    )

    del pkt[testutils.scapy.scapy.all.Raw]
    pkt = pkt / igmp_types[igmp_version][msg_type]

    do_test("L3", pkt, ptfadapter, duthost, ports_info, setup["dut_to_ptf_port_map"].values(), tx_dut_ports)
Beispiel #6
0
def _get_simple_ip_packet(src_mac, dst_mac, src_ip, dst_ip):
    pkt = testutils.simple_ip_packet(eth_src=src_mac,
                                     eth_dst=dst_mac,
                                     ip_src=src_ip,
                                     ip_dst=dst_ip)

    logging.info(
        "Generated simple IP packet (SMAC=%s, DMAC=%s, SIP=%s, DIP=%s)",
        src_mac, dst_mac, src_ip, dst_ip)

    return pkt
Beispiel #7
0
    def runTest(self):
        target = gc.Target(device_id=dev_id, pipe_id=0xffff)
        port_meta = self.bfrt_info.table_get("$PORT_METADATA")
        pass_one = self.bfrt_info.table_get("pass_one")
        port = random.choice(swports)
        port_meta_values = [random.getrandbits(32), random.getrandbits(32)]

        try:
            # Write values into the Port Metadata table which will be assigned
            # to the packet.
            k = port_meta.make_key(
                [gc.KeyTuple('ig_intr_md.ingress_port', port)])
            d = port_meta.make_data([
                gc.DataTuple('f1', port_meta_values[0]),
                gc.DataTuple('f2', port_meta_values[1])
            ])
            port_meta.entry_add(target, [k], [d])

            # Install an entry to match those metadata values in the "pass_one"
            # table with an action that will NOT perform a resubmit.
            k = pass_one.make_key([
                gc.KeyTuple("port", port),
                gc.KeyTuple("f1", port_meta_values[0]),
                gc.KeyTuple("f2", port_meta_values[1])
            ])
            d = pass_one.make_data([], "SwitchIngress.no_resub")
            pass_one.entry_add(target, [k], [d])

            # Since the packet will not perform a resubmit operation the header
            # modifications on the first (and only) pass of the packet through
            # the ingress pipe will be kept, so expect the MAC addresses to be
            # modified.
            pkt_in = testutils.simple_ip_packet()
            pkt_out = testutils.simple_ip_packet(eth_dst='00:00:00:00:00:01',
                                                 eth_src='00:00:00:00:00:00')
            testutils.send_packet(self, port, pkt_in)
            testutils.verify_packet(self, pkt_out, port)

        finally:
            port_meta.entry_del(target)
            pass_one.entry_del(target)
Beispiel #8
0
    def test_forward_ip_packet_recomputed_0xffff_chksum(self, duthost, ptfadapter, common_param):
        # GIVEN a ip packet, after forwarded(ttl-1) by DUT,
        #   it's checksum will be 0xffff after wrongly incrementally recomputed
        #   ref to https://datatracker.ietf.org/doc/html/rfc1624
        #   HC' = HC(0xff00) + m(0x7a2f) + ~m'(~0x792f)= 0xffff
        # WHEN send the packet to DUT
        # THEN DUT recompute new checksum correctly and forward packet as expected.

        (peer_ip_ifaces_pair, ptf_port_idx, pc_ports_map, ptf_indices) = common_param
        pkt = testutils.simple_ip_packet(
            eth_dst=duthost.facts["router_mac"],
            eth_src=ptfadapter.dataplane.get_mac(0, ptf_port_idx),
            pktlen=1246,
            ip_src="10.250.40.40",
            ip_dst="10.156.190.188",
            ip_proto=47,
            ip_tos=0x84,
            ip_id=0,
            ip_ihl=5,
            ip_ttl=122,
        )
        pkt.payload.flags = 2
        exp_pkt = pkt.copy()
        exp_pkt.payload.ttl = 121
        exp_pkt.payload.chksum = 0x0001
        exp_pkt = mask.Mask(exp_pkt)
        exp_pkt.set_do_not_care_scapy(packet.Ether, 'dst')
        exp_pkt.set_do_not_care_scapy(packet.Ether, 'src')

        out_ifaces = TestIPPacket.parse_interfaces(duthost.command("show ip route 10.156.190.188")["stdout_lines"],
                                                   pc_ports_map)
        out_ptf_indices = map(lambda iface: ptf_indices[iface], out_ifaces)

        duthost.command("portstat -c")
        ptfadapter.dataplane.flush()
        testutils.send(ptfadapter, ptf_port_idx, pkt, self.PKT_NUM)
        time.sleep(5)
        match_cnt = testutils.count_matched_packets_all_ports(ptfadapter, exp_pkt, ports=out_ptf_indices)

        portstat_out = parse_portstat(duthost.command("portstat")["stdout_lines"])

        rx_ok = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_ok"].replace(",", ""))
        rx_drp = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_drp"].replace(",", ""))
        tx_ok = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_ok")
        tx_drp = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_drp")

        pytest_assert(match_cnt == self.PKT_NUM, "Packet lost")
        pytest_assert(self.PKT_NUM_MIN <= rx_ok <= self.PKT_NUM_MAX, "rx_ok unexpected")
        pytest_assert(self.PKT_NUM_MIN <= tx_ok <= self.PKT_NUM_MAX, "tx_ok unexpected")
        pytest_assert(rx_drp <= self.PKT_NUM_ZERO, "rx_drp unexpected")
        pytest_assert(tx_drp <= self.PKT_NUM_ZERO, "tx_drp unexpected")
Beispiel #9
0
    def test_forward_ip_packet_with_0xffff_chksum_drop(self, duthost, ptfadapter, common_param):
        # GIVEN a ip packet with checksum 0x0000(compute from scratch)
        # WHEN manually set checksum as 0xffff and send the packet to DUT
        # THEN DUT should drop packet with 0xffff and add drop count

        (peer_ip_ifaces_pair, ptf_port_idx, pc_ports_map, ptf_indices) = common_param
        pkt = testutils.simple_ip_packet(
            eth_dst=duthost.facts["router_mac"],
            eth_src=ptfadapter.dataplane.get_mac(0, ptf_port_idx),
            pktlen=1246,
            ip_src="10.250.136.195",
            ip_dst="10.156.94.34",
            ip_proto=47,
            ip_tos=0x84,
            ip_id=0,
            ip_ihl=5,
            ip_ttl=121,
        )
        pkt.payload.flags = 2
        pkt.payload.chksum = 0xffff
        exp_pkt = pkt.copy()
        exp_pkt.payload.ttl = 120
        exp_pkt.payload.chksum = 0x0100
        exp_pkt = mask.Mask(exp_pkt)
        exp_pkt.set_do_not_care_scapy(packet.Ether, 'dst')
        exp_pkt.set_do_not_care_scapy(packet.Ether, 'src')

        out_ifaces = TestIPPacket.parse_interfaces(duthost.command("show ip route 10.156.94.34")["stdout_lines"],
                                                   pc_ports_map)
        out_ptf_indices = map(lambda iface: ptf_indices[iface], out_ifaces)

        duthost.command("portstat -c")
        ptfadapter.dataplane.flush()
        testutils.send(ptfadapter, ptf_port_idx, pkt, self.PKT_NUM)
        time.sleep(5)
        match_cnt = testutils.count_matched_packets_all_ports(ptfadapter, exp_pkt, ports=out_ptf_indices)

        portstat_out = parse_portstat(duthost.command("portstat")["stdout_lines"])

        rx_ok = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_ok"].replace(",", ""))
        rx_drp = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_drp"].replace(",", ""))
        tx_ok = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_ok")
        tx_drp = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_drp")

        pytest_assert(match_cnt == 0, "Packet not dropped")
        pytest_assert(self.PKT_NUM_MIN <= rx_ok <= self.PKT_NUM_MAX, "rx_ok unexpected")
        pytest_assert(self.PKT_NUM_MIN <= rx_drp <= self.PKT_NUM_MAX, "rx_drp unexpected")
        pytest_assert(tx_drp <= self.PKT_NUM_ZERO, "tx_drp unexpected")
        pytest_assert(tx_ok <= self.PKT_NUM_ZERO, "tx_ok unexpected")
Beispiel #10
0
def build_packet_to_server(duthost, ptfadapter, target_server_ip):
    """Build packet and expected mask packet destinated to server."""
    pkt_dscp = random.choice(range(0, 33))
    pkt_ttl = random.choice(range(3, 65))
    pkt = testutils.simple_ip_packet(eth_dst=duthost.facts["router_mac"],
                                     eth_src=ptfadapter.dataplane.get_mac(
                                         0, 0),
                                     ip_src="1.1.1.1",
                                     ip_dst=target_server_ip,
                                     ip_dscp=pkt_dscp,
                                     ip_ttl=pkt_ttl)
    logging.info("the packet destinated to server %s:\n%s", target_server_ip,
                 dump_scapy_packet_show_output(pkt))
    exp_pkt = mask.Mask(pkt)
    exp_pkt.set_do_not_care_scapy(scapyall.Ether, "dst")
    exp_pkt.set_do_not_care_scapy(scapyall.Ether, "src")
    exp_pkt.set_do_not_care_scapy(scapyall.IP, "tos")
    exp_pkt.set_do_not_care_scapy(scapyall.IP, "ttl")
    exp_pkt.set_do_not_care_scapy(scapyall.IP, "chksum")
    return pkt, exp_pkt
Beispiel #11
0
    def test_forward_normal_ip_packet(self, duthost, ptfadapter, common_param):
        # GIVEN a random normal ip packet
        # WHEN send the packet to DUT
        # THEN DUT should forward it as normal ip packet, nothing change but ttl-1
        (peer_ip_ifaces_pair, ptf_port_idx, pc_ports_map, ptf_indices) = common_param
        pkt = testutils.simple_ip_packet(
            eth_dst=duthost.facts["router_mac"],
            eth_src=ptfadapter.dataplane.get_mac(0, ptf_port_idx),
            ip_src=peer_ip_ifaces_pair[0][0],
            ip_dst=peer_ip_ifaces_pair[1][0])

        exp_pkt = pkt.copy()
        exp_pkt.payload.ttl = pkt.payload.ttl - 1
        exp_pkt = mask.Mask(exp_pkt)

        exp_pkt.set_do_not_care_scapy(packet.Ether, 'dst')
        exp_pkt.set_do_not_care_scapy(packet.Ether, 'src')

        out_ifaces = TestIPPacket.parse_interfaces(
            duthost.command("show ip route %s" % peer_ip_ifaces_pair[1][0])["stdout_lines"],
            pc_ports_map)
        out_ptf_indices = map(lambda iface: ptf_indices[iface], out_ifaces)

        duthost.command("portstat -c")
        ptfadapter.dataplane.flush()
        testutils.send(ptfadapter, ptf_port_idx, pkt, self.PKT_NUM)
        time.sleep(5)
        match_cnt = testutils.count_matched_packets_all_ports(ptfadapter, exp_pkt, ports=out_ptf_indices)

        portstat_out = parse_portstat(duthost.command("portstat")["stdout_lines"])

        rx_ok = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_ok"].replace(",", ""))
        rx_drp = int(portstat_out[peer_ip_ifaces_pair[0][1][0]]["rx_drp"].replace(",", ""))
        tx_ok = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_ok")
        tx_drp = TestIPPacket.sum_portstat_ifaces_counts(portstat_out, out_ifaces, "tx_drp")

        pytest_assert(match_cnt == self.PKT_NUM, "Packet lost")
        pytest_assert(self.PKT_NUM_MIN <= rx_ok <= self.PKT_NUM_MAX, "rx_ok unexpected")
        pytest_assert(self.PKT_NUM_MIN <= tx_ok <= self.PKT_NUM_MAX, "tx_ok unexpected")
        pytest_assert(rx_drp <= self.PKT_NUM_ZERO, "rx_drp unexpected")
        pytest_assert(tx_drp <= self.PKT_NUM_ZERO, "tx_drp unexpected")
Beispiel #12
0
def build_non_encapsulated_ip_packet(rand_selected_interface, ptfadapter,
                                     rand_selected_dut,
                                     tunnel_traffic_monitor):
    """
    Build the regular (non encapsulated) packet to be sent from T1 to ToR.
    """
    tor = rand_selected_dut
    _, server_ips = rand_selected_interface
    server_ipv4 = server_ips["server_ipv4"].split("/")[0]
    config_facts = tor.get_running_config_facts()
    try:
        peer_ipv4_address = [
            dut_name["address_ipv4"]
            for dut_name in config_facts["PEER_SWITCH"].values()
        ][0]
    except IndexError:
        raise ValueError("Failed to get peer ToR address from CONFIG_DB")

    tor_ipv4_address = [
        addr for addr in config_facts["LOOPBACK_INTERFACE"]["Loopback0"]
        if is_ipv4_address(addr.split("/")[0])
    ][0]
    tor_ipv4_address = tor_ipv4_address.split("/")[0]

    dscp = random.choice(range(0, 33))
    ttl = random.choice(range(3, 65))
    ecn = random.choice(range(0, 3))

    packet = testutils.simple_ip_packet(eth_dst=tor.facts["router_mac"],
                                        eth_src=ptfadapter.dataplane.get_mac(
                                            0, 0),
                                        ip_src="1.1.1.1",
                                        ip_dst=server_ipv4,
                                        ip_dscp=dscp,
                                        ip_ecn=ecn,
                                        ip_ttl=ttl)
    logging.info("the regular IP packet to send:\n%s",
                 dump_scapy_packet_show_output(packet))

    return packet
Beispiel #13
0
def generate_packet(src_ip, dst_ip, dst_mac):
    """
    Build ipv4 and ipv6 packets/expected_packets for testing.
    """
    if ipaddress.ip_network(unicode(src_ip), False).version == 4:
        pkt = testutils.simple_ip_packet(eth_dst=dst_mac,
                                         ip_src=src_ip,
                                         ip_dst=dst_ip)
        exp_pkt = Mask(pkt)
        exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst")
        exp_pkt.set_do_not_care_scapy(scapy.Ether, "src")
        exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl")
        exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum")
    else:
        pkt = testutils.simple_tcpv6_packet(eth_dst=dst_mac,
                                            ipv6_src=src_ip,
                                            ipv6_dst=dst_ip)
        exp_pkt = Mask(pkt)
        exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst")
        exp_pkt.set_do_not_care_scapy(scapy.Ether, "src")
        exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim")

    return pkt, exp_pkt
Beispiel #14
0
    def _get_simple_ip_packet(rx_port, src_ip, dst_ip):
        dst_mac = duthost.get_dut_iface_mac(
            testbed_params["physical_port_map"][rx_port])
        src_mac = "DE:AD:BE:EF:12:34"
        # send tagged packet for t0-backend whose vlan mode is tagged
        enable_vlan = rx_port in testbed_params[
            "vlan_ports"] and testbed_params["vlan_interface"][
                "type"] == "tagged"
        packet_params = dict(eth_src=src_mac,
                             eth_dst=dst_mac,
                             ip_src=src_ip,
                             ip_dst=dst_ip)
        if enable_vlan:
            packet_params["dl_vlan_enable"] = enable_vlan
            packet_params["vlan_vid"] = int(
                testbed_params["vlan_interface"]["attachto"].lstrip("Vlan"))
        pkt = testutils.simple_ip_packet(**packet_params)

        logging.info(
            "Generated simple IP packet (SMAC=%s, DMAC=%s, SIP=%s, DIP=%s)",
            src_mac, dst_mac, src_ip, dst_ip)

        return pkt
Beispiel #15
0
def test_non_routable_igmp_pkts(do_test, ptfadapter, duthost, setup,
                                fanouthost, tx_dut_ports, pkt_fields,
                                igmp_version, msg_type, ports_info):
    """
    @summary: Create an IGMP non-routable packets.
    """
    # IGMP Types:
    # 0x11 = Membership Query
    # 0x12 = Version 1 Membership Report
    # 0x16 = Version 2 Membership Report
    # 0x17 = Leave Group

    # IP destination address according to the RFC 2236:
    # Message Type                  Destination Group
    # ------------                  -----------------
    # General Query                 ALL-SYSTEMS (224.0.0.1)
    # Group-Specific Query          The group being queried
    # Membership Report             The group being reported
    # Leave Message                 ALL-ROUTERS (224.0.0.2)

    # TODO: fix this workaround as of now current PTF and Scapy versions do not support creation of IGMP packets
    # Temporaly created hex of IGMP packet layer by using scapy version 2.4.3.
    # Example how to get HEX of specific IGMP packets:
    # v3_membership_query = IGMPv3(type=0x11, mrcode=0, chksum=None)/scapy.contrib.igmpv3.IGMPv3mq(gaddr="224.0.0.1",
    # srcaddrs=["172.16.11.1", "10.0.0.59"], qrv=1, qqic=125, numsrc=2)
    # gr_obj = scapy.contrib.igmpv3.IGMPv3gr(rtype=1, auxdlen=0, maddr="224.2.2.4", numsrc=2, srcaddrs=["172.16.11.1",
    # "10.0.0.59"]).build()
    # v3_membership_report = IGMPv3(type=0x22, mrcode=0, chksum=None)/scapy.contrib.igmpv3.IGMPv3mr(res2=0x00, numgrp=1,
    # records=[gr_obj]).build()
    # The rest packets are build like "simple_igmp_packet" function from PTF testutils.py

    # FIXME: Need some sort of configuration for EOS and SONiC fanout hosts to
    # not drop IGMP packets before they reach the DUT
    if not fanouthost:
        pytest.skip("Test case requires explicit fanout support")

    from scapy.contrib.igmp import IGMP
    Ether = testutils.scapy.Ether
    IP = testutils.scapy.IP

    if "vlan" in tx_dut_ports[ports_info["dut_iface"]].lower(
    ) and msg_type == "membership_report":
        pytest.skip("Test case is not supported on VLAN interface")

    igmp_proto = 0x02
    multicast_group_addr = "224.1.1.1"
    ethernet_dst = "01:00:5e:01:01:01"
    ip_dst = {
        "general_query": "224.0.0.1",
        "membership_report": multicast_group_addr
    }
    igmp_types = {
        "v1": {
            "general_query": IGMP(type=0x11, gaddr="224.0.0.1"),
            "membership_report": IGMP(type=0x12, gaddr=multicast_group_addr)
        },
        "v2": {
            "membership_report": IGMP(type=0x16, gaddr=multicast_group_addr),
            "leave_group": IGMP(type=0x17, gaddr=multicast_group_addr)
        },
        "v3": {
            "general_query":
            "\x11\x00L2\xe0\x00\x00\x01\x01}\x00\x02\xac\x10\x0b\x01\n\x00\x00;",
            "membership_report":
            "\"\x009\xa9\x00\x00\x00\x01\x01\x00\x00\x02\xe0\x02\x02\x04\xac\x10\x0b\x01\n\x00\x00;"
        }
    }

    if igmp_version == "v3":
        pkt = testutils.simple_ip_packet(eth_dst=ethernet_dst,
                                         eth_src=ports_info["src_mac"],
                                         ip_src=pkt_fields["ipv4_src"],
                                         ip_dst=ip_dst[msg_type],
                                         ip_ttl=1,
                                         ip_proto=igmp_proto)
        del pkt["Raw"]
        pkt = pkt / igmp_types[igmp_version][msg_type]
    else:
        eth_layer = Ether(src=ports_info["src_mac"], dst=ethernet_dst)
        ip_layer = IP(src=pkt_fields["ipv4_src"], )
        igmp_layer = igmp_types[igmp_version][msg_type]
        assert igmp_layer.igmpize(ip=ip_layer,
                                  ether=eth_layer), "Can't create IGMP packet"
        pkt = eth_layer / ip_layer / igmp_layer

    log_pkt_params(ports_info["dut_iface"], ethernet_dst,
                   ports_info["src_mac"],
                   pkt.getlayer("IP").dst, pkt_fields["ipv4_src"])
    do_test("L3", pkt, ptfadapter, duthost, ports_info,
            setup["dut_to_ptf_port_map"].values(), tx_dut_ports)
Beispiel #16
0
    def runTest(self):
        target = gc.Target(device_id=dev_id, pipe_id=0xffff)
        port_meta = self.bfrt_info.table_get("$PORT_METADATA")
        pass_one = self.bfrt_info.table_get("pass_one")
        pass_two_a = self.bfrt_info.table_get("pass_two_type_a")
        pass_two_b = self.bfrt_info.table_get("pass_two_type_b")
        pass_two_c = self.bfrt_info.table_get("pass_two_type_c")
        port = random.choice(swports)
        port_meta_values = [random.getrandbits(32), random.getrandbits(32)]
        a_f1 = random.getrandbits(8)
        a_f2 = random.getrandbits(16)
        a_f3 = random.getrandbits(32)
        a_md = random.getrandbits(64)
        b_f1 = random.getrandbits(8)
        b_md = random.getrandbits(64)
        c_f1 = random.getrandbits(16)
        c_f2 = random.getrandbits(16)
        c_f3 = random.getrandbits(16)
        c_md = random.getrandbits(64)
        pkt = testutils.simple_ip_packet()
        tof1 = testutils.test_param_get('arch') == 'tofino'

        try:
            # Add a port metadata entry to assign the metadata used in the table
            # key for the pass_one table.
            k = port_meta.make_key(
                [gc.KeyTuple('ig_intr_md.ingress_port', port)])
            d = port_meta.make_data([
                gc.DataTuple('f1', port_meta_values[0]),
                gc.DataTuple('f2', port_meta_values[1])
            ])
            port_meta.entry_add(target, [k], [d])

            # Add an entry to each of the pass two tables which validates the
            # metadata passed through the resubmit path.
            key_fields = [
                gc.KeyTuple('md.a.f1', a_f1),
                gc.KeyTuple('md.a.f2', a_f2),
                gc.KeyTuple('md.a.f3', a_f3)
            ]
            if not tof1:
                key_fields.append(gc.KeyTuple('md.a.additional', a_md))
            d = pass_two_a.make_data([], 'SwitchIngress.okay_a')
            pass_two_a.entry_add(target, [pass_two_a.make_key(key_fields)],
                                 [d])

            key_fields = [gc.KeyTuple('md.b.f1', b_f1)]
            if not tof1:
                key_fields.append(gc.KeyTuple('md.b.additional', b_md))
            d = pass_two_b.make_data([], 'SwitchIngress.okay_b')
            pass_two_b.entry_add(target, [pass_two_b.make_key(key_fields)],
                                 [d])

            key_fields = [
                gc.KeyTuple('md.c.f1', c_f1),
                gc.KeyTuple('md.c.f2', c_f2),
                gc.KeyTuple('md.c.f3', c_f3)
            ]
            if not tof1:
                key_fields.append(gc.KeyTuple('md.c.additional', c_md))
            d = pass_two_c.make_data([], 'SwitchIngress.okay_c')
            pass_two_c.entry_add(target, [pass_two_c.make_key(key_fields)],
                                 [d])

            # Clear the counters to ensure we are starting in a known state
            # since other tests may have sent traffic which incremented them.
            self.clrCntrs()

            # Add an entry to the pass_one table to cause the packet to resubmit
            # with the first resubmit type.
            k = pass_one.make_key([
                gc.KeyTuple("port", port),
                gc.KeyTuple("f1", port_meta_values[0]),
                gc.KeyTuple("f2", port_meta_values[1])
            ])
            d = pass_one.make_data([
                gc.DataTuple('f1', a_f1),
                gc.DataTuple('f2', a_f2),
                gc.DataTuple('f3', a_f3),
                gc.DataTuple('more_data', a_md)
            ], "SwitchIngress.resub_a")
            pass_one.entry_add(target, [k], [d])

            # Verify it works as expected. There should be one count at index 0
            # from the first pass and one count at index 1 for a resubmit type A.
            testutils.send_packet(self, port, pkt)
            testutils.verify_packet(self, pkt, port)
            c1 = self.getCntr(0)
            c2 = self.getCntr(1)
            self.assertEqual(c1, 1)
            self.assertEqual(c2, 1)

            # Now modify the entry to use the next resubmit type and verify it
            # also works.
            d = pass_one.make_data(
                [gc.DataTuple('f1', b_f1),
                 gc.DataTuple('more_data', b_md)], "SwitchIngress.resub_b")
            pass_one.entry_mod(target, [k], [d])
            testutils.send_packet(self, port, pkt)
            testutils.verify_packet(self, pkt, port)
            c1 = self.getCntr(0)
            c2 = self.getCntr(2)
            self.assertEqual(c1, 2)
            self.assertEqual(c2, 1)

            # Modify it again to use the third resubmit type and verify.
            d = pass_one.make_data([
                gc.DataTuple('f1', c_f1),
                gc.DataTuple('f2', c_f2),
                gc.DataTuple('f3', c_f3),
                gc.DataTuple('more_data', c_md)
            ], "SwitchIngress.resub_c")
            pass_one.entry_mod(target, [k], [d])
            testutils.send_packet(self, port, pkt)
            testutils.verify_packet(self, pkt, port)
            c1 = self.getCntr(0)
            c2 = self.getCntr(3)
            self.assertEqual(c1, 3)
            self.assertEqual(c2, 1)

        finally:
            port_meta.entry_del(target)
            pass_one.entry_del(target)
            pass_two_a.entry_del(target)
            pass_two_b.entry_del(target)
            pass_two_c.entry_del(target)
Beispiel #17
0
def verify_upstream_traffic(host,
                            ptfadapter,
                            tbinfo,
                            itfs,
                            server_ip,
                            pkt_num=100,
                            drop=False):
    """
    @summary: Helper function for verifying upstream packets
    @param host: The dut host
    @param ptfadapter: The ptfadapter fixture
    @param tbinfo: The tbinfo fixture
    @param ifts: The interface name on DUT
    @param server_ip: The IP address of server
    @param pkt_num: The number of packets to generete and tx
    @param drop: Packets are expected to be dropped if drop is True, and vice versa
    @return: No return value. An exception will be raised if verify fails.
    """
    random_ip = generate_ip_through_default_route(host).split('/')[0]
    vlan_table = host.get_running_config_facts()['VLAN']
    vlan_name = list(vlan_table.keys())[0]
    vlan_mac = host.get_dut_iface_mac(vlan_name)
    router_mac = host.facts['router_mac']
    # Generate packets from server to a random IP address, which goes default routes
    pkt = testutils.simple_ip_packet(eth_dst=vlan_mac,
                                     ip_src=server_ip,
                                     ip_dst=random_ip)
    # Generate packet forwarded to portchannels
    pkt_copy = pkt.copy()
    pkt_copy[Ether].src = router_mac

    exp_pkt = mask.Mask(pkt_copy)
    exp_pkt.set_do_not_care_scapy(Ether, "dst")

    exp_pkt.set_do_not_care_scapy(IP, "dst")
    exp_pkt.set_do_not_care_scapy(IP, "ihl")
    exp_pkt.set_do_not_care_scapy(IP, "tos")
    exp_pkt.set_do_not_care_scapy(IP, "len")
    exp_pkt.set_do_not_care_scapy(IP, "id")
    exp_pkt.set_do_not_care_scapy(IP, "flags")
    exp_pkt.set_do_not_care_scapy(IP, "frag")
    exp_pkt.set_do_not_care_scapy(IP, "ttl")
    exp_pkt.set_do_not_care_scapy(IP, "proto")
    exp_pkt.set_do_not_care_scapy(IP, "chksum")

    exp_pkt.set_ignore_extra_bytes()

    port_channels = get_t1_ptf_pc_ports(host, tbinfo)
    rx_ports = []
    for v in port_channels.values():
        rx_ports += v
    rx_ports = [int(x.strip('eth')) for x in rx_ports]

    mg_facts = host.get_extended_minigraph_facts(tbinfo)
    tx_port = mg_facts['minigraph_ptf_indices'][itfs]
    logger.info(
        "Verifying upstream traffic. packet number = {} interface = {} server_ip = {} expect_drop = {}"
        .format(pkt_num, itfs, server_ip, drop))
    for i in range(0, pkt_num):
        ptfadapter.dataplane.flush()
        testutils.send(ptfadapter, tx_port, pkt, count=1)
        if drop:
            testutils.verify_no_packet_any(ptfadapter, exp_pkt, rx_ports)
        else:
            testutils.verify_packet_any_port(ptfadapter, exp_pkt, rx_ports)
Beispiel #18
0
def test_po_update_io_no_loss(duthosts,
                              enum_rand_one_per_hwsku_frontend_hostname,
                              enum_frontend_asic_index, tbinfo, reload_testbed,
                              ptfadapter):
    # GIVEN a lag topology, keep sending packets between 2 port channels
    # WHEN delete/add different members of a port channel
    # THEN no packets shall loss
    duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
    asichost = duthost.asic_instance(enum_frontend_asic_index)
    mg_facts = duthost.get_extended_minigraph_facts(tbinfo)

    if len(mg_facts["minigraph_portchannel_interfaces"]) < 2:
        pytest.skip(
            "Skip test due to there isn't enough port channel exists in current topology."
        )

    # generate ip-pc pairs, be like:[("10.0.0.56", "10.0.0.57", "PortChannel0001")]
    peer_ip_pc_pair = [(pc["addr"], pc["peer_addr"], pc["attachto"])
                       for pc in mg_facts["minigraph_portchannel_interfaces"]
                       if ipaddress.ip_address(pc['peer_addr']).version == 4]
    # generate pc tuples, fill in members,
    # be like:[("10.0.0.56", "10.0.0.57", "PortChannel0001", ["Ethernet48", "Ethernet52"])]
    pcs = [(pair[0], pair[1], pair[2],
            mg_facts["minigraph_portchannels"][pair[2]]["members"])
           for pair in peer_ip_pc_pair
           if len(mg_facts["minigraph_portchannels"][pair[2]]["members"]) >= 2]

    if len(pcs) < 2:
        pytest.skip(
            "Skip test due to there is no enough port channel with at least 2 members exists in current topology."
        )

    selected_pcs = random.sample(pcs, k=2)

    in_pc = selected_pcs[0]
    out_pc = selected_pcs[1]
    # use first port of in_pc as input port
    # all ports in out_pc will be output/forward ports
    pc, pc_members = out_pc[2], out_pc[3]
    in_ptf_index = mg_facts["minigraph_ptf_indices"][in_pc[3][0]]
    out_ptf_indices = map(lambda port: mg_facts["minigraph_ptf_indices"][port],
                          out_pc[3])
    logging.info(
        "selected_pcs is: %s, in_ptf_index is %s, out_ptf_indices is %s" %
        (selected_pcs, in_ptf_index, out_ptf_indices))

    tmp_pc = "PortChannel999"
    pc_ip = out_pc[0]
    in_peer_ip = in_pc[1]
    out_peer_ip = out_pc[1]

    # Step 1: Remove port channel members from port channel
    for member in pc_members:
        asichost.config_portchannel_member(pc, member, "del")

    # Step 2: Remove port channel ip from port channel
    asichost.config_ip_intf(pc, pc_ip + "/31", "remove")

    time.sleep(30)
    int_facts = asichost.interface_facts()['ansible_facts']
    pytest_assert(not int_facts['ansible_interface_facts'][pc]['link'])
    pytest_assert(
        wait_until(120, 10, 0, asichost.check_bgp_statistic, 'ipv4_idle', 1))

    # Step 3: Create tmp port channel with default min-links(1)
    asichost.config_portchannel(tmp_pc, "add")

    # Step 4: Add port channel members to tmp port channel
    for member in pc_members:
        asichost.config_portchannel_member(tmp_pc, member, "add")

    # Step 5: Add port channel ip to tmp port channel
    asichost.config_ip_intf(tmp_pc, pc_ip + "/31", "add")
    int_facts = asichost.interface_facts()['ansible_facts']
    pytest_assert(int_facts['ansible_interface_facts'][tmp_pc]['ipv4']
                  ['address'] == pc_ip)

    time.sleep(30)
    int_facts = asichost.interface_facts()['ansible_facts']
    pytest_assert(int_facts['ansible_interface_facts'][tmp_pc]['link'])
    pytest_assert(
        wait_until(120, 10, 0, asichost.check_bgp_statistic, 'ipv4_idle', 0))

    # Keep sending packets, and add/del different members during that time, observe whether packets lose
    pkt = testutils.simple_ip_packet(eth_dst=duthost.facts["router_mac"],
                                     eth_src=ptfadapter.dataplane.get_mac(
                                         0, in_ptf_index),
                                     ip_src=in_peer_ip,
                                     ip_dst=out_peer_ip)

    exp_pkt = pkt.copy()
    exp_pkt = mask.Mask(exp_pkt)

    exp_pkt.set_do_not_care_scapy(packet.Ether, 'dst')
    exp_pkt.set_do_not_care_scapy(packet.Ether, 'src')
    exp_pkt.set_do_not_care_scapy(packet.IP, 'chksum')
    exp_pkt.set_do_not_care_scapy(packet.IP, 'ttl')

    ptfadapter.dataplane.flush()
    member_update_finished_flag = Queue(1)
    packet_sending_flag = Queue(1)

    def del_add_members():
        # wait for packets sending started, then starts to update pc members
        while packet_sending_flag.empty() or (not packet_sending_flag.get()):
            time.sleep(0.5)
        asichost.config_portchannel_member(tmp_pc, pc_members[0], "del")
        time.sleep(2)
        asichost.config_portchannel_member(tmp_pc, pc_members[0], "add")
        time.sleep(2)
        asichost.config_portchannel_member(tmp_pc, pc_members[1], "del")
        time.sleep(2)
        asichost.config_portchannel_member(tmp_pc, pc_members[1], "add")
        time.sleep(5)
        member_update_finished_flag.put(True)

    t = threading.Thread(target=del_add_members, name="del_add_members_thread")
    t.start()
    t_max = time.time() + 60
    send_count = 0
    stop_sending = False
    while not stop_sending:
        # After 100 packets send, awake del_add_members thread, it happens only once.
        if send_count == 100:
            packet_sending_flag.put(True)

        testutils.send(ptfadapter, in_ptf_index, pkt)
        send_count += 1
        member_update_thread_finished = (not member_update_finished_flag.empty(
        )) and member_update_finished_flag.get()
        reach_max_time = time.time() > t_max
        stop_sending = reach_max_time or member_update_thread_finished
    t.join(20)
    match_cnt = testutils.count_matched_packets_all_ports(
        ptfadapter, exp_pkt, ports=out_ptf_indices)

    pytest_assert(match_cnt > 0, "Packets not send")
    pytest_assert(match_cnt == send_count,
                  "Packets lost during pc members add/removal")
Beispiel #19
0
 def runTest(self):
     pkt = testutils.simple_ip_packet(pktlen=80)
     self.runPacketInTest(pkt)