def runTest(self): ig_ports = [swports[1], swports[2]] eg_ports = [swports[2], swports[1]] ip2 = "2001:0000:0000::0000:0000:0002" ip1 = "2001:0000:0000::0000:0000:0001" mac2 = "00:00:00:00:00:02" mac1 = "00:00:00:00:00:01" # send pkt and verify sent pkt = testutils.simple_tcpv6_packet(eth_dst=mac2, eth_src=mac1, ipv6_dst=ip2) exp_pkt = pkt logger.info("Sending packet on port %d", ig_ports[0]) testutils.send_packet(self, ig_ports[0], str(pkt)) logger.info("Expecting packet on port %d", eg_ports[0]) testutils.verify_packets(self, exp_pkt, [eg_ports[0]]) # send pkt and verify sent pkt = testutils.simple_tcpv6_packet(eth_dst=mac1, eth_src=mac2, ipv6_dst=ip1) exp_pkt = pkt logger.info("Sending packet on port %d", ig_ports[1]) testutils.send_packet(self, ig_ports[1], str(pkt)) logger.info("Expecting packet on port %d", eg_ports[1]) testutils.verify_packets(self, exp_pkt, [eg_ports[1]])
def runTest(self): pkt = simple_tcpv6_packet(ipv6_src='2001::1', ipv6_dst='2001::2') exp_pkt = simple_tcpv6_packet(ipv6_src='2001::2', ipv6_dst='2001::1') mask = Mask(exp_pkt) mask.set_do_not_care_scapy(TCP, 'chksum') send_packet(self, (0, 1), pkt) verify_packets(self, mask, device_number=0, ports=[2])
def generate_and_verify_traffic(duthost, ptfadapter, ip_dst, expected_ports, ipv6=False): if ipv6: pkt = testutils.simple_tcpv6_packet( eth_dst=duthost.facts["router_mac"], eth_src=ptfadapter.dataplane.get_mac(0, 0), ipv6_src='2001:db8:85a3::8a2e:370:7334', ipv6_dst=ip_dst, ipv6_hlim=64, tcp_sport=1234, tcp_dport=4321) else: pkt = testutils.simple_tcp_packet( eth_dst=duthost.facts["router_mac"], eth_src=ptfadapter.dataplane.get_mac(0, 0), ip_src='1.1.1.1', ip_dst=ip_dst, ip_ttl=64, tcp_sport=1234, tcp_dport=4321) 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') if ipv6: exp_pkt.set_do_not_care_scapy(packet.IPv6, 'hlim') exp_pkt.set_do_not_care_scapy(packet.IPv6, 'chksum') else: exp_pkt.set_do_not_care_scapy(packet.IP, 'ttl') exp_pkt.set_do_not_care_scapy(packet.IP, 'chksum') testutils.send(ptfadapter, 5, pkt) testutils.verify_packet_any_port(ptfadapter, exp_pkt, ports=expected_ports)
def _base_tcpv6_packet(self, ptfadapter, setup, src_ip=DEFAULT_SRC_IP, dst_ip=DEFAULT_DST_IP, next_header=None, dscp=None, sport=2020, dport=8080, flags=0x10): pkt = testutils.simple_tcpv6_packet( eth_src=ptfadapter.dataplane.get_mac(0, 0), eth_dst=setup["router_mac"], ipv6_src=src_ip, ipv6_dst=dst_ip, ipv6_dscp=dscp, ipv6_hlim=64, tcp_sport=sport, tcp_dport=dport, tcp_flags=flags, ) if next_header: pkt["IPv6"].nh = next_header return pkt
def test_src_ip_is_multicast_addr(do_test, ptfadapter, duthosts, rand_one_dut_hostname, setup, tx_dut_ports, pkt_fields, ip_addr, ports_info): """ @summary: Create a packet with multicast source IP adress. """ duthost = duthosts[rand_one_dut_hostname] ip_src = None if ip_addr == "ipv4": ip_src = "224.0.0.5" pkt = testutils.simple_tcp_packet( eth_dst=ports_info["dst_mac"], # DUT port eth_src=ports_info["src_mac"], # PTF port ip_src=ip_src, ip_dst=pkt_fields["ipv4_dst"], # VM source tcp_sport=pkt_fields["tcp_sport"], tcp_dport=pkt_fields["tcp_dport"]) elif ip_addr == "ipv6": if not pkt_fields["ipv6_dst"]: pytest.skip("BGP neighbour with IPv6 addr was not found") ip_src = "FF02:AAAA:FEE5::1:3" pkt = testutils.simple_tcpv6_packet( eth_dst=ports_info["dst_mac"], # DUT port eth_src=ports_info["src_mac"], # PTF port ipv6_src=ip_src, ipv6_dst=pkt_fields["ipv6_dst"], # VM source tcp_sport=pkt_fields["tcp_sport"], tcp_dport=pkt_fields["tcp_dport"]) else: pytest.fail("Incorrect value specified for 'ip_addr' test parameter. Supported parameters: 'ipv4' and 'ipv6'") log_pkt_params(ports_info["dut_iface"], ports_info["dst_mac"], ports_info["src_mac"], pkt_fields["ipv4_dst"], ip_src) do_test("L3", pkt, ptfadapter, duthost, ports_info, setup["neighbor_sniff_ports"], tx_dut_ports)
def create_ipv6_inner_pkt_only(self, src_ip, dst_ip, tc, encap=False, hlim=64): """Creates an IPv6 only packet for the test @param src_ip: source ip @param dst_ip: destination ip @param tc: traffic class @param encap: build encapsulated packet. If @encap is True the return packet would be: IP(@src_ip, @dst_ip, @tc) / IP(dst_ip=4::4, src_ip=3::3) / TCP() """ # no ptf function to build simple ipv6 only packet # so use simple_tcpv6_packet function which builds the same packet # with TCP header as simple_ip_only_packet but extract away Ethernet inner_pkt = simple_tcpv6_packet(ipv6_dst=dst_ip, ipv6_src=src_ip, ipv6_hlim=hlim, ipv6_tc=tc).getlayer(scapy.IPv6) if encap: inner_pkt2 = self.create_ipv6_inner_pkt_only(self.DEFAULT_INNER2_V6_PKT_SRC_IP, self.DEFAULT_INNER2_V6_PKT_DST_IP, 0) inner_pkt = simple_ipv6ip_packet(ipv6_src=src_ip, ipv6_dst=dst_ip, ipv6_tc=tc, ipv6_hlim=hlim, inner_frame=inner_pkt2).getlayer(scapy.IPv6) # get only the IP layer return inner_pkt
def tcp_packet(self, setup, direction, ptfadapter, ip_version, src_ip=None, dst_ip=None, proto=None, sport=0x4321, dport=0x51, flags=None): """Generate a TCP packet for testing.""" src_ip = src_ip or DEFAULT_SRC_IP[ip_version] dst_ip = dst_ip or self.get_dst_ip(direction, ip_version) if ip_version == "ipv4": pkt = testutils.simple_tcp_packet( eth_dst=setup["destination_mac"][direction][self.src_port], eth_src=ptfadapter.dataplane.get_mac(0, 0), ip_dst=dst_ip, ip_src=src_ip, tcp_sport=sport, tcp_dport=dport, ip_ttl=64 ) if proto: pkt["IP"].proto = proto else: pkt = testutils.simple_tcpv6_packet( eth_dst=setup["destination_mac"][direction][self.src_port], eth_src=ptfadapter.dataplane.get_mac(0, 0), ipv6_dst=dst_ip, ipv6_src=src_ip, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=64 ) if proto: pkt["IPv6"].nh = proto if flags: pkt["TCP"].flags = flags return pkt
def test_ip_is_zero_addr(do_test, ptfadapter, setup, tx_dut_ports, pkt_fields, addr_type, addr_direction, ports_info): """ @summary: Create a packet with "0.0.0.0" source or destination IP address. """ zero_ipv4 = "0.0.0.0" zero_ipv6 = "::0" pkt_params = { "eth_dst": ports_info["dst_mac"], # DUT port "eth_src": ports_info["src_mac"], # PTF port "tcp_sport": pkt_fields["tcp_sport"], "tcp_dport": pkt_fields["tcp_dport"] } if addr_type == "ipv4": if addr_direction == "src": pkt_params["ip_src"] = zero_ipv4 pkt_params["ip_dst"] = pkt_fields["ipv4_dst"] # VM source elif addr_direction == "dst": pkt_params["ip_src"] = pkt_fields["ipv4_src"] # VM source pkt_params["ip_dst"] = zero_ipv4 else: pytest.fail( "Incorrect value specified for 'addr_direction'. Supported parameters: 'src' and 'dst'" ) pkt = testutils.simple_tcp_packet(**pkt_params) elif addr_type == "ipv6": if not pkt_fields["ipv6_dst"]: pytest.skip("BGP neighbour with IPv6 addr was not found") if addr_direction == "src": pkt_params["ipv6_src"] = zero_ipv6 pkt_params["ipv6_dst"] = pkt_fields["ipv6_dst"] # VM source elif addr_direction == "dst": pkt_params["ipv6_src"] = pkt_fields["ipv6_src"] # VM source pkt_params["ipv6_dst"] = zero_ipv6 else: pytest.fail( "Incorrect value specified for 'addr_direction'. Supported parameters: 'src' and 'dst'" ) pkt = testutils.simple_tcpv6_packet(**pkt_params) else: pytest.fail( "Incorrect value specified for 'addr_type' test parameter. Supported parameters: 'ipv4' or 'ipv6'" ) logger.info(pkt_params) group = "L3" # DNX platform DROP counters are not there yet if setup.get("platform_asic") == "broadcom-dnx": group = "NO_DROPS" do_test(group, pkt, ptfadapter, ports_info, setup["dut_to_ptf_port_map"].values(), tx_dut_ports)
def runTest(self): ip_dst_addr = '2001:0db8::3210' in_dmac = 'ee:30:ca:9d:1e:00' in_smac = 'ee:cd:00:7e:70:00' ig_port = 0 eg_port = 1 out_dmac = '00:00:00:00:00:01' # Add a set of table entries self.table_add(self.key_t2(ip_dst_addr, 128), self.act_set_dmac(out_dmac)) pkt_in = tu.simple_tcpv6_packet(eth_src=in_smac, eth_dst=in_dmac, ipv6_dst=ip_dst_addr) exp_pkt = tu.simple_tcpv6_packet(eth_src=in_smac, eth_dst=out_dmac, ipv6_dst=ip_dst_addr) tu.send_packet(self, ig_port, pkt_in) tu.verify_packets(self, exp_pkt, [eg_port])
def test_ip_is_zero_addr(do_test, ptfadapter, duthosts, rand_one_dut_hostname, setup, tx_dut_ports, pkt_fields, addr_type, addr_direction, ports_info): """ @summary: Create a packet with "0.0.0.0" source or destination IP address. """ duthost = duthosts[rand_one_dut_hostname] zero_ipv4 = "0.0.0.0" zero_ipv6 = "::0" pkt_params = { "eth_dst": ports_info["dst_mac"], # DUT port "eth_src": ports_info["src_mac"], # PTF port "tcp_sport": pkt_fields["tcp_sport"], "tcp_dport": pkt_fields["tcp_dport"] } if addr_type == "ipv4": if addr_direction == "src": pkt_params["ip_src"] = zero_ipv4 pkt_params["ip_dst"] = pkt_fields["ipv4_dst"] # VM source elif addr_direction == "dst": pkt_params["ip_src"] = pkt_fields["ipv4_src"] # VM source pkt_params["ip_dst"] = zero_ipv4 else: pytest.fail( "Incorrect value specified for 'addr_direction'. Supported parameters: 'src' and 'dst'" ) pkt = testutils.simple_tcp_packet(**pkt_params) elif addr_type == "ipv6": if not pkt_fields["ipv6_dst"]: pytest.skip("BGP neighbour with IPv6 addr was not found") if addr_direction == "src": pkt_params["ipv6_src"] = zero_ipv6 pkt_params["ipv6_dst"] = pkt_fields["ipv6_dst"] # VM source elif addr_direction == "dst": pkt_params["ipv6_src"] = pkt_fields["ipv6_src"] # VM source pkt_params["ipv6_dst"] = zero_ipv6 else: pytest.fail( "Incorrect value specified for 'addr_direction'. Supported parameters: 'src' and 'dst'" ) pkt = testutils.simple_tcpv6_packet(**pkt_params) else: pytest.fail( "Incorrect value specified for 'addr_type' test parameter. Supported parameters: 'ipv4' or 'ipv6'" ) logger.info(pkt_params) do_test("L3", pkt, ptfadapter, duthost, ports_info, setup["dut_to_ptf_port_map"].values(), tx_dut_ports)
def test_src_ip_is_multicast_addr(do_test, ptfadapter, setup, tx_dut_ports, pkt_fields, ip_addr, ports_info): """ @summary: Create a packet with multicast source IP adress. """ ip_src = None if ip_addr == "ipv4": ip_src = "224.0.0.5" pkt = testutils.simple_tcp_packet( eth_dst=ports_info["dst_mac"], # DUT port eth_src=ports_info["src_mac"], # PTF port ip_src=ip_src, ip_dst=pkt_fields["ipv4_dst"], # VM source tcp_sport=pkt_fields["tcp_sport"], tcp_dport=pkt_fields["tcp_dport"]) elif ip_addr == "ipv6": if not pkt_fields["ipv6_dst"]: pytest.skip("BGP neighbour with IPv6 addr was not found") ip_src = "FF02:AAAA:FEE5::1:3" pkt = testutils.simple_tcpv6_packet( eth_dst=ports_info["dst_mac"], # DUT port eth_src=ports_info["src_mac"], # PTF port ipv6_src=ip_src, ipv6_dst=pkt_fields["ipv6_dst"], # VM source tcp_sport=pkt_fields["tcp_sport"], tcp_dport=pkt_fields["tcp_dport"]) else: pytest.fail( "Incorrect value specified for 'ip_addr' test parameter. Supported parameters: 'ipv4' and 'ipv6'" ) log_pkt_params(ports_info["dut_iface"], ports_info["dst_mac"], ports_info["src_mac"], pkt_fields["ipv4_dst"], ip_src) group = "L3" # DNX platform DROP counters are not there yet if setup.get("platform_asic") == "broadcom-dnx": group = "NO_DROPS" do_test(group, pkt, ptfadapter, ports_info, setup["neighbor_sniff_ports"], tx_dut_ports)
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
def MultiSliceTestHelper(self, table_obj, exm_0_field_name, tcam_field_name, lpm_field_name, exm_1_field_name, is_multi_field): """ @brief This is a helper function that - Adds multiple field sliced entry in the table - For some runs, purposely creates discrepancies between the key fields that are already programmed and the values in the sent pkts and ensures that the packet doesn't hit the entry. The way this is done is, the ipv6 address is first generated. Then the value of the field slice is extraced from that address. Then a bit which we expect to match on is flipped in the extracted value. Thus there will be a mismatch between the value present in the packet and the value installed in the hardware which will cause the packet to miss - Always scrambles the bits which are not expected to match on - Reads back the entry and verifies - Sends packets and verifies, - If the installed key fields match the ones in the pkt, then the pkt should hit the entry - If they don't match then the pkt should miss the entry - Finally deletes the entry """ ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' target = gc.Target(device_id=0, pipe_id=0xffff) num_entries = 100 for entry_idx in range(num_entries): logger.info("Processing entry %d ", entry_idx) try: # Generate ipv6 dst addr and mask ipv6_dst_addr = generateIpv6Addr() ipv6_dst_addr_mask = generateIpv6Addr() logger.debug("Generated dst v6 addr is " + ipv6_dst_addr) logger.debug("Generated dst v6 mask is " + ipv6_dst_addr_mask) # Generate ipv6 src addr and mask ipv6_src_addr = generateIpv6Addr() ipv6_src_addr_mask = generateIpv6Addr() logger.debug("Generated src v6 addr is " + ipv6_src_addr) logger.debug("Generated src v6 mask is " + ipv6_src_addr_mask) # Extract all the field values from the dst addr tcam_v6_addr = ipv6_dst_addr tcam_v6_addr_mask = ipv6_dst_addr_mask lpm_v6_addr = ipv6_dst_addr exm_0_v6_addr = ipv6_dst_addr exm_1_v6_addr = ipv6_dst_addr if is_multi_field == True: # This indicates that the total 4 field slices are from 2 different fields, (2 slices from 1 field each) # Thus, the first exm field slice and tcam field slice are actually slices of a ipv6 src addr (Refer the p4 # program for deduction). Hence set them accordingly tcam_v6_addr = ipv6_src_addr tcam_v6_addr_mask = ipv6_src_addr_mask exm_0_v6_addr = ipv6_src_addr pkt = testutils.simple_tcpv6_packet(eth_dst=dmac, ipv6_dst=ipv6_dst_addr, ipv6_src=ipv6_src_addr) exp_pkt = pkt # Start off by expecting the sent packet to match on all the fields should_exm_match_0 = True should_exm_match_1 = True should_tcam_match = True should_lpm_match = True # For different iterations of the test, we want to tamper with different fields individually if entry_idx % 5 == 1: should_exm_match_0 = False elif entry_idx % 5 == 2: should_exm_match_1 = False elif entry_idx % 5 == 3: should_tcam_match = False elif entry_idx % 5 == 4: should_lpm_match = False # We use this set to keep track of bits we want to flip/garble within a field slice garble_bit_index = set() # exm exm_val_0 = getIpv6AddrFieldSliceValue(exm_0_field_name, exm_0_v6_addr) exm_field_byte_width_0 = getFieldSliceByteWidthFromName( exm_0_field_name) exm_field_bit_width_0 = getFieldSliceBitWidthFromName( exm_0_field_name) logger.debug("EXM_0 value before scrambling " + hex(exm_val_0)) # Scramble bits if we want the pkt to miss in this iteration because of a mismatch on this field if should_exm_match_0 == False: # Flip any bit which we expect to match on index = random.randint(0, exm_field_bit_width_0 - 1) exm_val_0 = garbleBits(exm_val_0, [index]) logger.debug("EXM_0 value after scrambling " + hex(exm_val_0)) # ternary tcam_val = getIpv6AddrFieldSliceValue(tcam_field_name, tcam_v6_addr) tcam_mask = getIpv6AddrFieldSliceValue(tcam_field_name, tcam_v6_addr_mask) tcam_field_bit_width = getFieldSliceBitWidthFromName( tcam_field_name) tcam_field_byte_width = getFieldSliceByteWidthFromName( tcam_field_name) logger.debug("TCAM value before scrambling " + hex(tcam_val)) # Scramble bits if we want the pkt to miss in this iteration because of a mismatch on this field if should_tcam_match == False: # Flip any bit which we expect to match on index = tcam_field_bit_width for i in range(tcam_field_bit_width): if ((tcam_mask >> i) & 0x01) == 1: index = i if index == tcam_field_bit_width: # indicates that the generated mask is all zeros. Thus ternary field is always going to match # Hence flip the flag accordingly should_tcam_match = True else: tcam_val = garbleBits(tcam_val, [index]) # Always scramble bits which are don't care garble_bit_index.clear() for i in range(tcam_field_bit_width): bit_val = (tcam_mask >> i) & 1 if bit_val == 0: garble_bit_index.add(i) tcam_val = garbleBits(tcam_val, garble_bit_index) logger.debug("TCAM value after scrambling " + hex(tcam_val)) # We never scramble the tcam mask logger.debug("TCAM mask " + hex(tcam_mask)) # lpm lpm_value_bit_width = getFieldSliceBitWidthFromName(lpm_field_name) lpm_value_byte_width = getFieldSliceByteWidthFromName( lpm_field_name) p_len = random.randint(1, lpm_value_bit_width) lpm_value = getIpv6AddrFieldSliceValue(lpm_field_name, lpm_v6_addr) logger.debug("LPM value before scrambling " + hex(lpm_value)) logger.debug("LPM prefix width " + hex(p_len)) # Scramble bits if we want the pkt to miss in this iteration because of a mismatch on this field if should_lpm_match == False: # Flip any bit within the prefix length so that the value in the packet # won't match with the value programmed. We are always flipping the bit # at index p_len lpm_value = garbleBits(lpm_value, [lpm_value_bit_width - p_len]) if p_len != lpm_value_bit_width: # Always scramble the bits which are not supposed to be looked up anyway garble_bit_index.clear() for i in range(lpm_value_bit_width - 1 - p_len): garble_bit_index.add(i) lpm_value = garbleBits(lpm_value, garble_bit_index) logger.debug("LPM value after scrambling " + hex(lpm_value)) # exm exm_val_1 = getIpv6AddrFieldSliceValue(exm_1_field_name, exm_1_v6_addr) exm_field_byte_width_1 = getFieldSliceByteWidthFromName( exm_1_field_name) exm_field_bit_width_1 = getFieldSliceBitWidthFromName( exm_1_field_name) logger.debug("EXM_1 value before scrambling " + hex(exm_val_1)) # Scramble bits if we want the pkt to miss in this iteration because of a mismatch on this field if should_exm_match_1 == False: # Flip any bit which we expect to match on index = random.randint(0, exm_field_bit_width_1 - 1) exm_val_1 = garbleBits(exm_val_1, [index]) logger.debug("EXM_1 value after scrambling " + hex(exm_val_1)) logger.info("Insert the entry") table_key = table_obj.make_key([ gc.KeyTuple(self.port_field_name, ig_port), gc.KeyTuple(exm_0_field_name, exm_val_0), gc.KeyTuple(tcam_field_name, tcam_val, tcam_mask), gc.KeyTuple(lpm_field_name, lpm_value, prefix_len=p_len), gc.KeyTuple(exm_1_field_name, exm_val_1), gc.KeyTuple("$MATCH_PRIORITY", 1) ]) table_obj.entry_add(target, [table_key], [getDataObj(table_obj, eg_port)]) # Get the entry resp = table_obj.entry_get(target, None, {"from_hw": True}) # for lpm and tcam, the mask is applied on the value before programming it in the hardware # thus get the expected lpm and tcam val to be read from hw lpm_val_hw = (((lpm_value) >> (lpm_value_bit_width - p_len)) << (lpm_value_bit_width - p_len)) tcam_value_hw = tcam_val & tcam_mask for data, key in resp: data_dict = data.to_dict() key_dict = key.to_dict() assert key_dict[self.port_field_name]['value'] == ig_port assert key_dict[exm_0_field_name]['value'] == exm_val_0 assert key_dict[tcam_field_name]['value'] == tcam_value_hw assert key_dict[tcam_field_name]['mask'] == tcam_mask assert key_dict[lpm_field_name]['value'] == lpm_val_hw assert key_dict[lpm_field_name]['prefix_len'] == p_len assert key_dict[exm_1_field_name]['value'] == exm_val_1 # Send the packet testutils.send_packet(self, ig_port, pkt) logger.info("Should Exm_0 match %d", should_exm_match_0) logger.info("Should Tcam match %d", should_tcam_match) logger.info("Should Lpm match %d", should_lpm_match) logger.info("Should Exm_1 match %d", should_exm_match_1) if should_exm_match_0 == 1 and should_tcam_match == 1 and should_lpm_match == 1 and should_exm_match_1 == 1: # For this iteration we expect the pkt to match on all the field slices logger.info( "Expecting packet on port %d after installing entry %d", eg_port, entry_idx) testutils.verify_packet(self, exp_pkt, eg_port) else: # For this iteration we expect the pkt to miss on any one of the fields and hence to get dropped logger.info( "Expecting the packet to get dropped after installing entry %d", entry_idx) testutils.verify_no_other_packets(self) finally: # Delete the entry logger.info("Delete the entry") table_obj.entry_del(target, [table_key]) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped.") testutils.verify_no_other_packets(self)
def runTest(self): ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' logger.info("Range field slices are not supported yet") # FIXME This test fails return self.set_bfrt_info( self.parse_bfrt_info(self.get_bfrt_info("tna_field_slice"))) target = self.Target(device_id=0, pipe_id=0xffff) num_entries = 100 for entry_idx in range(num_entries): logger.info("Processing entry %d", entry_idx) try: ipv6_dst_addr = generateIpv6Addr() pkt = testutils.simple_tcpv6_packet(eth_dst=dmac, ipv6_dst=ipv6_dst_addr) logger.debug("Ipv6 addr is " + ipv6_dst_addr) exp_pkt = pkt range_bit_width = getFieldSliceBitWidthFromName( self.range_field_name) range_byte_width = getFieldSliceByteWidthFromName( self.range_field_name) range_start = 1 range_end = 0 while range_end < range_start: range_start = random.randint(0, pow(2, range_bit_width)) range_end = random.randint(0, pow(2, range_bit_width)) pkt_range_value = getIpv6AddrFieldSliceValue( self.range_field_name, ipv6_dst_addr) range_start = pkt_range_value - 1 range_end = pkt_range_value + 1 should_range_match = False if pkt_range_value >= range_start and pkt_range_value <= range_end: logger.info("Entry is expected to hit") should_range_match = True else: logger.info("Entry is expected to miss") logger.debug("Range start is " + hex(range_start)) logger.debug("Range end is " + hex(range_end)) logger.debug("Pkt Range value is " + hex(pkt_range_value)) logger.info("Insert the entry") self.insert_table_entry( target, self.table_name, [ self.KeyField('ig_intr_md.ingress_port', self.to_bytes(ig_port, 2)), self.KeyField( self.range_field_name, low=self.to_bytes(range_start, range_byte_width), high=self.to_bytes(range_end, range_byte_width)), self.KeyField("$MATCH_PRIORITY", self.to_bytes(1, 4)) ], 'SwitchIngress.hit', [self.DataField('port', self.to_bytes(eg_port, 2))]) testutils.send_packet(self, ig_port, pkt) if should_range_match == True: logger.info("Expecting packet on port %d", eg_port) testutils.verify_packet(self, exp_pkt, eg_port) testutils.verify_no_other_packets(self) # Get key field ids key_port_field_id = self.get_key_field( self.table_name, "ig_intr_md.ingress_port") key_ipv6_dst_field_id = self.get_key_field( self.table_name, self.range_field_name) # Get all the entries resp = self.get_table_entry(target, self.table_name, None, {"from_hw": True}) key_dict = {} entry_iter = self.parseEntryGetResponse(resp, key_dict) for data_dict in entry_iter: assert key_dict[key_port_field_id][ 'value'] == self.to_bytes(ig_port, 2) assert key_dict[key_ipv6_dst_field_id][ 'low'] == self.to_bytes(range_start, range_byte_width) assert key_dict[key_ipv6_dst_field_id][ 'high'] == self.to_bytes(range_end, range_byte_width) finally: logger.info("Delete the entry") self.delete_table_entry(target, self.table_name, [ self.KeyField('ig_intr_md.ingress_port', self.to_bytes(ig_port, 2)), self.KeyField( self.range_field_name, low=self.to_bytes(range_start, range_byte_width), high=self.to_bytes(range_end, range_byte_width)), self.KeyField("$MATCH_PRIORITY", self.to_bytes(1, 4)) ]) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped.") testutils.verify_no_other_packets(self)
def SingleFieldSingleSliceLpmHelper(self, table_obj, lpm_field_name): """ @brief This is a helper function that adds a field slice entry in the table, sends packets and verifies, reads back the entry and verifies and then finally deletes the entry """ ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' num_entries = 100 for entry_idx in range(num_entries): logger.info("Processing entry %d", entry_idx) try: # Generate ipv6 addr ipv6_dst_addr = generateIpv6Addr() logger.debug("Ipv6 addr is " + ipv6_dst_addr) pkt = testutils.simple_tcpv6_packet(eth_dst=dmac, ipv6_dst=ipv6_dst_addr) exp_pkt = pkt target = gc.Target(device_id=0, pipe_id=0xffff) # Extract the lpm val, lpm field width in bits and bytes that is going to be programmed from the # generated ipv6 addr lpm_field_val = getIpv6AddrFieldSliceValue(lpm_field_name, ipv6_dst_addr) lpm_field_width_byte = getFieldSliceByteWidthFromName( lpm_field_name) lpm_value_bit_width = getFieldSliceBitWidthFromName(lpm_field_name) # Choose a prefix len between 1 and lpm field bit width p_len = random.randint(1, lpm_value_bit_width) logger.debug("LPM val is " + hex(lpm_field_val)) logger.debug("LPM prefix len is " + hex(p_len)) # Insert the entry logger.info("Insert the entry") table_key = table_obj.make_key([ gc.KeyTuple(self.port_field_name, ig_port), gc.KeyTuple(lpm_field_name, lpm_field_val, prefix_len=p_len) ]) table_obj.entry_add(target, [table_key], [getDataObj(table_obj, eg_port)]) testutils.send_packet(self, ig_port, pkt) logger.info("Expecting packet on port %d", eg_port) testutils.verify_packet(self, exp_pkt, eg_port) testutils.verify_no_other_packets(self) # Get the entry resp = table_obj.entry_get(target, None, {"from_hw": True}) # for lpm, the mask is applied on the value before programming it in the hardware # thus get the expected lpm field val to be read from hw lpm_field_val_hw = (((lpm_field_val) >> (lpm_value_bit_width - p_len)) << (lpm_value_bit_width - p_len)) for data, key in resp: data_dict = data.to_dict() key_dict = key.to_dict() assert key_dict[self.port_field_name]['value'] == ig_port assert key_dict[lpm_field_name]['value'] == lpm_field_val_hw assert key_dict[lpm_field_name]['prefix_len'] == p_len finally: # Delete the entry logger.info("Delete the entry") table_obj.entry_del(target, [table_key]) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped.") testutils.verify_no_other_packets(self)
def runTest(self): ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' bfrt_info = self.interface.bfrt_info_get("tna_field_slice") num_entries = 100 table_obj = bfrt_info.table_get(self.table_name) table_key = None for entry_idx in range(num_entries): logger.info("Processing entry %d", entry_idx) try: # Generate ipv6 addr ipv6_dst_addr = generateIpv6Addr() logger.debug("Ipv6 addr is " + ipv6_dst_addr) pkt = testutils.simple_tcpv6_packet(eth_dst=dmac, ipv6_dst=ipv6_dst_addr) exp_pkt = pkt target = gc.Target(device_id=0, pipe_id=0xffff) # Extract the exact match val that is going to be programmed from the # generated ipv6 addr exm_value = getIpv6AddrFieldSliceValue(self.exm_field_name, ipv6_dst_addr) logger.debug("EXM val is " + hex(exm_value)) # Insert the entry logger.info("Insert the entry") table_key = table_obj.make_key([ gc.KeyTuple(self.port_field_name, ig_port), gc.KeyTuple(self.exm_field_name, exm_value) ]) table_obj.entry_add(target, [table_key], [getDataObj(table_obj, eg_port)]) testutils.send_packet(self, ig_port, pkt) logger.info("Expecting packet on port %d", eg_port) testutils.verify_packet(self, exp_pkt, eg_port) testutils.verify_no_other_packets(self) # Get the entry resp = table_obj.entry_get(target, None, {"from_hw": True}) for data, key in resp: data_dict = data.to_dict() key_dict = key.to_dict() assert key_dict[self.port_field_name]['value'] == ig_port assert key_dict[self.exm_field_name]['value'] == exm_value finally: # Delete the entry if table_key: logger.info("Delete the entry") table_obj.entry_del(target, [table_key]) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped") testutils.verify_no_other_packets(self)
def runTest(self): ig_port = swports[1] eg_port = swports[2] dmac = '22:22:22:22:22:22' bfrt_info = self.interface.bfrt_info_get("tna_field_slice") num_entries = 100 table_obj = bfrt_info.table_get(self.table_name) for entry_idx in range(num_entries): logger.info("Processing entry %d", entry_idx) try: # Generate ipv6 addr and mask ipv6_dst_addr = generateIpv6Addr() ipv6_dst_addr_mask = generateIpv6Addr() logger.debug("Ipv6 addr is : " + ipv6_dst_addr) logger.debug("Ipv6 addr mask is :" + ipv6_dst_addr_mask) pkt = testutils.simple_tcpv6_packet(eth_dst=dmac, ipv6_dst=ipv6_dst_addr) exp_pkt = pkt target = gc.Target(device_id=0, pipe_id=0xffff) # Extract the tcam val and mask that is going to be programmed from the # generated ipv6 addr and mask tcam_field_val = getIpv6AddrFieldSliceValue( self.tcam_field_name, ipv6_dst_addr) logger.debug("TCAM val is " + hex(tcam_field_val)) tcam_field_mask = getIpv6AddrFieldSliceValue( self.tcam_field_name, ipv6_dst_addr_mask) logger.debug("TCAM mask is " + hex(tcam_field_mask)) tcam_field_width_byte = getFieldSliceByteWidthFromName( self.tcam_field_name) # Insert the entry logger.info("Insert the entry") table_key = table_obj.make_key([ gc.KeyTuple(self.port_field_name, ig_port), gc.KeyTuple(self.tcam_field_name, tcam_field_val, tcam_field_mask), gc.KeyTuple("$MATCH_PRIORITY", 1) ]) table_obj.entry_add(target, [table_key], [getDataObj(table_obj, eg_port)]) testutils.send_packet(self, ig_port, pkt) logger.info("Expecting packet on port %d", eg_port) testutils.verify_packet(self, exp_pkt, eg_port) testutils.verify_no_other_packets(self) # Get the entry resp = table_obj.entry_get(target, None, {"from_hw": True}) # For tcam, the mask is applied on the value before programming it in the hardware # Thus form the expected tcam value to be read from the hw tcam_field_val_hw = (tcam_field_val & tcam_field_mask) for data, key in resp: data_dict = data.to_dict() key_dict = key.to_dict() assert key_dict[self.port_field_name]['value'] == ig_port assert key_dict[ self.tcam_field_name]['value'] == tcam_field_val_hw assert key_dict[ self.tcam_field_name]['mask'] == tcam_field_mask finally: # Delete the entry logger.info("Delete the entry") table_obj.entry_del(target, [table_key]) testutils.send_packet(self, ig_port, pkt) logger.info("Packet is expected to get dropped.") testutils.verify_no_other_packets(self)
def check_ipv6_route(self, hash_key, src_port, dst_port_list): ''' @summary: Check IPv6 route works. @param hash_key: hash key to build packet with. @param in_port: index of port to use for sending packet to switch @param dst_port_list: list of ports on which to expect packet to come back from the switch @return Boolean ''' base_mac = self.dataplane.get_mac(0, 0) ip_src = self.src_ip_interval.get_random_ip( ) if hash_key == 'src-ip' else self.src_ip_interval.get_first_ip() ip_dst = self.dst_ip_interval.get_random_ip( ) if hash_key == 'dst-ip' else self.dst_ip_interval.get_first_ip() sport = random.randint(0, 65535) if hash_key == 'src-port' else 1234 dport = random.randint(0, 65535) if hash_key == 'dst-port' else 80 src_mac = (base_mac[:-5] + "%02x" % random.randint(0, 255) + ":" + "%02x" % random.randint(0, 255)) \ if hash_key == 'src-mac' else base_mac router_mac = self.ptf_test_port_map[str(src_port)]['target_mac'] exp_router_mac = self.router_macs[self.ptf_test_port_map[str(src_port)] ['target_dut']] vlan_id = random.choice(self.vlan_ids) if hash_key == 'vlan-id' else 0 ip_proto = self._get_ip_proto( ipv6=True) if hash_key == "ip-proto" else None pkt = simple_tcpv6_packet( pktlen=100 if vlan_id == 0 else 104, eth_dst=router_mac, eth_src=src_mac, dl_vlan_enable=False if vlan_id == 0 else True, vlan_vid=vlan_id, vlan_pcp=0, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=64) exp_pkt = simple_tcpv6_packet(eth_src=exp_router_mac, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=63) if hash_key == 'ip-proto': pkt['IPv6'].nh = ip_proto exp_pkt['IPv6'].nh = ip_proto masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") send_packet(self, src_port, pkt) logging.info('Sent Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format(pkt.src, pkt.dst, pkt['IPv6'].src, pkt['IPv6'].dst, sport, dport)) logging.info('Expect Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format(exp_router_mac, 'any', ip_src, ip_dst, sport, dport)) return verify_packet_any_port(self, masked_exp_pkt, dst_port_list)
def check_ipv6_route(self, hash_key, src_port, dst_port_list): ''' @summary: Check IPv6 route works. @param hash_key: hash key to build packet with. @param in_port: index of port to use for sending packet to switch @param dst_port_list: list of ports on which to expect packet to come back from the switch @return Boolean ''' ip_src = self.src_ip_interval.get_random_ip( ) if hash_key == 'src-ip' else self.src_ip_interval.get_first_ip() ip_dst = self.dst_ip_interval.get_random_ip( ) if hash_key == 'dst-ip' else self.dst_ip_interval.get_first_ip() sport = random.randint(0, 65535) if hash_key == 'src-port' else 1234 dport = random.randint(0, 65535) if hash_key == 'dst-port' else 80 src_mac = (self.base_mac[:-5] + "%02x" % random.randint(0, 255) + ":" + "%02x" % random.randint(0, 255)) \ if hash_key == 'src-mac' else self.base_mac router_mac = self.ptf_test_port_map[str(src_port)]['target_mac'] vlan_id = random.choice(self.vlan_ids) if hash_key == 'vlan-id' else 0 ip_proto = self._get_ip_proto( ipv6=True) if hash_key == "ip-proto" else None pkt = simple_tcpv6_packet( pktlen=100 if vlan_id == 0 else 104, eth_dst=router_mac, eth_src=src_mac, dl_vlan_enable=False if vlan_id == 0 else True, vlan_vid=vlan_id, vlan_pcp=0, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=64) exp_pkt = simple_tcpv6_packet(ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=63) if hash_key == 'ip-proto': pkt['IPv6'].nh = ip_proto exp_pkt['IPv6'].nh = ip_proto masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") # mask the chksum also if masking the ttl if self.ignore_ttl: masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.TCP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src") send_packet(self, src_port, pkt) logging.info('Sent Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={} on port {})'\ .format(pkt.src, pkt.dst, pkt['IPv6'].src, pkt['IPv6'].dst, sport, dport, src_port)) logging.info('Expect Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format('any', 'any', ip_src, ip_dst, sport, dport)) rcvd_port, rcvd_pkt = verify_packet_any_port(self, masked_exp_pkt, dst_port_list) exp_src_mac = self.router_macs[self.ptf_test_port_map[str( dst_port_list[rcvd_port])]['target_dut']] actual_src_mac = Ether(rcvd_pkt).src if exp_src_mac != actual_src_mac: raise Exception( "Pkt sent from {} to {} on port {} was rcvd pkt on {} which is one of the expected ports, " "but the src mac doesn't match, expected {}, got {}".format( ip_src, ip_dst, src_port, dst_port_list[rcvd_port], exp_src_mac, actual_src_mac)) return (rcvd_port, rcvd_pkt)
def check_ipv6_route(self, src_port, dst_ip_addr, dst_port_list): ''' @summary: Check IPv6 route works. @param source_port_index: index of port to use for sending packet to switch @param dest_ip_addr: destination IP to build packet with. @param dst_port_list: list of ports on which to expect packet to come back from the switch @return Boolean ''' sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = '2000:0030::1' ip_dst = dst_ip_addr src_mac = self.dataplane.get_mac(0, src_port) router_mac = self.ptf_test_port_map[str(src_port)]['target_mac'] pkt = simple_tcpv6_packet(pktlen=self.pktlen, eth_dst=router_mac, eth_src=src_mac, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=self.ttl, dl_vlan_enable=self.src_vid is not None, vlan_vid=self.src_vid or 0) exp_pkt = simple_tcpv6_packet(pktlen=self.pktlen, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=max(self.ttl - 1, 0), dl_vlan_enable=self.dst_vid is not None, vlan_vid=self.dst_vid or 0) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src") # mask the chksum also if masking the ttl if self.ignore_ttl: masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.TCP, "chksum") send_packet(self, src_port, pkt) logging.info('Sent Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={}) on port {}'\ .format(pkt.src, pkt.dst, pkt['IPv6'].src, pkt['IPv6'].dst, sport, dport, src_port)) logging.info('Expect Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format('any', 'any', ip_src, ip_dst, sport, dport)) if self.pkt_action == self.ACTION_FWD: rcvd_port, rcvd_pkt = verify_packet_any_port( self, masked_exp_pkt, dst_port_list) exp_src_mac = self.router_macs[self.ptf_test_port_map[str( dst_port_list[rcvd_port])]['target_dut']] actual_src_mac = Ether(rcvd_pkt).src if actual_src_mac != exp_src_mac: raise Exception( "Pkt sent from {} to {} on port {} was rcvd pkt on {} which is one of the expected ports, " "but the src mac doesn't match, expected {}, got {}". format(ip_src, ip_dst, src_port, dst_port_list[rcvd_port], exp_src_mac, actual_src_mac)) return (rcvd_port, rcvd_pkt) elif self.pkt_action == self.ACTION_DROP: return verify_no_packet_any(self, masked_exp_pkt, dst_port_list)
def test_encap(self, ptf_port, vni, ptf_addr, destination, nhs, test_ecn=False, vlan=0): rv = True try: pkt_len = self.DEFAULT_PKT_LEN if 'vlan' != 0: tagged = True pkt_len += 4 else: tagged = False options = {'ip_ecn': 0} options_v6 = {'ipv6_ecn': 0} if test_ecn: ecn = random.randint(0, 3) options = {'ip_ecn': ecn} options_v6 = {'ipv6_ecn': ecn} # ECMP support, assume it is a string of comma seperated list of addresses. returned_ip_addresses = {} check_ecmp = False for host_address in nhs: check_ecmp = True # This will ensure that every nh is used atleast once. for i in range(self.packet_count): tcp_sport = get_incremental_value('tcp_sport') valid_combination = True if isinstance(ip_address(destination), ipaddress.IPv4Address) and isinstance( ip_address(ptf_addr), ipaddress.IPv4Address): pkt_opts = { "pktlen": pkt_len, "eth_dst": self.dut_mac, "eth_src": self.ptf_mac_addrs['eth%d' % ptf_port], "ip_dst": destination, "ip_src": ptf_addr, "ip_id": 105, "ip_ttl": 64, "tcp_sport": tcp_sport, "tcp_dport": VARS['tcp_dport'] } pkt_opts.update(options) pkt = simple_tcp_packet(**pkt_opts) pkt_opts['ip_ttl'] = 63 pkt_opts['eth_src'] = self.dut_mac exp_pkt = simple_tcp_packet(**pkt_opts) elif isinstance(ip_address(destination), ipaddress.IPv6Address) and isinstance( ip_address(ptf_addr), ipaddress.IPv6Address): pkt_opts = { "pktlen": pkt_len, "eth_dst": self.dut_mac, "eth_src": self.ptf_mac_addrs['eth%d' % ptf_port], "ipv6_dst": destination, "ipv6_src": ptf_addr, "ipv6_hlim": 64, "tcp_sport": tcp_sport, "tcp_dport": VARS['tcp_dport'] } pkt_opts.update(options_v6) pkt = simple_tcpv6_packet(**pkt_opts) pkt_opts['ipv6_hlim'] = 63 pkt_opts['eth_src'] = self.dut_mac exp_pkt = simple_tcpv6_packet(**pkt_opts) else: valid_combination = False udp_sport = 1234 # Use entropy_hash(pkt), it will be ignored in the test later. udp_dport = self.vxlan_port if isinstance(ip_address(host_address), ipaddress.IPv4Address): encap_pkt = simple_vxlan_packet( eth_src=self.dut_mac, eth_dst=self.random_mac, ip_id=0, ip_src=self.loopback_ipv4, ip_dst=host_address, ip_ttl=128, udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt, **options) encap_pkt[scapy.IP].flags = 0x2 elif isinstance(ip_address(host_address), ipaddress.IPv6Address): encap_pkt = simple_vxlanv6_packet( eth_src=self.dut_mac, eth_dst=self.random_mac, ipv6_src=self.loopback_ipv6, ipv6_dst=host_address, udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt, **options_v6) send_packet(self, ptf_port, str(pkt)) masked_exp_pkt = Mask(encap_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src") masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") if isinstance(ip_address(host_address), ipaddress.IPv4Address): masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy( scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "dst") else: masked_exp_pkt.set_do_not_care_scapy( scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy( scapy.IPv6, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "dst") masked_exp_pkt.set_do_not_care_scapy(scapy.UDP, "sport") masked_exp_pkt.set_do_not_care_scapy(scapy.UDP, "chksum") logger.info("Sending packet from port " + str(ptf_port) + " to " + destination) if self.expect_encap_success: _, received_pkt = verify_packet_any_port( self, masked_exp_pkt, self.t2_ports) scapy_pkt = scapy.Ether(received_pkt) # Store every destination that was received. if isinstance(ip_address(host_address), ipaddress.IPv6Address): dest_ip = scapy_pkt['IPv6'].dst else: dest_ip = scapy_pkt['IP'].dst try: returned_ip_addresses[ dest_ip] = returned_ip_addresses[dest_ip] + 1 except KeyError: returned_ip_addresses[dest_ip] = 1 else: check_ecmp = False logger.info("Verifying no packet") verify_no_packet_any(self, masked_exp_pkt, self.t2_ports) # Verify ECMP: if check_ecmp: self.verify_all_addresses_used_equally(nhs, returned_ip_addresses) pkt.load = '0' * 60 + str(len(self.packets)) self.packets.append((ptf_port, str(pkt).encode("base64"))) finally: logger.info("")
def check_ipv6_route(self, src_port, dst_ip_addr, dst_port_list): ''' @summary: Check IPv6 route works. @param source_port_index: index of port to use for sending packet to switch @param dest_ip_addr: destination IP to build packet with. @param dst_port_list: list of ports on which to expect packet to come back from the switch @return Boolean ''' sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = '2000:0030::1' ip_dst = dst_ip_addr src_mac = self.dataplane.get_mac(0, src_port) router_mac = self.ptf_test_port_map[str(src_port)]['target_mac'] exp_router_mac = self.router_macs[self.ptf_test_port_map[str(src_port)]['target_dut']] pkt = simple_tcpv6_packet( pktlen=self.pktlen, eth_dst=router_mac, eth_src=src_mac, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=self.ttl, dl_vlan_enable=self.src_vid is not None, vlan_vid=self.src_vid or 0) exp_pkt = simple_tcpv6_packet( pktlen=self.pktlen, eth_src=exp_router_mac, ipv6_dst=ip_dst, ipv6_src=ip_src, tcp_sport=sport, tcp_dport=dport, ipv6_hlim=max(self.ttl-1, 0), dl_vlan_enable=self.dst_vid is not None, vlan_vid=self.dst_vid or 0) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether,"dst") send_packet(self, src_port, pkt) logging.info('Sent Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format(pkt.src, pkt.dst, pkt['IPv6'].src, pkt['IPv6'].dst, sport, dport)) logging.info('Expect Ether(src={}, dst={})/IPv6(src={}, dst={})/TCP(sport={}, dport={})'\ .format(exp_router_mac, 'any', ip_src, ip_dst, sport, dport)) if self.pkt_action == self.ACTION_FWD: return verify_packet_any_port(self, masked_exp_pkt, dst_port_list) elif self.pkt_action == self.ACTION_DROP: return verify_no_packet_any(self, masked_exp_pkt, dst_port_list)
def craft_packet(src_mac, dst_mac, dst_ip, ip_version, stage, tagged_mode, vlan_id=10, outer_vlan_id=0, pkt_type=None): """ Generate IPV4/IPV6 packets with single or double Vlan Header Args: src_mac: Source MAC address dst_mac: Dest MAC address dst_ip: IP address of packet ip_version: Ip version of packet that should be generated stage: ingress or egress tagged_mode: TAGGED or UNTAGGED vlan_id: Vlan Id number dl_vlan_outer: Outer Vlan ID pkt_type: packet type to be created Returns: QinQ or TCP packet """ DUMMY_IP = '8.8.8.8' exp_pkt_with_tag = tagged_mode in [TYPE_TAGGED, TYPE_COMBINE_TAGGED] if ip_version == IPV4: if pkt_type == 'qinq': pkt = testutils.simple_qinq_tcp_packet(eth_src=src_mac, eth_dst=dst_mac, dl_vlan_outer=outer_vlan_id, vlan_vid=vlan_id, ip_src=DUMMY_IP, ip_dst=dst_ip) if exp_pkt_with_tag: exp_pkt = testutils.simple_tcp_packet( pktlen=96, # Default len (100) - Dot1Q len (4) eth_src=src_mac, eth_dst=dst_mac, dl_vlan_enable=True, vlan_vid=vlan_id, ip_src=DUMMY_IP, ip_dst=dst_ip) else: exp_pkt = pkt else: pkt = testutils.simple_tcp_packet(eth_src=src_mac, eth_dst=dst_mac, ip_src=DUMMY_IP, ip_dst=dst_ip) if exp_pkt_with_tag: exp_pkt = testutils.simple_tcp_packet( pktlen=104, # Default len(100) + Dot1Q len (4) eth_src=src_mac, eth_dst=dst_mac, dl_vlan_enable=True, vlan_vid=outer_vlan_id, ip_src=DUMMY_IP, ip_dst=dst_ip) else: exp_pkt = pkt.copy() exp_pkt = mask.Mask(exp_pkt) exp_pkt.set_do_not_care_scapy(Ether, 'src') exp_pkt.set_do_not_care_scapy(Ether, 'dst') exp_pkt.set_do_not_care_scapy(IP, 'ttl') exp_pkt.set_do_not_care_scapy(IP, 'chksum') else: pkt = testutils.simple_tcpv6_packet(eth_src=src_mac, eth_dst=dst_mac, dl_vlan_enable=True, vlan_vid=outer_vlan_id, ipv6_dst=dst_ip) if exp_pkt_with_tag: exp_pkt = testutils.simple_tcpv6_packet( pktlen=96, # Default len (100) - Dot1Q len (4) eth_src=src_mac, eth_dst=dst_mac, ipv6_dst=dst_ip) else: exp_pkt = pkt return pkt, exp_pkt