def runTest(self): print "Sending L2 packet - port 1 -> port 2 [trunk vlan=10])" switch_init(self.client) vlan_id = 10 port1 = port_list[1] port2 = port_list[2] mac1 = '00:11:11:11:11:11' mac2 = '00:22:22:22:22:22' mac_action = 1 self.client.sai_thrift_create_vlan(vlan_id) vlan_port1 = sai_thrift_vlan_port_t(port_id=port1, tagging_mode=1) vlan_port2 = sai_thrift_vlan_port_t(port_id=port2, tagging_mode=0) self.client.sai_thrift_add_ports_to_vlan(vlan_id, [vlan_port1, vlan_port2]) sai_thrift_create_fdb(self.client, vlan_id, mac1, port1, mac_action) sai_thrift_create_fdb(self.client, vlan_id, mac2, port2, mac_action) pkt = simple_tcp_packet(eth_dst='00:11:11:11:11:11', eth_src='00:22:22:22:22:22', ip_dst='10.0.0.1', ip_id=102, ip_ttl=64) exp_pkt = simple_tcp_packet(eth_dst='00:11:11:11:11:11', eth_src='00:22:22:22:22:22', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=10, ip_id=102, ip_ttl=64, pktlen=104) # illustrates how to use a mask even if no impact here m = Mask(exp_pkt) m.set_do_not_care_scapy(IP, 'ttl') try: send_packet(self, 2, pkt) verify_packets(self, m, [1]) finally: sai_thrift_delete_fdb(self.client, vlan_id, mac1, port1) sai_thrift_delete_fdb(self.client, vlan_id, mac2, port2) self.client.sai_thrift_remove_ports_from_vlan(vlan_id, [vlan_port1, vlan_port2]) self.client.sai_thrift_delete_vlan(vlan_id)
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 checkMirroredFlow(self): """ @summary: Send traffic & check how many mirrored packets are received @return: count: number of mirrored packets received Note: Mellanox crafts the GRE packets with extra information: That is: 22 bytes extra information after the GRE header """ payload = self.base_pkt.copy() payload_mask = Mask(payload) if self.mirror_stage == "egress": payload['Ethernet'].src = self.router_mac payload['IP'].ttl -= 1 payload_mask.set_do_not_care_scapy(scapy.Ether, "dst") payload_mask.set_do_not_care_scapy(scapy.IP, "chksum") if self.asic_type in ["mellanox"]: import binascii payload = binascii.unhexlify("0" * 44) + str( payload) # Add the padding exp_pkt = testutils.simple_gre_packet( eth_src=self.router_mac, ip_src=self.session_src_ip, ip_dst=self.session_dst_ip, ip_dscp=self.session_dscp, ip_id=0, #ip_flags = 0x10, # need to upgrade ptf version to support it ip_ttl=self.session_ttl, inner_frame=payload) if self.asic_type in ["mellanox"]: exp_pkt['GRE'].proto = 0x8949 # Mellanox specific else: exp_pkt['GRE'].proto = 0x88be 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.IP, "flags") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care( 38 * 8, len(payload) * 8 ) # don't match payload, payload will be matched by match_payload(pkt) def match_payload(pkt): pkt = scapy.Ether(pkt).load if self.asic_type in ["mellanox"]: pkt = pkt[22:] # Mask the Mellanox specific inner header pkt = scapy.Ether(pkt) return dataplane.match_exp_pkt(payload_mask, pkt) self.dataplane.flush() count = 0 testutils.send_packet(self, self.src_port, self.base_pkt, count=self.NUM_OF_TOTAL_PACKETS) for i in range(0, self.NUM_OF_TOTAL_PACKETS): (rcv_device, rcv_port, rcv_pkt, pkt_time) = testutils.dp_poll(self, timeout=0.1, exp_pkt=masked_exp_pkt) if rcv_pkt is not None and match_payload(rcv_pkt): count += 1 elif count == 0: assert_str = "The first mirrored packet is not recieved" assert count > 0, assert_str # Fast failure without waiting for full iteration else: break # No more packets available logger.info( "Received {} mirrored packets after rate limiting".format(count)) return count
def generate_from_t1(self): self.from_t1 = [] vlan_ip_range = self.test_params['vlan_ip_range'] _, mask = vlan_ip_range.split('/') n_hosts = min(2**(32 - int(mask)) - 3, self.max_nr_vl_pkts) dump = defaultdict(dict) counter = 0 for i in xrange(2, n_hosts + 2): from_t1_src_addr = self.random_ip( self.test_params['default_ip_range']) from_t1_src_port = self.random_port(self.portchannel_ports) from_t1_dst_addr = self.host_ip(vlan_ip_range, i) from_t1_dst_port = self.vlan_ports[i % len(self.vlan_ports)] from_t1_if_name = "eth%d" % from_t1_dst_port from_t1_if_addr = "%s/%s" % (from_t1_dst_addr, vlan_ip_range.split('/')[1]) vlan_mac_hex = '72060001%04x' % counter lag_mac_hex = '5c010203%04x' % counter mac_addr = ':'.join(lag_mac_hex[i:i + 2] for i in range(0, len(lag_mac_hex), 2)) packet = simple_tcp_packet(eth_src=mac_addr, eth_dst=self.dut_mac, ip_src=from_t1_src_addr, ip_dst=from_t1_dst_addr, ip_ttl=255, tcp_dport=5000) self.from_t1.append((from_t1_src_port, str(packet))) dump[from_t1_if_name][from_t1_dst_addr] = vlan_mac_hex counter += 1 exp_packet = simple_tcp_packet( ip_src="0.0.0.0", ip_dst="0.0.0.0", tcp_dport=5000, ) self.from_t1_exp_packet = Mask(exp_packet) self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "src") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "src") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "dst") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "chksum") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.TCP, "chksum") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "ttl") # save data for arp_replay process with open("/tmp/from_t1.json", "w") as fp: json.dump(dump, fp) random_vlan_iface = random.choice(dump.keys()) self.from_server_src_port = int(random_vlan_iface.replace('eth', '')) self.from_server_src_addr = random.choice( dump[random_vlan_iface].keys()) self.from_server_dst_addr = self.random_ip( self.test_params['default_ip_range']) self.from_server_dst_ports = self.portchannel_ports self.nr_vl_pkts = n_hosts return
def verify_relayed_request_relay_forward(self): # Create a packet resembling a DHCPv6 RELAY-FORWARD encapsulating REQUEST packet request_relay_forward_packet = self.create_dhcp_request_relay_forward_packet( ) # Mask off fields we don't care about matching masked_packet = Mask(request_relay_forward_packet) masked_packet.set_do_not_care_scapy(packet.Ether, "dst") masked_packet.set_do_not_care_scapy(IPv6, "src") masked_packet.set_do_not_care_scapy(IPv6, "dst") masked_packet.set_do_not_care_scapy(IPv6, "fl") masked_packet.set_do_not_care_scapy(IPv6, "tc") masked_packet.set_do_not_care_scapy(IPv6, "plen") masked_packet.set_do_not_care_scapy(IPv6, "nh") masked_packet.set_do_not_care_scapy(packet.UDP, "chksum") masked_packet.set_do_not_care_scapy(packet.UDP, "len") masked_packet.set_do_not_care_scapy(DHCP6OptClientLinkLayerAddr, "clladdr") masked_packet.set_do_not_care_scapy( scapy.layers.dhcp6.DHCP6_RelayForward, "linkaddr") # Count the number of these packets received on the ports connected to our leaves request_count = testutils.count_matched_packets_all_ports( self, masked_packet, self.server_port_indices) self.assertTrue(request_count >= 1, "Failed: Request count of %d" % request_count)
def send_and_verify(self, dst_ip, expected_ports, src_port, triple_encap = False): ''' @summary: This function builds encap packet, send and verify their arrival. @dst_ip: the destination ip for the inner IP header @expected_ports: list of ports that a packet can arrived from @src_port: the physical port that the packet will be sent from @triple_encap: True to send triple encapsulated packet ''' #setting parameters src_mac = self.dataplane.get_mac(0, 0) dst_mac = '00:11:22:33:44:55' inner_src_ip = '2.2.2.2' router_mac = self.test_params['router_mac'] dscp_in = random.randint(0, 32) tos_in = dscp_in << 2 dscp_out = random.randint(0, 32) tos_out = dscp_out << 2 if ("pipe" == self.test_params['dscp_mode']): exp_tos = tos_in elif("uniform" == self.test_params['dscp_mode']): exp_tos = tos_out else: print("ERROR: no dscp is configured") exit() default_packet_len = 100 default_packet_add_header_len = 114 #building the packets and the expected packets if (not triple_encap): #for the double encap packet we will use IP header with TCP header without mac inner_pkt = simple_ip_only_packet(ip_dst=dst_ip, ip_src=inner_src_ip, ip_ttl=64, ip_tos=tos_in) #after the decap process the retuning packet will be normal tcp packet, The TTL is taked from the inner layer and redused by one exp_pkt = simple_tcp_packet(pktlen=default_packet_add_header_len, eth_dst=dst_mac, eth_src=router_mac, ip_dst=dst_ip, ip_src=inner_src_ip, ip_tos=exp_tos, ip_ttl=63) else: #Building triple encap packet with SCAPY, because there is no PTF function for it, I use the defualt values for the TCP header tcp_hdr = scapy.TCP(sport=1234, dport=80, flags="S", chksum=0) inner_pkt2 = scapy.IP(src='4.4.4.4', dst='3.3.3.3', tos=0, ttl=64, id=1, ihl=None) / tcp_hdr inner_pkt = scapy.IP(src=inner_src_ip, dst=dst_ip, tos=tos_in, ttl=64, id=1, ihl=None,proto=4) / inner_pkt2 inner_pkt = inner_pkt/("".join([chr(x) for x in xrange(default_packet_len - len(inner_pkt))])) #The expected packet is also built by scapy, and the TTL is taked from the inner layer and redused by one exp_pkt = scapy.Ether(dst=dst_mac, src=router_mac)/inner_pkt exp_pkt['IP'].tos = exp_tos #this parameter is taken by the decap rule configuration exp_pkt['IP'].ttl = 63 pkt = simple_ipv4ip_packet( eth_dst=router_mac, eth_src=src_mac, ip_src='1.1.1.1', ip_dst=self.test_params['lo_ip'], ip_tos=tos_out, ip_ttl=random.randint(2, 63), inner_frame=inner_pkt) #send and verify the return packets 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") send_packet(self, src_port, pkt) logging.info(".....Sending packet from port" + str(src_port) + " to " + dst_ip + ", Triple_encap: " + str(triple_encap)) (matched, received) = verify_packet_any_port(self, masked_exp_pkt, expected_ports) assert received return (matched, received)
def runTest(self): """ For SONiC testing ECMP uniformn distribution over 16 RIFs from 16 differnt ports ---- Test require 32 connected ports and SONiC up and running ---- ---- MUST RUN WITH "--relax" option on the ptf running line ---- Preliminary steps 1. Configure IPs of all of the connected ports (SONiC will configure neighbors) 2. configure all routes (run add_routes.sh on SONiC) Test structure Sending Packets sequance 1. Main loop running on 16 sources ports 2. IP_LAST_WORD_RANGE loop running from 0-254 3. IP_2ND_LAST_WORD_RANGE loop running 0-15 4. Inside loop, to increase the number of packets, with differnt ports 5. Sending and reciving packets, and counting destanation ports - Final counters checking for uniform distribution Final steps For cleaning configuration run remove_routes.sh from SONiC """ switch_init(self.client) random.seed(1) #init vars sport = 0x1234 dport = 0x50 router_mac = self.test_params['router_mac'] destanation_ports = range(NUMBER_OF_SRC_PORTS,NUMBER_OF_DST_PORTS+NUMBER_OF_SRC_PORTS) pkt_counter = [0]*32 logging.debug("the router mac is ") logging.debug( router_mac) logging.debug("the rif macs are") for i in range(16): logging.debug( self.dataplane.get_mac(0, i+16)) #send packets for port in xrange(NUMBER_OF_SRC_PORTS): for i in xrange(IP_LAST_WORD_RANGE): for j in xrange(IP_2ND_LAST_WORD_RANGE): ip_src = '10.0.0.' + str(port * 2 + 32) src_mac = self.dataplane.get_mac(0, 0) ip_dst = '172.16.' + str(j) + '.' + str(i + 1) pkt = simple_tcp_packet( eth_dst=router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, ip_id=i, tcp_sport=sport, tcp_dport=dport, ip_ttl=64) exp_pkt = simple_tcp_packet( eth_dst=self.dataplane.get_mac(0, 16), eth_src=router_mac, ip_src=ip_src, ip_dst=ip_dst, ip_id=i, tcp_sport=sport, tcp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether,"dst") send_packet(self, port, pkt) (match_index,rcv_pkt) = verify_packet_any_port(self,masked_exp_pkt,destanation_ports) logging.debug("found expected packet from port %d" % destanation_ports[match_index]) pkt_counter[match_index] += 1 sport = random.randint(0,0xffff) dport = random.randint(0,0xffff) #final uniform distribution check for stat_port in xrange(NUMBER_OF_DST_PORTS): logging.debug( "PORT #"+str(hex(port_list[stat_port+NUMBER_OF_SRC_PORTS]))+":") logging.debug(str(pkt_counter[stat_port])) self.assertTrue((pkt_counter[stat_port ] >= ((IP_LAST_WORD_RANGE * IP_2ND_LAST_WORD_RANGE) * 0.9)), "Not all paths are equally balanced, %s" % pkt_counter[stat_port+NUMBER_OF_SRC_PORTS]) self.assertTrue((pkt_counter[stat_port ] <= ((IP_LAST_WORD_RANGE * IP_2ND_LAST_WORD_RANGE) * 1.1)), "Not all paths are equally balanced, %s" % pkt_counter[stat_port+NUMBER_OF_SRC_PORTS]) print "END OF TEST"
def _get_expected_mirror_packet(self, mirror_session, setup, duthost, mirror_packet): payload = mirror_packet.copy() # Add vendor specific padding to the packet if duthost.facts["asic_type"] in ["mellanox"]: payload = binascii.unhexlify("0" * 44) + str(payload) if duthost.facts["asic_type"] in ["barefoot"]: payload = binascii.unhexlify("0" * 24) + str(payload) expected_packet = testutils.simple_gre_packet( eth_src=setup["router_mac"], ip_src=mirror_session["session_src_ip"], ip_dst=mirror_session["session_dst_ip"], ip_dscp=int(mirror_session["session_dscp"]), ip_id=0, ip_ttl=int(mirror_session["session_ttl"]), inner_frame=payload) expected_packet["GRE"].proto = mirror_session["session_gre"] expected_packet = Mask(expected_packet) expected_packet.set_do_not_care_scapy(packet.Ether, "dst") expected_packet.set_do_not_care_scapy(packet.IP, "ihl") expected_packet.set_do_not_care_scapy(packet.IP, "len") expected_packet.set_do_not_care_scapy(packet.IP, "flags") expected_packet.set_do_not_care_scapy(packet.IP, "chksum") # The fanout switch may modify this value en route to the PTF so we should ignore it, even # though the session does have a DSCP specified. expected_packet.set_do_not_care_scapy(packet.IP, "tos") # Mask off the payload (we check it later) expected_packet.set_do_not_care(self.OUTER_HEADER_SIZE * 8, len(payload) * 8) return expected_packet
def check_mirrored_packet(self, ipv6=False): """ Send an ARP or ND request and verify that it is mirrored. NOTE: This test only verifies that the payload is correct and that the outermost packet headers are correct (Ether / IP / GRE). Any extra info or headers that an ASIC chooses to include is ignored. Keyword arguments: ipv6 -- the IP version for this test run """ pkt = self.basev6_pkt if ipv6 else self.base_pkt payload = pkt.copy() if self.mirror_stage == "egress": payload['Ethernet'].src = self.router_mac payload['IP'].ttl -= 1 exp_pkt = testutils.simple_gre_packet( eth_src=self.router_mac, ip_src=self.MIRROR_SESSION_SRC_IP, ip_dst=self.MIRROR_SESSION_DST_IP, ip_dscp=self.MIRROR_SESSION_DSCP, ip_id=self.IP_ID, ip_ttl=self.MIRROR_SESSION_TTL, inner_frame=payload) if self.asic_type in ["mellanox"]: exp_pkt['GRE'].proto = self.GRE_PROTO_MLNX else: exp_pkt['GRE'].proto = self.GRE_PROTO_ERSPAN 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.IP, "ihl") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "len") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "flags") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") # NOTE: The fanout modifies the tos field, so it will always be 0 even # if we specify a particular value in the mirror session. masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "tos") # NOTE: Later versions of PTF allow you to ignore extra bytes, which # would allow us to specify an expected packet to be received by # masking off everything but the outer headers (Ether / IP / GRE). # # For now we just trim away any extra headers and check that the packet # matches after it is received. self.dataplane.flush() testutils.send_packet(self, self.src_port, pkt) _, _, rcv_pkt, _ = testutils.dp_poll(self, timeout=0.1) rcv_pkt = self.trim_extra_asic_headers(rcv_pkt, len(payload)) if rcv_pkt and masked_exp_pkt.pkt_match(rcv_pkt): print("{} mirroring succesful".format("ND" if ipv6 else "ARP")) else: assert False
def check_icmp_mtu(self): """Check ICMP/Ping to DUT works for MAX MTU. """ ip_src = self.src_host_ip ip_dst = self.src_router_ip src_mac = self.dataplane.get_mac(0, self.src_ptf_port_list[0]) pktlen = self.pktlen if self.version == 4: pkt = simple_icmp_packet(pktlen=pktlen, eth_dst=self.router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, ip_ttl=64) exp_pkt = simple_icmp_packet(pktlen=pktlen, eth_src=self.router_mac, ip_src=ip_dst, ip_dst=ip_src, icmp_type=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.IP, "id") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.ICMP, "chksum") else: pkt = simple_icmpv6_packet(pktlen=pktlen, eth_dst=self.router_mac, eth_src=src_mac, ipv6_src=ip_src, ipv6_dst=ip_dst, ipv6_hlim=64, icmp_code=0, icmp_type=128) exp_pkt = simple_icmpv6_packet(pktlen=pktlen, eth_src=self.router_mac, ipv6_src=ip_dst, ipv6_dst=ip_src, icmp_type=129, icmp_code=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.IPv6, "id") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "tc") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "fl") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "plen") masked_exp_pkt.set_do_not_care_scapy(scapy.ICMPv6Unknown, "chksum") src_port = self.src_ptf_port_list[0] send_packet(self, src_port, pkt) logging.info("Sending packet from port " + str(src_port) + " address " + ip_src) logging.info("To MAC %s, dst_ip: %s", self.router_mac, ip_dst) dst_port_list = self.src_ptf_port_list logging.info( "Expect packet on port: %s of len %s, eth: %s, ipsrc: %s, ipdst: %s", str(dst_port_list), pktlen, self.router_mac, ip_dst, ip_src) (matched_index, received) = verify_packet_any_port(self, masked_exp_pkt, dst_port_list) assert received matched_port = dst_port_list[matched_index] logging.info("Received packet at " + str(matched_port)) return
def build_ttl0_pkts(version, dst_mac, dst_ip, vm_mac, vm_ip, dut_lb): """ Builds ttl0 packet to send and ICMP TTL exceeded packet to expect back. Args: version: 4 or 6 for dst_mac: Destination MAC, of DUT port. dst_ip: Destination IP, a farend VM interface. vm_mac: Source MAC, of VM port that packets are sent out. vm_ip: Source IP, of the VM port. dut_lb: Loopback of DUT, source of the ICMP packets returned to the VM. Returns: 3 packets, one with ttl0 to send, one as the ICMP expected packet, and one to check for TTL wrapping. """ if version == 4: send_pkt = simple_udp_packet( eth_dst=dst_mac, # mac address of dut eth_src=vm_mac, # mac address of vm1 ip_src=str(vm_ip), ip_dst=str(dst_ip), ip_ttl=0, pktlen=100) exp_pkt255 = simple_udp_packet( eth_dst=dst_mac, # mac address of dut eth_src=vm_mac, # mac address of vm1 ip_src=str(vm_ip), ip_dst=str(dst_ip), ip_ttl=255, pktlen=100) v4_pktsz = 128 exp_pkt = simple_icmp_packet( eth_dst=vm_mac, # mac address of vm1 eth_src=dst_mac, # mac address of dut ip_src=dut_lb, ip_dst=vm_ip, ip_ttl=64, icmp_code=0, icmp_type=11, pktlen=v4_pktsz, ) masked_pkt = Mask(exp_pkt) masked_pkt.set_do_not_care_scapy(scapy.IP, "tos") masked_pkt.set_do_not_care_scapy(scapy.IP, "len") masked_pkt.set_do_not_care_scapy(scapy.IP, "id") masked_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_pkt.set_do_not_care_scapy(scapy.ICMP, "chksum") masked_pkt.set_do_not_care(304, v4_pktsz * 8 - 304) # ignore icmp data else: send_pkt = simple_udpv6_packet( eth_dst=dst_mac, # mac address of dut eth_src=vm_mac, # mac address of vm1 ipv6_src=str(vm_ip), ipv6_dst=str(dst_ip), ipv6_hlim=0, pktlen=100) exp_pkt255 = simple_udpv6_packet( eth_dst=dst_mac, # mac address of dut eth_src=vm_mac, # mac address of vm1 ipv6_src=str(vm_ip), ipv6_dst=str(dst_ip), ipv6_hlim=255, pktlen=100) v6_pktsz = 148 exp_pkt = simple_icmpv6_packet( eth_dst=vm_mac, # mac address of vm1 eth_src=dst_mac, # mac address of dut ipv6_src=str(dut_lb), ipv6_dst=str(vm_ip), ipv6_hlim=64, icmp_code=0, icmp_type=3, pktlen=v6_pktsz, ) # masked_pkt = Mask(exp_pkt) masked_pkt.set_do_not_care_scapy(scapy.IPv6, "tc") masked_pkt.set_do_not_care_scapy(scapy.IPv6, "fl") masked_pkt.set_do_not_care_scapy(scapy.IPv6, "plen") masked_pkt.set_do_not_care_scapy(scapy.ICMPv6Unknown, "cksum") masked_pkt.set_do_not_care(456, v6_pktsz * 8 - 456) # ignore icmp data return send_pkt, masked_pkt, exp_pkt255
def generate_expected_packet(self, inner_pkt): """ Generate ip_in_ip packet for verifying. """ inner_pkt = inner_pkt.copy() inner_pkt.ttl = inner_pkt.ttl - 1 pkt = scapy.Ether(dst=self.active_tor_mac, src=self.standby_tor_mac) / \ scapy.IP(src=self.standby_tor_ip, dst=self.active_tor_ip) / inner_pkt['IP'] exp_pkt = Mask(pkt) exp_pkt.set_do_not_care_scapy(scapy.Ether, 'dst') exp_pkt.set_do_not_care_scapy(scapy.IP, "ihl") exp_pkt.set_do_not_care_scapy(scapy.IP, "tos") exp_pkt.set_do_not_care_scapy(scapy.IP, "len") exp_pkt.set_do_not_care_scapy(scapy.IP, "id") exp_pkt.set_do_not_care_scapy(scapy.IP, "flags") exp_pkt.set_do_not_care_scapy(scapy.IP, "frag") exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") exp_pkt.set_do_not_care_scapy(scapy.IP, "proto") exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") exp_pkt.set_do_not_care_scapy(scapy.TCP, "sport") exp_pkt.set_do_not_care_scapy(scapy.TCP, "seq") exp_pkt.set_do_not_care_scapy(scapy.TCP, "ack") exp_pkt.set_do_not_care_scapy(scapy.TCP, "reserved") exp_pkt.set_do_not_care_scapy(scapy.TCP, "dataofs") exp_pkt.set_do_not_care_scapy(scapy.TCP, "window") exp_pkt.set_do_not_care_scapy(scapy.TCP, "chksum") exp_pkt.set_do_not_care_scapy(scapy.TCP, "urgptr") exp_pkt.set_ignore_extra_bytes() return exp_pkt
def send_and_verify(self, dst_ip, expected_ports, src_port, outer_pkt='ipv4', triple_encap=False, outer_ttl=None, inner_ttl=None): ''' @summary: This function builds encap packet, send and verify their arrival. @dst_ip: the destination ip for the inner IP header @expected_ports: list of ports that a packet can arrived from @src_port: the physical port that the packet will be sent from @triple_encap: True to send triple encapsulated packet @outer_ttl: TTL for the outer layer @inner_ttl: TTL for the inner layer ''' pkt, exp_pkt = self.create_encap_packet(dst_ip, outer_pkt, triple_encap, outer_ttl, inner_ttl) 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") if self.ignore_ttl: if ipaddress.ip_address(unicode(dst_ip)).version == 4: masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") else: masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "chksum") #send and verify the return packets send_packet(self, src_port, pkt) logging.info(".....Sending packet from port" + str(src_port) + " to " + dst_ip + ", Triple_encap: " + str(triple_encap)) matched, received = verify_packet_any_port(self, masked_exp_pkt, expected_ports) assert received return matched, received
def runTest(self): print switch_init(self.client) port1=port_list[0] #From where we expect encapsulated packet port2=port_list[1] #From where we send normal ip packet mac1 = '00:05:06:00:00:00' # port1 l2 entry mac2 = '00:05:06:00:00:02' vr_mac='00:00:08:08:08:08' mac_action=1 vlan_id=0 #expecting to use unused vlans addr_family_ipv4=SAI_IP_ADDR_FAMILY_IPV4 tunnel_src_ip_addr='2.2.2.2' #src for outer ip encap_ip_addr='10.10.1.1' #egress enighbhor ingress_ip_addr='20.20.1.1' #ingress neighbor tunnel_ip_addr_route='1.1.1.0' #to reach tunnel nhop tunnel_ip_mask_route='255.255.255.0' ingress_nhop_ip_addr='20.20.1.1' egress_nhop_ip_addr='10.10.1.1' ip_addr_ingress_route='20.20.1.0' ip_mask_ingress_route='255.255.255.0' ip_addr_encap_route='10.10.1.0' ip_mask_encap_route='255.255.255.0' initiator_ip_addr='10.10.1.1' #tunnel dest ip(outer header) neighbor_mac_ingress='00:05:06:00:00:02' neighbor_mac_encap='00:05:06:00:00:00' #egress side ip_addr_decap_src='10.10.1.1' ip_addr_decap_dst='2.2.2.2' ######################################################################## #Creating Virtual router ####################################################################### vr_id=sai_thrift_create_virtual_router(self.client, 1, 1) #creating a underlay interface in loopback underlay_if = sai_thrift_create_router_interface(self.client, type=SAI_ROUTER_INTERFACE_TYPE_LOOPBACK, port_oid=0, vr_oid=vr_id, vlan_oid=vlan_id, v4_enabled=1, v6_enabled=1, mac='') #creating an overlay interface in loopback overlay_if = sai_thrift_create_router_interface(self.client, type=SAI_ROUTER_INTERFACE_TYPE_LOOPBACK, port_oid=0, vr_oid=vr_id, vlan_oid=vlan_id, v4_enabled=1, v6_enabled=1, mac='') #creating a tunnel tunnel_id=sai_thrift_create_tunnel(self.client, tunnel_type=SAI_TUNNEL_TYPE_IPINIP, addr_family=addr_family_ipv4, ip_addr=tunnel_src_ip_addr, underlay_if=underlay_if, overlay_if=overlay_if, encap_ttl_mode=SAI_TUNNEL_TTL_MODE_PIPE_MODEL, encap_dscp_mode=SAI_TUNNEL_DSCP_MODE_PIPE_MODEL, encap_dscp_val=50) ############################################################################## # Egress configurations # create router interface, # create neighbor # create route # ############################################################################## #encap router interface encap_if_id=sai_thrift_create_router_interface(self.client, vr_oid=vr_id, type=SAI_ROUTER_INTERFACE_TYPE_PORT, port_oid=port1, vlan_oid=vlan_id, v4_enabled = 1, v6_enabled = 1, mac='') #egress(encap side) neighbor (ip=10.10.1.1 , mac=00:05:06:00:00:00 ) sai_thrift_create_neighbor(self.client, addr_family=addr_family_ipv4, rif_id=encap_if_id, ip_addr=encap_ip_addr, dmac=neighbor_mac_encap) #egress(encap) nhop and route create sai_thrift_create_route(self.client, vr_id=vr_id, addr_family=addr_family_ipv4, ip_addr=ip_addr_encap_route, ip_mask=ip_mask_encap_route, nhop=encap_if_id) ############################################################################### # Ingress configurations # create router interface, # create neighbor # create nhop # create route # ############################################################################## #ingress router interface ingress_if_id=sai_thrift_create_router_interface(self.client,vr_oid=vr_id,type=SAI_ROUTER_INTERFACE_TYPE_PORT,port_oid=port2,vlan_oid=vlan_id,v4_enabled=1,v6_enabled = 1, mac='') #ingress neighbor neighbor (ip=20.20.1.1 , mac = 00:05:06:00:00:02) sai_thrift_create_neighbor(self.client, addr_family=addr_family_ipv4, rif_id=ingress_if_id, ip_addr=ingress_ip_addr, dmac=neighbor_mac_ingress) #adding tunnel and route initiator_id=sai_thrift_create_nhop(self.client, addr_family=addr_family_ipv4, ip_addr=initiator_ip_addr, rif_id=tunnel_id , is_tunnel=1) sai_thrift_create_route(self.client,vr_id=vr_id, addr_family=addr_family_ipv4, ip_addr=tunnel_ip_addr_route, ip_mask=tunnel_ip_mask_route, nhop=initiator_id) #Packet to be send pkt = simple_tcp_packet(eth_dst=router_mac, eth_src='00:00:00:00:00:01', ip_src='20.20.1.2', ip_dst='1.1.1.1', ip_id=1, ip_ttl=64) #expected packet inner IP header inner_hdr = simple_tcp_packet(eth_dst=router_mac, eth_src='00:00:00:00:00:01', ip_src='20.20.1.2', ip_dst='1.1.1.1', ip_id=1, ip_ttl=63) exp_pkt = simple_ipv4ip_packet(eth_dst='00:05:06:00:00:00', eth_src=router_mac, ip_dst='10.10.1.1', ip_src='2.2.2.2', ip_id=0,#mask the indentifier during check because it differs every time.better chech with wireshark ip_tos=0xc8, ip_ttl=63, inner_frame=inner_hdr['IP'] ) #masking packet m=Mask(exp_pkt) m.set_do_not_care_scapy(ptf.packet.IP, 'id') m.set_do_not_care_scapy(ptf.packet.IP, 'chksum') try: # in tuple: 0 is device number, 1 is port number # this tuple uniquely identifies a port send_packet(self, 1, pkt) verify_packets(self, m, [0]) finally: sai_thrift_remove_route(self.client,vr_id,addr_family_ipv4,tunnel_ip_addr_route,tunnel_ip_mask_route,initiator_id) self.client.sai_thrift_remove_next_hop(initiator_id) sai_thrift_remove_route(self.client,vr_id,addr_family_ipv4,ip_addr_encap_route,ip_mask_encap_route,encap_if_id) sai_thrift_remove_neighbor(self.client,addr_family_ipv4,rif_id=ingress_if_id,ip_addr=ingress_ip_addr,dmac=neighbor_mac_ingress) sai_thrift_remove_neighbor(self.client,addr_family_ipv4,rif_id=encap_if_id,ip_addr=encap_ip_addr,dmac=neighbor_mac_encap) self.client.sai_thrift_remove_router_interface(ingress_if_id) self.client.sai_thrift_remove_router_interface(encap_if_id) self.client.sai_thrift_remove_tunnel(tunnel_id) self.client.sai_thrift_remove_router_interface(underlay_if) self.client.sai_thrift_remove_router_interface(overlay_if) self.client.sai_thrift_remove_virtual_router(vr_id)
def verify_relayed_request(self): # Create a packet resembling a relayed DCHPREQUEST packet dhcp_request_relayed = self.create_dhcp_request_relayed_packet() # Mask off fields we don't care about matching masked_request = Mask(dhcp_request_relayed) masked_request.set_do_not_care_scapy(scapy.Ether, "dst") masked_request.set_do_not_care_scapy(scapy.IP, "version") masked_request.set_do_not_care_scapy(scapy.IP, "ihl") masked_request.set_do_not_care_scapy(scapy.IP, "tos") masked_request.set_do_not_care_scapy(scapy.IP, "len") masked_request.set_do_not_care_scapy(scapy.IP, "id") masked_request.set_do_not_care_scapy(scapy.IP, "flags") masked_request.set_do_not_care_scapy(scapy.IP, "frag") masked_request.set_do_not_care_scapy(scapy.IP, "ttl") masked_request.set_do_not_care_scapy(scapy.IP, "proto") masked_request.set_do_not_care_scapy(scapy.IP, "chksum") masked_request.set_do_not_care_scapy(scapy.IP, "src") masked_request.set_do_not_care_scapy(scapy.IP, "dst") masked_request.set_do_not_care_scapy(scapy.IP, "options") masked_request.set_do_not_care_scapy(scapy.UDP, "chksum") masked_request.set_do_not_care_scapy(scapy.UDP, "len") masked_request.set_do_not_care_scapy(scapy.BOOTP, "sname") masked_request.set_do_not_care_scapy(scapy.BOOTP, "file") # Count the number of these packets received on the ports connected to our leaves num_expected_packets = self.num_dhcp_servers request_count = testutils.count_matched_packets_all_ports( self, masked_request, self.server_port_indices) self.assertTrue( request_count == num_expected_packets, "Failed: Request count of %d != %d" % (request_count, num_expected_packets))
def send_packets(self): random.seed(time.time()) sport = 0x1234 dport = 0x50 router_mac = self.test_params['router_mac'] destanation_ports = range(NUMBER_OF_SRC_PORTS, NUMBER_OF_DST_PORTS + NUMBER_OF_SRC_PORTS) self.log("the router mac is %s" % router_mac) self.log("the rif macs are:") for i in range(16): self.log(" %s" % self.dataplane.get_mac(0, i + 16)) #send packets for port in xrange(NUMBER_OF_SRC_PORTS): for i in xrange(IP_LAST_WORD_RANGE): for j in xrange(IP_2ND_LAST_WORD_RANGE): ip_src = '10.0.0.' + str(port * 2 + 32) src_mac = self.dataplane.get_mac(0, 0) ip_dst = '172.16.' + str(j) + '.' + str(i + 1) pkt = simple_tcp_packet(eth_dst=router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, ip_id=i * j * port, tcp_sport=sport, tcp_dport=dport, ip_ttl=64) exp_pkt = simple_tcp_packet(eth_dst=self.dataplane.get_mac( 0, 16), eth_src=router_mac, ip_src=ip_src, ip_dst=ip_dst, ip_id=i * j * port, tcp_sport=sport, tcp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") sleep_time = 1 repeat = 5 # Repeat the send action until we receive a packet while True: send_packet(self, port, pkt) self.log( "Sent packet src=%s dst=%s port=%s" % (ip_src, ip_dst, port), True) port_index = self.verify_packet_any_port( masked_exp_pkt, destanation_ports) if port_index is None: self.log( "Expected packet isn't received. Repeating", True) time.sleep(sleep_time) sleep_time *= 2 repeat -= 1 if repeat == 0: self.fail( "Can't receive packet: src=%s dst=%s port=%s" % (ip_src, ip_dst, port)) else: break self.log( "Received expected packet from port %d" % destanation_ports[port_index], True) self.pkt_counter[port_index] += 1 sport = random.randint(0, 0xffff) dport = random.randint(0, 0xffff) return
def runTest(self): print switch_init(self.client) port1 = port_list[0] port2 = port_list[1] port3 = port_list[2] monitor_port=port1 source_port=port2 mac3='00:00:00:00:00:33' mac2='00:00:00:00:00:22' mirror_type=SAI_MIRROR_TYPE_LOCAL sai_thrift_create_fdb(self.client, 2, mac3, port3, 1) sai_thrift_create_fdb(self.client, 2, mac2, port2, 1) # Put ports under test in VLAN 2 self.client.sai_thrift_create_vlan(2) vlan_member1 = sai_thrift_create_vlan_member(self.client, 2, port1, SAI_VLAN_PORT_TAGGED) vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_TAGGED) vlan_member2 = sai_thrift_create_vlan_member(self.client, 2, port2, SAI_VLAN_PORT_TAGGED) vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_TAGGED) vlan_member3 = sai_thrift_create_vlan_member(self.client, 2, port3, SAI_VLAN_PORT_TAGGED) vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_TAGGED) # Remove ports from default VLAN self.client.sai_thrift_remove_vlan_member(vlan_member1a) self.client.sai_thrift_remove_vlan_member(vlan_member2a) self.client.sai_thrift_remove_vlan_member(vlan_member3a) # Set PVID attr_value = sai_thrift_attribute_value_t(u16=2) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) self.client.sai_thrift_set_port_attribute(port1, attr) self.client.sai_thrift_set_port_attribute(port2, attr) self.client.sai_thrift_set_port_attribute(port3, attr) spanid=sai_thrift_create_mirror_session(self.client,mirror_type=mirror_type,port=monitor_port,vlan=1,vlan_priority=0,vlan_tpid=0,src_mac=None,dst_mac=None,addr_family=0,src_ip=None,dst_ip=None,encap_type=0,protocol=0,ttl=0,tos=0,gre_type=0) attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=1,object_id_list=[spanid])) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', eth_src='00:22:22:22:22:22', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=2, ip_id=101, ip_ttl=64) exp_pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', eth_src='00:22:22:22:22:22', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=2, ip_id=101, ip_ttl=64) pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', eth_src='00:33:33:33:33:33', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=2, ip_id=101, ip_ttl=64, pktlen=104) exp_pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', eth_src='00:33:33:33:33:33', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=2,#use vlan_vid field if packets are expected to be monitored on client side otherwise not needed ip_id=101, ip_ttl=64, pktlen=104) m=Mask(exp_pkt2) m.set_do_not_care_scapy(ptf.packet.IP,'id') m.set_do_not_care_scapy(ptf.packet.IP,'chksum') try: # in tuple: 0 is device number, 2 is port number # this tuple uniquely identifies a port # for ingress mirroring print "Checking INGRESS Local Mirroring" print "Sending packet port 2 -> port 3 (00:22:22:22:22:22 -> 00:00:00:00:00:33)" send_packet(self, 1, pkt) verify_packets(self, exp_pkt, ports=[0,2]) # for egress mirroring print "Checking EGRESS Local Mirroring" print "Sending packet port 3 -> port 2 (00:33:33:33:33:33 -> 00:00:00:00:00:22)" send_packet(self, 2, pkt2) verify_each_packet_on_each_port(self, [m,pkt2], ports=[0,1]) finally: sai_thrift_delete_fdb(self.client, 2, mac3, port3) sai_thrift_delete_fdb(self.client, 2, mac2, port2) # Remove ports from mirror destination attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=0,object_id_list=[spanid])) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) # Now you can remove destination self.client.sai_thrift_remove_mirror_session(spanid) # Remove ports from VLAN 2 self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) self.client.sai_thrift_remove_vlan_member(vlan_member3) self.client.sai_thrift_delete_vlan(2) # Add ports back to default VLAN vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_UNTAGGED) vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_UNTAGGED) vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=1) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) self.client.sai_thrift_set_port_attribute(port1, attr) self.client.sai_thrift_set_port_attribute(port2, attr) self.client.sai_thrift_set_port_attribute(port3, attr)
def runTest(self): ecn = 1 dscp = self.queue_index tos = dscp << 2 tos |= ecn matches = re.findall('\[([\d\s]+)\]', self.port_dst) dst_port_list = [] for match in matches: for port in match.split(): dst_port_list.append(int(port)) src_mac = self.dataplane.get_mac( *random.choice(self.dataplane.ports.keys())) if self.port_type == "portchannel": for x in range(0, self.pkt_count): sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = socket.inet_ntoa( struct.pack('>I', random.randint(1, 0xffffffff))) ip_src = ipaddress.IPv4Address(unicode(ip_src, 'utf-8')) if not isinstance(self.ip_dst, unicode): self.ip_dst = unicode(self.ip_dst, 'utf-8') ip_dst = ipaddress.IPv4Address(self.ip_dst) while ip_src == ip_dst or ip_src.is_multicast or ip_src.is_private or ip_src.is_global or ip_src.is_reserved: ip_src = socket.inet_ntoa( struct.pack('>I', random.randint(1, 0xffffffff))) ip_src = ipaddress.IPv4Address(unicode(ip_src, 'utf-8')) ip_src = str(ip_src) pkt_args = { 'eth_dst': self.router_mac, 'eth_src': src_mac, 'ip_src': ip_src, 'ip_dst': self.ip_dst, 'ip_tos': tos, 'tcp_sport': sport, 'tcp_dport': dport, 'ip_ttl': 64 } if self.port_src_vlan_id is not None: pkt_args['dl_vlan_enable'] = True pkt_args['vlan_vid'] = int(self.port_src_vlan_id) pkt_args['vlan_pcp'] = self.queue_index pkt = simple_tcp_packet(**pkt_args) exp_pkt_args = { 'eth_src': self.router_mac, 'ip_src': ip_src, 'ip_dst': self.ip_dst, 'ip_tos': tos, 'tcp_sport': sport, 'tcp_dport': dport, 'ip_ttl': 63 } if self.port_dst_vlan_id is not None: exp_pkt_args['dl_vlan_enable'] = True exp_pkt_args['vlan_vid'] = int(self.port_dst_vlan_id) exp_pkt_args['vlan_pcp'] = self.queue_index exp_pkt = simple_tcp_packet(**exp_pkt_args) 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") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "len") send_packet(self, self.port_src, pkt, 1) else: sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = "1.1.1.1" pkt_args = { 'eth_dst': self.router_mac, 'eth_src': src_mac, 'ip_src': ip_src, 'ip_dst': self.ip_dst, 'ip_tos': tos, 'tcp_sport': sport, 'tcp_dport': dport, 'ip_ttl': 64 } if self.port_src_vlan_id is not None: pkt_args['dl_vlan_enable'] = True pkt_args['vlan_vid'] = int(self.port_src_vlan_id) pkt_args['vlan_pcp'] = self.queue_index pkt = simple_tcp_packet(**pkt_args) exp_pkt_args = { 'eth_src': self.router_mac, 'ip_src': ip_src, 'ip_dst': self.ip_dst, 'ip_tos': tos, 'tcp_sport': sport, 'tcp_dport': dport, 'ip_ttl': 63 } if self.port_dst_vlan_id is not None: exp_pkt_args['dl_vlan_enable'] = True exp_pkt_args['vlan_vid'] = int(self.port_dst_vlan_id) exp_pkt_args['vlan_pcp'] = self.queue_index exp_pkt = simple_tcp_packet(**exp_pkt_args) 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") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "len") send_packet(self, self.port_src, pkt, self.pkt_count) if self.wd_action == 'drop': return verify_no_packet_any(self, masked_exp_pkt, dst_port_list) elif self.wd_action == 'forward': return verify_packet_any_port(self, masked_exp_pkt, dst_port_list)
def test_vlan_tc6_tagged_untagged_unicast( ptfadapter, work_vlan_ports_list, vlan_intfs_dict, toggle_all_simulator_ports_to_rand_selected_tor_m): """ Test case #6 Send packets w/ src and dst specified over tagged port and untagged port in vlan Verify that bidirectional communication between tagged port and untagged port work """ for test_vlan in vlan_intfs_dict: untagged_ports_for_test = [] tagged_ports_for_test = [] for vlan_port in work_vlan_ports_list: if test_vlan not in vlan_port['permit_vlanid']: continue if vlan_port['pvid'] == test_vlan: untagged_ports_for_test.append(vlan_port['port_index']) else: tagged_ports_for_test.append(vlan_port['port_index']) if not untagged_ports_for_test: continue if not tagged_ports_for_test: continue #take two ports for test src_port = untagged_ports_for_test[0] dst_port = tagged_ports_for_test[0] src_mac = ptfadapter.dataplane.get_mac(0, src_port[0]) dst_mac = ptfadapter.dataplane.get_mac(0, dst_port[0]) transmit_untagged_pkt = build_icmp_packet(vlan_id=0, src_mac=src_mac, dst_mac=dst_mac) exp_tagged_pkt = build_icmp_packet(vlan_id=test_vlan, src_mac=src_mac, dst_mac=dst_mac) exp_tagged_pkt = Mask(exp_tagged_pkt) exp_tagged_pkt.set_do_not_care_scapy(scapy.Dot1Q, "prio") return_transmit_tagged_pkt = build_icmp_packet(vlan_id=test_vlan, src_mac=dst_mac, dst_mac=src_mac) exp_untagged_pkt = build_icmp_packet(vlan_id=0, src_mac=dst_mac, dst_mac=src_mac) logger.info( "Untagged({}) packet to be sent from port {} to port {}".format( test_vlan, src_port, dst_port)) verify_unicast_packets(ptfadapter, transmit_untagged_pkt, exp_tagged_pkt, src_port[0], dst_port) logger.info("One Way Untagged Packet Transmission Works") logger.info( "Untagged({}) packet successfully sent from port {} to port {}". format(test_vlan, src_port, dst_port)) logger.info( "Tagged({}) packet to be sent from port {} to port {}".format( test_vlan, dst_port, src_port)) verify_unicast_packets(ptfadapter, return_transmit_tagged_pkt, exp_untagged_pkt, dst_port[0], src_port) logger.info("Two Way tagged Packet Transmission Works") logger.info( "Tagged({}) packet successfully sent from port {} to port {}". format(test_vlan, dst_port, src_port))
def FromServer(self, test): rv = True try: pkt_len = self.DEFAULT_PKT_LEN if test['vlan'] != 0: tagged = True pkt_len += 4 else: tagged = False vni = int(test['vni']) if 'dst_vni' in test: vni = int(test['dst_vni']) pkt = simple_tcp_packet(pktlen=pkt_len, eth_dst=self.dut_mac, eth_src=self.ptf_mac_addrs['eth%d' % test['port']], dl_vlan_enable=tagged, vlan_vid=test['vlan'], ip_dst=test['dst'], ip_src=test['src'], ip_id=105, ip_ttl=64, tcp_sport=1234, tcp_dport=5000) exp_pkt = simple_tcp_packet(eth_dst=test['mac'], eth_src=self.dut_mac, ip_dst=test['dst'], ip_src=test['src'], ip_id=105, ip_ttl=63, tcp_sport=1234, tcp_dport=5000) udp_sport = 1234 # Use entropy_hash(pkt) udp_dport = self.vxlan_port if isinstance(ip_address(test['host']), 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=test['host'], ip_ttl=128, udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt) encap_pkt[IP].flags = 0x2 elif isinstance(ip_address(test['host']), ipaddress.IPv6Address): encap_pkt = simple_vxlanv6_packet(eth_src=self.dut_mac, eth_dst=self.random_mac, ipv6_src=self.loopback_ipv6, ipv6_dst=test['host'], udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt) else: raise Exception("Found invalid IP address in test") send_packet(self, test['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(test['host']), ipaddress.IPv4Address): masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") else: masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.UDP, "sport") log_str = "Sending packet from port " + str( 'eth%d' % test['port']) + " to " + test['dst'] logging.info(log_str) if not self.routes_removed: status, received_pkt = verify_packet_any_port( self, masked_exp_pkt, self.net_ports) if self.vxlan_srcport_range_enabled: scapy_pkt = Ether(received_pkt) assert ( self.vxlan_srcport_lower_bound <= scapy_pkt.sport ) and (self.vxlan_srcport_upper_bound >= scapy_pkt.sport ), ("Received packet has UDP src port {} " "that is not in expected range {} - {}".format( scapy_pkt.sport, self.vxlan_srcport_lower_bound, self.vxlan_srcport_upper_bound)) else: verify_no_packet_any(self, masked_exp_pkt, self.net_ports) pkt.load = '0' * 60 + str(len(self.packets)) self.packets.append((test['port'], str(pkt).encode("base64"))) finally: print
def verify_dhcp_relay_pkt_on_server_port_with_no_padding( self, dst_mac=BROADCAST_MAC, src_port=DHCP_CLIENT_PORT): # Form and send DHCP Relay packet dhcp_request = self.create_dhcp_request_packet(dst_mac, src_port) testutils.send_packet(self, self.client_port_index, dhcp_request) # Mask off fields we don't care about matching # Create a packet resembling a relayed DCHPREQUEST packet dhcp_request_relayed = self.create_dhcp_request_relayed_packet() # Mask off fields we don't care about matching masked_request = Mask(dhcp_request_relayed) masked_request.set_do_not_care_scapy(scapy.Ether, "dst") masked_request.set_do_not_care_scapy(scapy.IP, "version") masked_request.set_do_not_care_scapy(scapy.IP, "ihl") masked_request.set_do_not_care_scapy(scapy.IP, "tos") masked_request.set_do_not_care_scapy(scapy.IP, "len") masked_request.set_do_not_care_scapy(scapy.IP, "id") masked_request.set_do_not_care_scapy(scapy.IP, "flags") masked_request.set_do_not_care_scapy(scapy.IP, "frag") masked_request.set_do_not_care_scapy(scapy.IP, "ttl") masked_request.set_do_not_care_scapy(scapy.IP, "proto") masked_request.set_do_not_care_scapy(scapy.IP, "chksum") masked_request.set_do_not_care_scapy(scapy.IP, "src") masked_request.set_do_not_care_scapy(scapy.IP, "dst") masked_request.set_do_not_care_scapy(scapy.IP, "options") masked_request.set_do_not_care_scapy(scapy.UDP, "chksum") masked_request.set_do_not_care_scapy(scapy.UDP, "len") masked_request.set_do_not_care_scapy(scapy.BOOTP, "sname") masked_request.set_do_not_care_scapy(scapy.BOOTP, "file") try: testutils.verify_packets_any(self, masked_request, self.server_port_indices) except Exception: self.assertTrue( False, "DHCP Relay packet not matched or Padded extra on server side")
def send_and_check_mirror_packets(self, setup, mirror_session, ptfadapter, duthost, mirror_packet, src_port=None, dest_ports=None, expect_recv=True, valid_across_namespace=True): expected_mirror_packet = self._get_expected_mirror_packet( mirror_session, setup, duthost, mirror_packet) if not src_port: src_port = self._get_random_src_port(setup) if not dest_ports: dest_ports = [ self._get_monitor_port(setup, mirror_session, duthost) ] # In Below logic idea is to send traffic in such a way so that mirror traffic # will need to go across namespaces and within namespace. If source and mirror destination # namespace are different then traffic mirror will go across namespace via (backend asic) # else via same namespace(asic) src_port_namespace = self._get_port_namespace(setup, int(src_port)) dest_ports_namespace = self._get_port_namespace( setup, int(dest_ports[0])) src_port_set = set() # Some of test scenario are not valid across namespaces so test will explicltly pass # valid_across_namespace as False (default is True) if valid_across_namespace == True or src_port_namespace == dest_ports_namespace: src_port_set.add(src_port) # To verify same namespace mirroring we will add destination port also to the Source Port Set if src_port_namespace != dest_ports_namespace: src_port_set.add(dest_ports[0]) # Loop through Source Port Set and send traffic on each source port of the set for src_port in src_port_set: ptfadapter.dataplane.flush() testutils.send(ptfadapter, src_port, mirror_packet) if expect_recv: _, received_packet = testutils.verify_packet_any_port( ptfadapter, expected_mirror_packet, ports=dest_ports) logging.info("Received packet: %s", packet.Ether(received_packet).summary()) inner_packet = self._extract_mirror_payload( received_packet, len(mirror_packet)) logging.info("Received inner packet: %s", inner_packet.summary()) inner_packet = Mask(inner_packet) # For egress mirroring, we expect the DUT to have modified the packet # before forwarding it. Specifically: # # - In L2 the SMAC and DMAC will change. # - In L3 the TTL and checksum will change. # # We know what the TTL and SMAC should be after going through the pipeline, # but DMAC and checksum are trickier. For now, update the TTL and SMAC, and # mask off the DMAC and IP Checksum to verify the packet contents. if self.mirror_type() == "egress": mirror_packet[packet.IP].ttl -= 1 mirror_packet[packet.Ether].src = setup["router_mac"] inner_packet.set_do_not_care_scapy(packet.Ether, "dst") inner_packet.set_do_not_care_scapy(packet.IP, "chksum") logging.info("Expected inner packet: %s", mirror_packet.summary()) pytest_assert(inner_packet.pkt_match(mirror_packet), "Mirror payload does not match received packet") else: testutils.verify_no_packet_any(ptfadapter, expected_mirror_packet, dest_ports)
def runTest(self): pass_cnt = 0 tos = self.dscp << 2 tos_bg = self.dscp_bg << 2 if self.debug: # remove previous debug files files = glob.glob("/tmp/pfc_pause_{}*".format(self.dscp)) for file in files: os.remove(file) current_time = datetime.datetime.now().strftime( "%Y-%m-%d_%H:%M:%S") log_file = open( "/tmp/pfc_pause_{}_{}".format(self.dscp, current_time), "w") """ If DUT needs to learn MAC addresses """ if not self.dut_has_mac: pkt = simple_udp_packet(eth_dst=self.mac_dst, eth_src=self.mac_src, ip_src=self.ip_src, ip_dst=self.ip_dst) send_packet(self, self.port_src, pkt, 5) pkt = simple_udp_packet(eth_dst=self.mac_src, eth_src=self.mac_dst, ip_src=self.ip_dst, ip_dst=self.ip_src) send_packet(self, self.port_dst, pkt, 5) for x in range(self.pkt_count): sport = random.randint(0, 65535) dport = random.randint(0, 65535) pkt = simple_udp_packet(eth_dst=self.mac_dst, eth_src=self.mac_src, ip_src=self.ip_src, ip_dst=self.ip_dst, ip_tos=tos, udp_sport=sport, udp_dport=dport, ip_ttl=64) pkt_bg = simple_udp_packet(eth_dst=self.mac_dst, eth_src=self.mac_src, ip_src=self.ip_src, ip_dst=self.ip_dst, ip_tos=tos_bg, udp_sport=sport, udp_dport=dport, ip_ttl=64) exp_pkt = simple_udp_packet(ip_src=self.ip_src, ip_dst=self.ip_dst, ip_tos=tos_bg, udp_sport=sport, udp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "src") masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "tos") send_packet(self, self.port_src, pkt, 1) send_packet(self, self.port_src, pkt_bg, 1) pkts = capture_matched_packets(self, masked_exp_pkt, self.port_dst) if self.debug: for i, pkt in enumerate(pkts): dump_msg = "Iteration {}:\n Pkt num {}:\n Hex dump: {}\n\n".format( x, i, sc.utils.hexstr(pkt)) log_file.write(dump_msg) time.sleep(self.pkt_intvl) """ If the queue is paused, we should only receive the background packet """ if self.queue_paused: pass_cnt += int( len(pkts) == 1 and scapy.Ether(pkts[0])[scapy.IP].tos == tos_bg) else: pass_cnt += int(len(pkts) == 2) if self.debug: log_file.close() print "Passes: %d / %d" % (pass_cnt, self.pkt_count)
def runTest(self): ecn = 1 dscp = self.queue_index tos = dscp << 2 tos |= ecn matches = re.findall('\[([\d\s]+)\]', self.port_dst) dst_port_list = [] for match in matches: for port in match.split(): dst_port_list.append(int(port)) src_mac = self.dataplane.get_mac(0, 0) if self.port_type == "portchannel": for x in range(0, self.pkt_count): sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff))) ip_src =ipaddress.IPv4Address(unicode(ip_src,'utf-8')) while ip_src == ipaddress.IPv4Address(unicode(self.ip_dst,'utf-8')) or ip_src.is_multicast or ip_src.is_private or ip_src.is_global or ip_src.is_reserved: ip_src = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff))) ip_src =ipaddress.IPv4Address(unicode(ip_src,'utf-8')) ip_src = str(ip_src) pkt = simple_tcp_packet( eth_dst=self.router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=self.ip_dst, ip_tos = tos, tcp_sport=sport, tcp_dport=dport, ip_ttl=64) exp_pkt = simple_tcp_packet( eth_src=self.router_mac, ip_src=ip_src, ip_dst=self.ip_dst, ip_tos = tos, tcp_sport=sport, tcp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") send_packet(self, self.port_src, pkt, 1) else: sport = random.randint(0, 65535) dport = random.randint(0, 65535) ip_src = "1.1.1.1" pkt = simple_tcp_packet( eth_dst=self.router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=self.ip_dst, ip_tos = tos, tcp_sport=sport, tcp_dport=dport, ip_ttl=64) exp_pkt = simple_tcp_packet( eth_src=self.router_mac, ip_src=ip_src, ip_dst=self.ip_dst, ip_tos = tos, tcp_sport=sport, tcp_dport=dport, ip_ttl=63) masked_exp_pkt = Mask(exp_pkt) masked_exp_pkt.set_do_not_care_scapy(scapy.Ether, "dst") send_packet(self, self.port_src, pkt, self.pkt_count) if self.wd_action == 'drop': return verify_no_packet_any(self, masked_exp_pkt, dst_port_list) elif self.wd_action == 'forward': return verify_packet_any_port(self, masked_exp_pkt, dst_port_list)
class FastReloadTest(BaseTest): TIMEOUT = 0.5 def __init__(self): BaseTest.__init__(self) self.fails = {} self.info = {} self.cli_info = {} self.logs_info = {} self.log_fp = open('/tmp/fast-reboot.log', 'w') self.test_params = testutils.test_params_get() self.check_param('verbose', False, required=False) self.check_param('dut_username', '', required=True) self.check_param('dut_hostname', '', required=True) self.check_param('fast_reboot_limit', 30, required=False) self.check_param('graceful_limit', 120, required=False) self.check_param('portchannel_ports_file', '', required=True) self.check_param('vlan_ports_file', '', required=True) self.check_param('ports_file', '', required=True) self.check_param('dut_mac', '', required=True) self.check_param('default_ip_range', '', required=True) self.check_param('vlan_ip_range', '', required=True) self.check_param('lo_prefix', '10.1.0.32/32', required=False) self.check_param('lo_v6_prefix', 'fc00:1::/64', required=False) self.check_param('arista_vms', [], required=True) self.check_param('min_bgp_gr_timeout', 15, required=False) # Default settings self.nr_pc_pkts = 100 self.nr_tests = 3 self.reboot_delay = 10 self.task_timeout = 300 # Wait up to 5 minutes for tasks to complete self.max_nr_vl_pkts = 500 # FIXME: should be 1000. # But ptf is not fast enough + swss is slow for FDB and ARP entries insertions self.timeout_thr = None return def read_json(self, name): with open(self.test_params[name]) as fp: content = json.load(fp) return content def read_port_indices(self): self.port_indices = self.read_json('ports_file') return def read_portchannel_ports(self): content = self.read_json('portchannel_ports_file') pc_ifaces = [] for pc in content.values(): pc_ifaces.extend( [self.port_indices[member] for member in pc['members']]) return pc_ifaces def read_vlan_ports(self): content = self.read_json('vlan_ports_file') if len(content) > 1: raise "Too many vlans" return [ self.port_indices[ifname] for ifname in content.values()[0]['members'] ] def check_param(self, param, default, required=False): if param not in self.test_params: if required: raise Exception("Test parameter '%s' is required" % param) self.test_params[param] = default def random_ip(self, ip): net_addr, mask = ip.split('/') n_hosts = 2**(32 - int(mask)) random_host = random.randint(2, n_hosts - 2) return self.host_ip(ip, random_host) def host_ip(self, net_ip, host_number): src_addr, mask = net_ip.split('/') n_hosts = 2**(32 - int(mask)) if host_number > (n_hosts - 2): raise Exception( "host number %d is greater than number of hosts %d in the network %s" % (host_number, n_hosts - 2, net_ip)) src_addr_n = struct.unpack(">I", socket.inet_aton(src_addr))[0] net_addr_n = src_addr_n & (2**32 - n_hosts) host_addr_n = net_addr_n + host_number host_ip = socket.inet_ntoa(struct.pack(">I", host_addr_n)) return host_ip def random_port(self, ports): return random.choice(ports) def log(self, message, verbose=False): current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if verbose and self.test_params['verbose'] or not verbose: print "%s : %s" % (current_time, message) self.log_fp.write("%s : %s\n" % (current_time, message)) def timeout(self, seconds, message): def timeout_exception(self, message): self.log('Timeout is reached: %s' % message) self.tearDown() os.kill(os.getpid(), signal.SIGINT) if self.timeout_thr is None: self.timeout_thr = threading.Timer(seconds, timeout_exception, args=(self, message)) self.timeout_thr.start() else: raise Exception("Timeout already set") def cancel_timeout(self): if self.timeout_thr is not None: self.timeout_thr.cancel() self.timeout_thr = None def setUp(self): self.read_port_indices() self.portchannel_ports = self.read_portchannel_ports() vlan_ip_range = self.test_params['vlan_ip_range'] self.vlan_ports = self.read_vlan_ports() self.limit = datetime.timedelta( seconds=self.test_params['fast_reboot_limit']) self.dut_ssh = self.test_params[ 'dut_username'] + '@' + self.test_params['dut_hostname'] self.dut_mac = self.test_params['dut_mac'] # self.generate_from_t1() self.generate_from_vlan() self.log("Test params:") self.log("DUT ssh: %s" % self.dut_ssh) self.log("DUT fast-reboot limit: %s" % self.limit) self.log("DUT mac address: %s" % self.dut_mac) self.log("From server src addr: %s" % self.from_server_src_addr) self.log("From server src port: %s" % self.from_server_src_port) self.log("From server dst addr: %s" % self.from_server_dst_addr) self.log("From server dst ports: %s" % self.from_server_dst_ports) self.log("From upper layer number of packets: %d" % self.nr_vl_pkts) self.log("VMs: %s" % str(self.test_params['arista_vms'])) self.dataplane = ptf.dataplane_instance for p in self.dataplane.ports.values(): port = p.get_packet_source() port.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1000000) self.dataplane.flush() if config["log_dir"] != None: filename = os.path.join(config["log_dir"], str(self)) + ".pcap" self.dataplane.start_pcap(filename) self.log("Enabling arp_responder") self.cmd(["supervisorctl", "start", "arp_responder"]) return def tearDown(self): self.log("Disabling arp_responder") self.cmd(["supervisorctl", "stop", "arp_responder"]) if config["log_dir"] != None: self.dataplane.stop_pcap() self.log_fp.close() def get_if(self, iff, cmd): s = socket.socket() ifreq = ioctl(s, cmd, struct.pack("16s16x", iff)) s.close() return ifreq def get_mac(self, iff): SIOCGIFHWADDR = 0x8927 # Get hardware address return ':'.join([ '%02x' % ord(char) for char in self.get_if(iff, SIOCGIFHWADDR)[18:24] ]) def generate_from_t1(self): self.from_t1 = [] vlan_ip_range = self.test_params['vlan_ip_range'] _, mask = vlan_ip_range.split('/') n_hosts = min(2**(32 - int(mask)) - 3, self.max_nr_vl_pkts) dump = defaultdict(dict) counter = 0 for i in xrange(2, n_hosts + 2): from_t1_src_addr = self.random_ip( self.test_params['default_ip_range']) from_t1_src_port = self.random_port(self.portchannel_ports) from_t1_dst_addr = self.host_ip(vlan_ip_range, i) from_t1_dst_port = self.vlan_ports[i % len(self.vlan_ports)] from_t1_if_name = "eth%d" % from_t1_dst_port from_t1_if_addr = "%s/%s" % (from_t1_dst_addr, vlan_ip_range.split('/')[1]) vlan_mac_hex = '72060001%04x' % counter lag_mac_hex = '5c010203%04x' % counter mac_addr = ':'.join(lag_mac_hex[i:i + 2] for i in range(0, len(lag_mac_hex), 2)) packet = simple_tcp_packet(eth_src=mac_addr, eth_dst=self.dut_mac, ip_src=from_t1_src_addr, ip_dst=from_t1_dst_addr, ip_ttl=255, tcp_dport=5000) self.from_t1.append((from_t1_src_port, str(packet))) dump[from_t1_if_name][from_t1_dst_addr] = vlan_mac_hex counter += 1 exp_packet = simple_tcp_packet( ip_src="0.0.0.0", ip_dst="0.0.0.0", tcp_dport=5000, ) self.from_t1_exp_packet = Mask(exp_packet) self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "src") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "src") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "dst") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "chksum") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.TCP, "chksum") self.from_t1_exp_packet.set_do_not_care_scapy(scapy.IP, "ttl") # save data for arp_replay process with open("/tmp/from_t1.json", "w") as fp: json.dump(dump, fp) random_vlan_iface = random.choice(dump.keys()) self.from_server_src_port = int(random_vlan_iface.replace('eth', '')) self.from_server_src_addr = random.choice( dump[random_vlan_iface].keys()) self.from_server_dst_addr = self.random_ip( self.test_params['default_ip_range']) self.from_server_dst_ports = self.portchannel_ports self.nr_vl_pkts = n_hosts return def generate_from_vlan(self): packet = simple_tcp_packet(eth_dst=self.dut_mac, ip_src=self.from_server_src_addr, ip_dst=self.from_server_dst_addr, tcp_dport=5000) exp_packet = simple_tcp_packet( ip_src=self.from_server_src_addr, ip_dst=self.from_server_dst_addr, ip_ttl=63, tcp_dport=5000, ) self.from_vlan_exp_packet = Mask(exp_packet) self.from_vlan_exp_packet.set_do_not_care_scapy(scapy.Ether, "src") self.from_vlan_exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") self.from_vlan_packet = str(packet) return def runTest(self): self.reboot_start = None no_routing_start = None no_routing_stop = None arista_vms = self.test_params['arista_vms'][1:-1].split(",") ssh_targets = [] for vm in arista_vms: if (vm.startswith("'") or vm.startswith('"')) and (vm.endswith("'") or vm.endswith('"')): ssh_targets.append(vm[1:-1]) else: ssh_targets.append(vm) self.log("Converted addresses VMs: %s" % str(ssh_targets)) self.ssh_jobs = [] for addr in ssh_targets: q = Queue.Queue() thr = threading.Thread(target=self.peer_state_check, kwargs={ 'ip': addr, 'queue': q }) thr.setDaemon(True) self.ssh_jobs.append((thr, q)) thr.start() thr = threading.Thread(target=self.background) thr.setDaemon(True) self.log("Check that device is alive and pinging") self.assertTrue(self.check_alive(), 'DUT is not stable') self.log("Schedule to reboot the remote switch in %s sec" % self.reboot_delay) thr.start() self.log("Wait until ASIC stops") self.timeout(self.task_timeout, "DUT hasn't stopped in %d seconds" % self.task_timeout) no_routing_start, upper_replies = self.check_forwarding_stop() self.cancel_timeout() self.log("ASIC was stopped, Waiting until it's up. Stop time: %s" % str(no_routing_start)) self.timeout( self.task_timeout, "DUT hasn't started to work for %d seconds" % self.task_timeout) no_routing_stop, _ = self.check_forwarding_resume() self.cancel_timeout() # wait until all bgp session are established self.log("Wait until bgp routing is up on all devices") for _, q in self.ssh_jobs: q.put('quit') self.timeout( self.task_timeout, "SSH threads haven't finished for %d seconds" % self.task_timeout) while any(thr.is_alive() for thr, _ in self.ssh_jobs): for _, q in self.ssh_jobs: q.put('go') time.sleep(self.TIMEOUT) for thr, _ in self.ssh_jobs: thr.join() self.cancel_timeout() self.log("ASIC works again. Start time: %s" % str(no_routing_stop)) self.log("") no_cp_replies = self.extract_no_cpu_replies(upper_replies) self.fails['dut'] = set() if no_routing_stop - no_routing_start > self.limit: self.fails['dut'].add("Downtime must be less then %s seconds. It was %s" \ % (self.test_params['fast_reboot_limit'], str(no_routing_stop - no_routing_start))) if no_routing_stop - self.reboot_start > datetime.timedelta( seconds=self.test_params['graceful_limit']): self.fails['dut'].add( "Fast-reboot cycle must be less than graceful limit %s seconds" % self.test_params['graceful_limit']) if no_cp_replies < 0.95 * self.nr_vl_pkts: self.fails['dut'].add( "Dataplane didn't route to all servers, when control-plane was down: %d vs %d" % (no_cp_replies, self.nr_vl_pkts)) # Generating report self.log("=" * 50) self.log("Report:") self.log("=" * 50) self.log("LACP/BGP were down for (extracted from cli):") self.log("-" * 50) for ip in sorted(self.cli_info.keys()): self.log(" %s - lacp: %7.3f (%d) bgp v4: %7.3f (%d) bgp v6: %7.3f (%d)" \ % (ip, self.cli_info[ip]['lacp'][1], self.cli_info[ip]['lacp'][0], \ self.cli_info[ip]['bgp_v4'][1], self.cli_info[ip]['bgp_v4'][0],\ self.cli_info[ip]['bgp_v6'][1], self.cli_info[ip]['bgp_v6'][0])) self.log("-" * 50) self.log("Extracted from VM logs:") self.log("-" * 50) for ip in sorted(self.logs_info.keys()): self.log("Extracted log info from %s" % ip) for msg in sorted(self.logs_info[ip].keys()): if msg != 'error': self.log(" %s : %d" % (msg, self.logs_info[ip][msg])) else: self.log(" %s" % self.logs_info[ip][msg]) self.log("-" * 50) self.log("Summary:") self.log("-" * 50) self.log("Downtime was %s" % str(no_routing_stop - no_routing_start)) self.log("Reboot time was %s" % str(no_routing_stop - self.reboot_start)) self.log( "How many packets were received back when control plane was down: %d Expected: %d" % (no_cp_replies, self.nr_vl_pkts)) has_info = any(len(info) > 0 for info in self.info.values()) if has_info: self.log("-" * 50) self.log("Additional info:") self.log("-" * 50) for name, info in self.info.items(): for entry in info: self.log("INFO:%s:%s" % (name, entry)) self.log("-" * 50) is_good = all(len(fails) == 0 for fails in self.fails.values()) errors = "" if not is_good: self.log("-" * 50) self.log("Fails:") self.log("-" * 50) errors = "\n\nSomething went wrong. Please check output below:\n\n" for name, fails in self.fails.items(): for fail in fails: self.log("FAILED:%s:%s" % (name, fail)) errors += "FAILED:%s:%s\n" % (name, fail) self.log("=" * 50) self.assertTrue(is_good, errors) def extract_no_cpu_replies(self, arr): """ This function tries to extract number of replies from dataplane, when control plane is non working """ # remove all tail zero values non_zero = filter(lambda x: x > 0, arr) # check that last value is different from previos if len(non_zero) > 1 and non_zero[-1] < non_zero[-2]: return non_zero[-2] else: return non_zero[-1] def background(self): time.sleep(self.reboot_delay) self.log("Rebooting remote side") self.reboot_start = datetime.datetime.now() stdout, stderr, return_code = self.cmd([ "ssh", "-oStrictHostKeyChecking=no", self.dut_ssh, "sudo fast-reboot" ]) if stdout != []: self.log("stdout from fast-reboot: %s" % str(stdout)) if stderr != []: self.log("stderr from fast-reboot: %s" % str(stderr)) self.log("return code from fast-reboot: %s" % str(return_code)) return def cmd(self, cmds): process = subprocess.Popen(cmds, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() return_code = process.returncode return stdout, stderr, return_code def peer_state_check(self, ip, queue): ssh = Arista(ip, queue, self.test_params) self.fails[ip], self.info[ip], self.cli_info[ip], self.logs_info[ ip] = ssh.run() def check_forwarding_stop(self): return self.iteration(True) def check_forwarding_resume(self): return self.iteration(False) def iteration(self, is_stop): recorded_time = None counter = self.nr_tests nr_from_upper_array = [] while True: success, nr_from_upper = self.ping_iteration() nr_from_upper_array.append(nr_from_upper) for _, q in self.ssh_jobs: q.put('go') if success and is_stop or not success and not is_stop: self.log("Base state", True) recorded_time = None else: self.log("Changed state", True) if recorded_time is None: recorded_time = datetime.datetime.now() if counter == 0: break else: counter -= 1 return recorded_time, nr_from_upper_array def ping_iteration(self): replies_from_servers = self.pingFromServers() if replies_from_servers > 0: replies_from_upper = self.pingFromUpperTier() else: replies_from_upper = 0 return replies_from_servers > 0 and replies_from_upper > 0, replies_from_upper def check_alive(self): # This function checks that DUT routes the packets in the both directions. # # Sometimes first attempt failes because ARP responses to DUT are not so fast. # But after this the function expects to see steady "replies". # If the function sees that there is an issue with the dataplane after we saw # successful replies it considers that the DUT is not healthy # # Sometimes I see that DUT returns more replies then requests. # I think this is because of not populated FDB table # The function waits while it's done was_alive = False for counter in range(self.nr_tests * 2): success, _ = self.ping_alive() if success: was_alive = True else: if was_alive: return False # Stopped working after it working for sometime? # wait, until FDB entries are populated for _ in range(self.nr_tests * 10): # wait for some time if not self.ping_alive( )[1]: # until we see that there're no extra replies return True return False # we still see extra replies def ping_alive(self): nr_from_s = self.pingFromServers() nr_from_l = self.pingFromUpperTier() is_alive = nr_from_s > self.nr_pc_pkts * 0.7 and nr_from_l > self.nr_vl_pkts * 0.7 is_asic_weird = nr_from_s > self.nr_pc_pkts or nr_from_l > self.nr_vl_pkts # we receive more, then sent. not populated FDB table return is_alive, is_asic_weird def pingFromServers(self): for i in xrange(self.nr_pc_pkts): testutils.send_packet(self, self.from_server_src_port, self.from_vlan_packet) total_rcv_pkt_cnt = testutils.count_matched_packets_all_ports( self, self.from_vlan_exp_packet, self.from_server_dst_ports, timeout=self.TIMEOUT) self.log( "Send %5d Received %5d servers->t1" % (self.nr_pc_pkts, total_rcv_pkt_cnt), True) return total_rcv_pkt_cnt def pingFromUpperTier(self): for entry in self.from_t1: testutils.send_packet(self, *entry) total_rcv_pkt_cnt = testutils.count_matched_packets_all_ports( self, self.from_t1_exp_packet, self.vlan_ports, timeout=self.TIMEOUT) self.log( "Send %5d Received %5d t1->servers" % (self.nr_vl_pkts, total_rcv_pkt_cnt), True) return total_rcv_pkt_cnt
def check_icmp_mtu(self, ipv4=True): ''' @summary: Check ICMP/Ping or ICMPv6/Ping6 to DUT works for MAX MTU. ''' src_mac = self.dataplane.get_mac(0, self.src_ptf_port_list[0]) pktlen = self.pktlen if ipv4: ip_src = self.src_host_ip ip_dst = self.src_router_ip pkt = simple_icmp_packet(pktlen=pktlen, eth_dst=self.router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, ip_ttl=64) exp_pkt = simple_icmp_packet(pktlen=pktlen, eth_src=self.router_mac, ip_src=ip_dst, ip_dst=ip_src, icmp_type=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.IP, "id") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.ICMP, "chksum") else: ip_src = self.src_host_ipv6 ip_dst = self.src_router_ipv6 pkt = simple_icmpv6_packet(pktlen=pktlen, eth_dst=self.router_mac, eth_src=src_mac, ipv6_src=ip_src, ipv6_dst=ip_dst, icmp_type=128, ipv6_hlim=64) exp_pkt = simple_icmpv6_packet(pktlen=pktlen, eth_src=self.router_mac, ipv6_src=ip_dst, ipv6_dst=ip_src, icmp_type=129) 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.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "tc") masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "fl") masked_exp_pkt.set_do_not_care_scapy(scapy.ICMPv6Unknown, "chksum") src_port = self.src_ptf_port_list[0] send_packet(self, src_port, pkt) logging.info("Sending packet from port " + str(src_port) + " to " + ip_dst) dst_port_list = self.src_ptf_port_list (matched_index, received) = verify_packet_any_port(self, masked_exp_pkt, dst_port_list) assert received matched_port = dst_port_list[matched_index] logging.info("Received packet at " + str(matched_port)) return
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_icmp_mtu(self): ''' @summary: Check ICMP/Ping to DUT works for MAX MTU. ''' ip_src = "10.0.0.1" ip_dst = "10.0.0.0" src_mac = self.dataplane.get_mac(0, 0) pktlen = (self.DEFAULT_PACKET_LEN - self.ICMP_HDR_LEN) pkt = simple_icmp_packet(pktlen=pktlen, eth_dst=self.router_mac, eth_src=src_mac, ip_src=ip_src, ip_dst=ip_dst, ip_ttl=64) exp_pkt = simple_icmp_packet(pktlen=pktlen, eth_src=self.router_mac, ip_src=ip_dst, ip_dst=ip_src, icmp_type=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.IP, "id") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "chksum") masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") masked_exp_pkt.set_do_not_care_scapy(scapy.ICMP, "chksum") src_port = 0 send_packet(self, src_port, pkt) logging.info("Sending packet from port " + str(src_port) + " to " + ip_dst) dst_port_list = [0, 1] (matched_index, received) = verify_packet_any_port(self, masked_exp_pkt, dst_port_list) assert received matched_port = dst_port_list[matched_index] logging.info("Received packet at " + str(matched_port)) return
def build_syn_pkt(local_addr, peer_addr): pkt = testutils.simple_tcp_packet(pktlen=54, ip_src=local_addr, ip_dst=peer_addr, tcp_dport=BGP_PORT, tcp_flags="S") exp_packet = Mask(pkt) exp_packet.set_do_not_care_scapy(scapy.Ether, "dst") exp_packet.set_do_not_care_scapy(scapy.Ether, "src") exp_packet.set_do_not_care_scapy(scapy.IP, "version") exp_packet.set_do_not_care_scapy(scapy.IP, "ihl") exp_packet.set_do_not_care_scapy(scapy.IP, "tos") exp_packet.set_do_not_care_scapy(scapy.IP, "len") exp_packet.set_do_not_care_scapy(scapy.IP, "flags") exp_packet.set_do_not_care_scapy(scapy.IP, "id") exp_packet.set_do_not_care_scapy(scapy.IP, "frag") exp_packet.set_do_not_care_scapy(scapy.IP, "ttl") exp_packet.set_do_not_care_scapy(scapy.IP, "chksum") exp_packet.set_do_not_care_scapy(scapy.IP, "options") exp_packet.set_do_not_care_scapy(scapy.TCP, "sport") exp_packet.set_do_not_care_scapy(scapy.TCP, "seq") exp_packet.set_do_not_care_scapy(scapy.TCP, "ack") exp_packet.set_do_not_care_scapy(scapy.TCP, "reserved") exp_packet.set_do_not_care_scapy(scapy.TCP, "dataofs") exp_packet.set_do_not_care_scapy(scapy.TCP, "window") exp_packet.set_do_not_care_scapy(scapy.TCP, "chksum") exp_packet.set_do_not_care_scapy(scapy.TCP, "urgptr") exp_packet.set_ignore_extra_bytes() return exp_packet
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 FromServer(self, test): rv = True try: pkt_len = self.DEFAULT_PKT_LEN if test['vlan'] != 0: tagged = True pkt_len += 4 else: tagged = False vni = int(test['vni']) if 'dst_vni' in test: vni = int(test['dst_vni']) pkt = simple_tcp_packet(pktlen=pkt_len, eth_dst=self.dut_mac, eth_src=self.ptf_mac_addrs['eth%d' % test['port']], dl_vlan_enable=tagged, vlan_vid=test['vlan'], ip_dst=test['dst'], ip_src=test['src'], ip_id=105, ip_ttl=64) exp_pkt = simple_tcp_packet(eth_dst=test['mac'], eth_src=self.dut_mac, ip_dst=test['dst'], ip_src=test['src'], ip_id=105, ip_ttl=63) udp_sport = 1234 # Use entropy_hash(pkt) udp_dport = self.vxlan_port if isinstance(ip_address(test['host']), 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=test['host'], ip_ttl=128, udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt) encap_pkt[IP].flags = 0x2 elif isinstance(ip_address(test['host']), ipaddress.IPv6Address): encap_pkt = simple_vxlanv6_packet(eth_src=self.dut_mac, eth_dst=self.random_mac, ipv6_src=self.loopback_ipv6, ipv6_dst=test['host'], udp_sport=udp_sport, udp_dport=udp_dport, with_udp_chksum=False, vxlan_vni=vni, inner_frame=exp_pkt) else: raise Exception("Found invalid IP address in test") send_packet(self, test['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(test['host']), ipaddress.IPv4Address): masked_exp_pkt.set_do_not_care_scapy(scapy.IP, "ttl") else: masked_exp_pkt.set_do_not_care_scapy(scapy.IPv6, "hlim") masked_exp_pkt.set_do_not_care_scapy(scapy.UDP, "sport") log_str = "Sending packet from port " + str( 'eth%d' % test['port']) + " to " + test['dst'] logging.info(log_str) if not self.routes_removed: verify_packet_any_port(self, masked_exp_pkt, self.net_ports) else: verify_no_packet_any(self, masked_exp_pkt, self.net_ports) finally: print
def mask_off_dont_care_ra_packet_fields(self, rapkt): masked_rapkt = Mask(rapkt) masked_rapkt.set_ignore_extra_bytes() masked_rapkt.set_do_not_care_scapy(IPv6, "tc") masked_rapkt.set_do_not_care_scapy(IPv6, "fl") masked_rapkt.set_do_not_care_scapy(IPv6, "plen") masked_rapkt.set_do_not_care_scapy(IPv6, "nh") masked_rapkt.set_do_not_care_scapy(RA, "cksum") masked_rapkt.set_do_not_care_scapy(RA, "chlim") masked_rapkt.set_do_not_care_scapy(RA, "H") masked_rapkt.set_do_not_care_scapy(RA, "prf") masked_rapkt.set_do_not_care_scapy(RA, "P") masked_rapkt.set_do_not_care_scapy(RA, "res") masked_rapkt.set_do_not_care_scapy(RA, "routerlifetime") masked_rapkt.set_do_not_care_scapy(RA, "reachabletime") masked_rapkt.set_do_not_care_scapy(RA, "retranstimer") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "prefixlen") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "L") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "A") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "R") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "res1") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "validlifetime") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "preferredlifetime") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "res2") masked_rapkt.set_do_not_care_scapy(PrefixInfo, "prefix") return masked_rapkt
def verify_ack_received(self): dhcp_ack = self.create_dhcp_ack_relayed_packet() masked_ack = Mask(dhcp_ack) masked_ack.set_do_not_care_scapy(scapy.IP, "version") masked_ack.set_do_not_care_scapy(scapy.IP, "ihl") masked_ack.set_do_not_care_scapy(scapy.IP, "tos") masked_ack.set_do_not_care_scapy(scapy.IP, "len") masked_ack.set_do_not_care_scapy(scapy.IP, "id") masked_ack.set_do_not_care_scapy(scapy.IP, "flags") masked_ack.set_do_not_care_scapy(scapy.IP, "frag") masked_ack.set_do_not_care_scapy(scapy.IP, "ttl") masked_ack.set_do_not_care_scapy(scapy.IP, "proto") masked_ack.set_do_not_care_scapy(scapy.IP, "chksum") masked_ack.set_do_not_care_scapy(scapy.IP, "options") masked_ack.set_do_not_care_scapy(scapy.UDP, "len") masked_ack.set_do_not_care_scapy(scapy.UDP, "chksum") masked_ack.set_do_not_care_scapy(scapy.BOOTP, "sname") masked_ack.set_do_not_care_scapy(scapy.BOOTP, "file") masked_ack.set_do_not_care_scapy(scapy.DHCP, "lease_time") # NOTE: verify_packet() will fail for us via an assert, so no need to check a return value here testutils.verify_packet(self, masked_ack, self.client_port_index)
def runTest(self): print switch_init(self.client) port1 = port_list[0] port2 = port_list[1] port3 = port_list[2] mac3='00:00:00:00:00:33' mac2='00:00:00:00:00:22' monitor_port=port1 source_port=port2 mirror_type=SAI_MIRROR_TYPE_ENHANCED_REMOTE vlan=0x2 vlan_tpid=0x8100 vlan_pri=0x6 src_mac='00:00:00:00:11:22' dst_mac='00:00:00:00:11:33' encap_type=SAI_MIRROR_L3_GRE_TUNNEL ip_version=0x4 tos=0x3c ttl=0xf0 gre_type=0x88be src_ip='17.18.19.0' dst_ip='33.19.20.0' addr_family=0 sai_thrift_create_fdb(self.client, 3, mac3, port3, 1) sai_thrift_create_fdb(self.client, 3, mac2, port2, 1) # Put ports under test in VLAN 3 self.client.sai_thrift_create_vlan(3) vlan_member1 = sai_thrift_create_vlan_member(self.client, 3, port1, SAI_VLAN_PORT_TAGGED) vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_TAGGED) vlan_member2 = sai_thrift_create_vlan_member(self.client, 3, port2, SAI_VLAN_PORT_TAGGED) vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_TAGGED) vlan_member3 = sai_thrift_create_vlan_member(self.client, 3, port3, SAI_VLAN_PORT_TAGGED) vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_TAGGED) # Remove ports from default VLAN self.client.sai_thrift_remove_vlan_member(vlan_member1a) self.client.sai_thrift_remove_vlan_member(vlan_member2a) self.client.sai_thrift_remove_vlan_member(vlan_member3a) # Set PVID attr_value = sai_thrift_attribute_value_t(u16=3) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) self.client.sai_thrift_set_port_attribute(port1, attr) self.client.sai_thrift_set_port_attribute(port2, attr) self.client.sai_thrift_set_port_attribute(port3, attr) erspanid=sai_thrift_create_mirror_session(self.client,mirror_type=mirror_type,port=monitor_port,vlan=vlan,vlan_priority=vlan_pri,vlan_tpid=vlan_tpid,src_mac=src_mac,dst_mac=dst_mac,addr_family=addr_family,src_ip=src_ip,dst_ip=dst_ip,encap_type=encap_type,protocol=ip_version,ttl=ttl,tos=tos,gre_type=gre_type) #attrb_value = sai_thrift_attribute_value_t(oid=erspanid) attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=1,object_id_list=[erspanid])) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) pkt = simple_tcp_packet(eth_dst='00:00:00:00:00:33', eth_src='00:22:22:22:22:22', ip_dst='10.0.0.1', dl_vlan_enable=True, vlan_vid=3, ip_id=101, ip_ttl=64) pkt2 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', eth_src='00:33:33:33:33:33', dl_vlan_enable=True, vlan_vid=3, ip_dst='10.0.0.1', ip_id=101, ip_ttl=64) pkt3 = simple_tcp_packet(eth_dst='00:00:00:00:00:22', eth_src='00:33:33:33:33:33', dl_vlan_enable=True, vlan_vid=3, ip_dst='10.0.0.1', ip_id=101, ip_ttl=64) exp_pkt1= simple_gre_packet(pktlen=142, eth_dst='00:00:00:00:11:33', eth_src='00:00:00:00:11:22', dl_vlan_enable=True, vlan_vid=2, ip_id=0, ip_ttl=240, ip_tos=0x3c, ip_ihl=5, ip_src='17.18.19.0', ip_dst='33.19.20.0', inner_frame=pkt ) exp_pkt2= simple_gre_packet(pktlen=142, eth_dst='00:00:00:00:11:33', eth_src='00:00:00:00:11:22', dl_vlan_enable=True, vlan_vid=2, ip_id=0, ip_ttl=240, ip_tos=0x3c, ip_ihl=5, ip_src='17.18.19.0', ip_dst='33.19.20.0', inner_frame=pkt3 ) m1=Mask(exp_pkt1) m2=Mask(exp_pkt2) m1.set_do_not_care_scapy(ptf.packet.IP,'tos') m1.set_do_not_care_scapy(ptf.packet.IP,'frag') m1.set_do_not_care_scapy(ptf.packet.IP,'flags') m1.set_do_not_care_scapy(ptf.packet.IP,'chksum') m1.set_do_not_care_scapy(ptf.packet.GRE,'proto') m2.set_do_not_care_scapy(ptf.packet.IP,'tos') m2.set_do_not_care_scapy(ptf.packet.IP,'frag') m2.set_do_not_care_scapy(ptf.packet.IP,'flags') m2.set_do_not_care_scapy(ptf.packet.IP,'chksum') m2.set_do_not_care_scapy(ptf.packet.GRE,'proto') n=Mask(pkt2) n.set_do_not_care_scapy(ptf.packet.IP,'len') n.set_do_not_care_scapy(ptf.packet.IP,'chksum') try: # in tuple: 0 is device number, 2 is port number # this tuple uniquely identifies a port # for ingress mirroring print "Checking INGRESS ERSPAN Mirroring" print "Sending packet port 2 -> port 3 (00:22:22:22:22:22 -> 00:00:00:00:00:33)" send_packet(self, 1, pkt) verify_each_packet_on_each_port(self, [m1,pkt], ports=[0,2])#FIXME need to properly implement # for egress mirroring print "Checking EGRESS ERSPAN Mirroring" print "Sending packet port 3 -> port 2 (00:33:33:33:33:33 -> 00:00:00:00:00:22)" send_packet(self, 2, pkt2) verify_each_packet_on_each_port(self, [pkt2,m2], ports=[1,0])#FIXME need to properly implement finally: sai_thrift_delete_fdb(self.client, 3, mac2, port2) sai_thrift_delete_fdb(self.client, 3, mac3, port3) # Remove ports from mirror destination attrb_value = sai_thrift_attribute_value_t(objlist=sai_thrift_object_list_t(count=0,object_id_list=[erspanid])) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_INGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_EGRESS_MIRROR_SESSION, value=attrb_value) self.client.sai_thrift_set_port_attribute(port2, attr) # Now you can remove destination self.client.sai_thrift_remove_mirror_session(erspanid) # Remove ports from VLAN 3 self.client.sai_thrift_remove_vlan_member(vlan_member1) self.client.sai_thrift_remove_vlan_member(vlan_member2) self.client.sai_thrift_remove_vlan_member(vlan_member3) self.client.sai_thrift_delete_vlan(3) # Add ports back to default VLAN vlan_member1a = sai_thrift_create_vlan_member(self.client, 1, port1, SAI_VLAN_PORT_UNTAGGED) vlan_member2a = sai_thrift_create_vlan_member(self.client, 1, port2, SAI_VLAN_PORT_UNTAGGED) vlan_member3a = sai_thrift_create_vlan_member(self.client, 1, port3, SAI_VLAN_PORT_UNTAGGED) attr_value = sai_thrift_attribute_value_t(u16=1) attr = sai_thrift_attribute_t(id=SAI_PORT_ATTR_PORT_VLAN_ID, value=attr_value) self.client.sai_thrift_set_port_attribute(port1, attr) self.client.sai_thrift_set_port_attribute(port2, attr) self.client.sai_thrift_set_port_attribute(port3, attr)