def verify_tunneled_4o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = rx[GRE] rx_ip = rx_gre[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) # IP processing post pop has decremented the TTL self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def verify_capture(self, capture, ip_class, dropped_packet_indexes=[]): """Verify captured packet stream. :param list capture: Captured packet stream. """ info = None seen = set() for packet in capture: try: self.logger.debug(ppp("Got packet:", packet)) ip = packet[ip_class] udp = packet[UDP] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index self.assertTrue( packet_index not in dropped_packet_indexes, ppp("Packet received, but should be dropped:", packet)) if packet_index in seen: raise Exception(ppp("Duplicate packet received", packet)) seen.add(packet_index) self.assertEqual(payload_info.dst, self.dst_if.sw_if_index) info = self._packet_infos[packet_index] self.assertTrue(info is not None) self.assertEqual(packet_index, info.index) saved_packet = info.data self.assertEqual(ip.src, saved_packet[ip_class].src) self.assertEqual(ip.dst, saved_packet[ip_class].dst) self.assertEqual(udp.payload, saved_packet[UDP].payload) except Exception: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for index in self._packet_infos: self.assertTrue(index in seen or index in dropped_packet_indexes, "Packet with packet_index %d not received" % index)
def verify_tunneled_6o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload)) rx_ip = rx_gre[IPv6] tx_ip = tx[IPv6] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def verify_tunneled_l2o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = rx[GRE] rx_l2 = rx_gre[Ether] rx_ip = rx_l2[IP] tx_gre = tx[GRE] tx_l2 = tx_gre[Ether] tx_ip = tx_l2[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) # bridged, not L3 forwarded, so no TTL decrement self.assertEqual(rx_ip.ttl, tx_ip.ttl) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def verify_capture(self, capture): """Verify captured packet stream. :param list capture: Captured packet stream. """ info = None seen = set() for packet in capture: try: self.logger.debug(ppp("Got packet:", packet)) ip = packet[IP] icmp = packet[ICMP] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index if packet_index in seen: raise Exception(ppp("Duplicate packet received", packet)) seen.add(packet_index) self.assertEqual(payload_info.dst, self.src_dst_if.sw_if_index) info = self._packet_infos[packet_index] self.assertIsNotNone(info) self.assertEqual(packet_index, info.index) saved_packet = info.data self.assertEqual(ip.src, saved_packet[IP].dst) self.assertEqual(ip.dst, saved_packet[IP].src) self.assertEqual(icmp.type, 0) # echo reply self.assertEqual(icmp.id, saved_packet[ICMP].id) self.assertEqual(icmp.payload, saved_packet[ICMP].payload) except Exception: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for index in self._packet_infos: self.assertIn(index, seen, "Packet with packet_index %d not received" % index)
def verify_tun_44(self, p, count=1): self.vapi.cli("clear errors") try: config_tun_params(p, self.encryption_type, self.tun_if) send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IP].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: try: decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug( ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) if (hasattr(p, "spd_policy_in_any")): pkts = p.spd_policy_in_any.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SPD any policy: expected %d != %d" % (count, pkts)) if (hasattr(p, "tun_sa_in")): pkts = p.tun_sa_in.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tun_sa_out.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tun4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tun4_decrypt_node_name, count)
def test_tun_basic66(self, count=1): """ ipsec 6o6 tunnel basic test """ self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET6] vpp_tun_sa, scapy_tun_sa = self.configure_sa_tun(p) send_pkts = self.gen_encrypt_pkts6(scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip6, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: try: decrypt_pkt = vpp_tun_sa.decrypt(recv_pkt[IPv6]) if not decrypt_pkt.haslayer(IPv6): decrypt_pkt = IPv6(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) pkts = p.tun_sa_in.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tun_sa_out.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tun6_encrypt_node_name, count) self.assert_packet_counter_equal(self.tun6_decrypt_node_name, count)
def test_ipsec_spd_outbound_add(self): # In this test case, packets in IPv4 FWD path are configured # to go through IPSec outbound SPD policy lookup. # 2 SPD rules (1 HIGH and 1 LOW) are added. # High priority rule action is set to BYPASS. # Low priority rule action is set to DISCARD. # Traffic sent on pg0 interface should match high priority # rule and should be sent out on pg1 interface. self.create_interfaces(2) pkt_count = 5 self.spd_create_and_intf_add(1, [self.pg1]) policy_0 = self.spd_add_rem_policy( # outbound, priority 10 1, self.pg0, self.pg1, socket.IPPROTO_UDP, is_out=1, priority=10, policy_type="bypass") policy_1 = self.spd_add_rem_policy( # outbound, priority 5 1, self.pg0, self.pg1, socket.IPPROTO_UDP, is_out=1, priority=5, policy_type="discard") # check flow cache is empty before sending traffic self.verify_num_outbound_flow_cache_entries(0) # create the packet stream packets = self.create_stream(self.pg0, self.pg1, pkt_count) # add the stream to the source interface + enable capture self.pg0.add_stream(packets) self.pg0.enable_capture() self.pg1.enable_capture() # start the packet generator self.pg_start() # get capture capture = self.pg1.get_capture() for packet in capture: try: self.logger.debug(ppp("SPD - Got packet:", packet)) except Exception: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise self.logger.debug("SPD: Num packets: %s", len(capture.res)) # assert nothing captured on pg0 self.pg0.assert_nothing_captured() # verify captured packets self.verify_capture(self.pg0, self.pg1, capture) # verify all policies matched the expected number of times self.verify_policy_match(pkt_count, policy_0) self.verify_policy_match(0, policy_1) # check policy in SPD has been cached after traffic # matched BYPASS rule in SPD self.verify_num_outbound_flow_cache_entries(1)
def resolve_arp(self, pg_interface=None): """Resolve ARP using provided packet-generator interface :param pg_interface: interface used to resolve, if None then this interface is used """ if pg_interface is None: pg_interface = self self.test.logger.info("Sending ARP request for %s on port %s" % (self.local_ip4, pg_interface.name)) arp_req = self.create_arp_req() pg_interface.add_stream(arp_req) pg_interface.enable_capture() self.test.pg_start() self.test.logger.info(self.test.vapi.cli("show trace")) try: captured_packet = pg_interface.wait_for_packet(1) except: self.test.logger.info("No ARP received on port %s" % pg_interface.name) return arp_reply = captured_packet.copy() # keep original for exception try: if arp_reply[ARP].op == ARP.is_at: self.test.logger.info("VPP %s MAC address is %s " % (self.name, arp_reply[ARP].hwsrc)) self._local_mac = arp_reply[ARP].hwsrc else: self.test.logger.info("No ARP received on port %s" % pg_interface.name) except: self.test.logger.error( ppp("Unexpected response to ARP request:", captured_packet)) raise
def verify_capture(self, src_loc, dst_loc, capture): """ Verify captured packet :param src_loc: source locator address :param dst_loc: destination locator address :param capture: list of captured packets """ self.test.assertEqual(len(capture), 1, "Unexpected number of " "packets! Expected 1 but {} received" .format(len(capture))) packet = capture[0] try: ip_hdr = packet[IP] # assert the values match self.test.assertEqual(ip_hdr.src, src_loc, "IP source address") self.test.assertEqual(ip_hdr.dst, dst_loc, "IP destination address") gpe_hdr = packet[LISP_GPE_Header] self.test.assertEqual(gpe_hdr.next_proto, 1, "next_proto is not ipv4!") ih = gpe_hdr[IP] self.test.assertEqual(ih.src, self.test.pg0.remote_ip4, "unexpected source EID!") self.test.assertEqual(ih.dst, self.test.deid_ip4, "unexpected dest EID!") except: self.test.logger.error(ppp("Unexpected or invalid packet:", packet)) raise
def verify_capture_plain(self, capture): for packet in capture: try: self.assert_packet_checksums_valid(packet) self.assert_equal(packet[IP].src, self.tun_if.remote_ip4, "decrypted packet source address") self.assert_equal(packet[IP].dst, self.pg1.remote_ip4, "decrypted packet destination address") if packet.haslayer(TCP): self.assertFalse( packet.haslayer(UDP), "unexpected UDP header in decrypted packet") self.assert_equal(packet[TCP].dport, self.tcp_port_in, "decrypted packet TCP destination port") elif packet.haslayer(UDP): if packet[UDP].payload: self.assertFalse( packet[UDP][1].haslayer(UDP), "unexpected UDP header in decrypted packet") self.assert_equal(packet[UDP].dport, self.udp_port_in, "decrypted packet UDP destination port") else: self.assertFalse( packet.haslayer(UDP), "unexpected UDP header in decrypted packet") self.assert_equal(packet[ICMP].id, self.icmp_id_in, "decrypted packet ICMP ID") except Exception: self.logger.error( ppp("Unexpected or invalid plain packet:", packet)) raise
def verify_capture_in(self, capture, in_if): """ Verify captured packets on inside network :param capture: Captured packets :param in_if: Inside interface """ fired = False for packet in capture: try: self.assert_packet_checksums_valid(packet) self.assertEqual(packet[IP].dst, in_if.remote_ip4) if packet.haslayer(TCP): self.assertEqual(packet[TCP].dport, self.tcp_port_in) elif packet.haslayer(UDP): self.assertEqual(packet[UDP].dport, self.udp_port_in) else: self.assertEqual(packet[ICMP].id, self.icmp_id_in) except: fired = True self.logger.error( ppp("Unexpected or invalid packet " "(inside network):", packet)) if fired: raise
def verify_capture_encrypted(self, capture, sa): for packet in capture: try: copy = packet.__class__(scapy.compat.raw(packet)) del copy[UDP].len copy = packet.__class__(scapy.compat.raw(copy)) self.assert_equal(packet[UDP].len, copy[UDP].len, "UDP header length") self.assert_packet_checksums_valid(packet) self.assertIn(ESP, packet[IP]) decrypt_pkt = sa.decrypt(packet[IP]) self.assert_packet_checksums_valid(decrypt_pkt) self.assert_equal( decrypt_pkt[IP].src, self.pg1.remote_ip4, "encrypted packet source address", ) self.assert_equal( decrypt_pkt[IP].dst, self.tun_if.remote_ip4, "encrypted packet destination address", ) except Exception: self.logger.error( ppp("Unexpected or invalid encrypted packet:", packet)) raise
def test_tra_basic(self, count=1): """ ipsec v4 transport basic test """ self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET] send_pkts = self.gen_encrypt_pkts(p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4, count=count) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: try: decrypted = p.vpp_tra_sa.decrypt(rx[IP]) self.assert_packet_checksums_valid(decrypted) except: self.logger.debug(ppp("Unexpected packet:", rx)) raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) pkts = p.tra_sa_in.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tra_sa_out.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tra4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra4_decrypt_node_name, count)
def test_tra_basic6(self, count=1): """ ipsec v6 transport basic test """ self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET6] send_pkts = self.gen_encrypt_pkts6(p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip6, dst=self.tra_if.local_ip6, count=count) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: try: decrypted = p.vpp_tra_sa.decrypt(rx[IPv6]) self.assert_packet_checksums_valid(decrypted) except: self.logger.debug(ppp("Unexpected packet:", rx)) raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) self.assert_packet_counter_equal(self.tra6_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra6_decrypt_node_name, count)
def verify_tra_basic6(self, count=1): self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET6] send_pkts = self.gen_encrypt_pkts6(p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip6, dst=self.tra_if.local_ip6, count=count) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: self.assertEqual(len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen) try: decrypted = p.vpp_tra_sa.decrypt(rx[IPv6]) self.assert_packet_checksums_valid(decrypted) except: self.logger.debug(ppp("Unexpected packet:", rx)) raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) pkts = p.tra_sa_in.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tra_sa_out.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tra6_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra6_decrypt_node_name, count)
def verify_tra_basic6(self, count=1): self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET6] send_pkts = self.gen_encrypt_pkts6(p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip6, dst=self.tra_if.local_ip6, count=count) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: self.assertEqual( len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen) try: decrypted = p.vpp_tra_sa.decrypt(rx[IPv6]) self.assert_packet_checksums_valid(decrypted) except: self.logger.debug(ppp("Unexpected packet:", rx)) raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec all")) pkts = p.tra_sa_in.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tra_sa_out.get_stats()['packets'] self.assertEqual( pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tra6_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra6_decrypt_node_name, count)
def test_check_no_translate(self): """NAT66 translate only when egress interface is outside interface""" flags = self.config_flags.NAT_IS_INSIDE self.vapi.nat66_add_del_interface(is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index) self.vapi.nat66_add_del_interface(is_add=1, flags=flags, sw_if_index=self.pg1.sw_if_index) self.vapi.nat66_add_del_static_mapping( local_ip_address=self.pg0.remote_ip6, external_ip_address=self.nat_addr, is_add=1, ) # in2out p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / UDP()) self.pg0.add_stream([p]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() capture = self.pg1.get_capture(1) packet = capture[0] try: self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6) self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise
def test_ping_out_interface_from_outside(self): """ Ping SNAT out interface from outside """ self.snat_add_address(self.snat_addr) self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index) self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index, is_inside=0) p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) / ICMP(id=self.icmp_id_out, type='echo-request')) pkts = [p] self.pg1.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() capture = self.pg1.get_capture(len(pkts)) self.assertEqual(1, len(capture)) packet = capture[0] try: self.assertEqual(packet[IP].src, self.pg1.local_ip4) self.assertEqual(packet[IP].dst, self.pg1.remote_ip4) self.assertEqual(packet[ICMP].id, self.icmp_id_in) self.assertEqual(packet[ICMP].type, 0) # echo reply except: self.logger.error( ppp("Unexpected or invalid packet " "(outside network):", packet)) raise
def test_tra_basic(self, count=1): """ ipsec v4 transport basic test """ self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET] send_pkts = self.gen_encrypt_pkts(p.scapy_tra_sa, self.tra_if, src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4, count=count) recv_pkts = self.send_and_expect(self.tra_if, send_pkts, self.tra_if) for rx in recv_pkts: try: decrypted = p.vpp_tra_sa.decrypt(rx[IP]) self.assert_packet_checksums_valid(decrypted) except: self.logger.debug(ppp("Unexpected packet:", rx)) raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) pkts = p.tra_sa_in.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA in counts: expected %d != %d" % (count, pkts)) pkts = p.tra_sa_out.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SA out counts: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tra4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tra4_decrypt_node_name, count)
def assert_packet_checksums_valid(self, packet, ignore_zero_udp_checksums=True): received = packet.__class__(str(packet)) self.logger.debug( ppp("Verifying packet checksums for packet:", received)) udp_layers = ['UDP', 'UDPerror'] checksum_fields = ['cksum', 'chksum'] checksums = [] counter = 0 temp = received.__class__(str(received)) while True: layer = temp.getlayer(counter) if layer: for cf in checksum_fields: if hasattr(layer, cf): if ignore_zero_udp_checksums and \ 0 == getattr(layer, cf) and \ layer.name in udp_layers: continue delattr(layer, cf) checksums.append((counter, cf)) else: break counter = counter + 1 if 0 == len(checksums): return temp = temp.__class__(str(temp)) for layer, cf in checksums: calc_sum = getattr(temp[layer], cf) self.assert_equal( getattr(received[layer], cf), calc_sum, "packet checksum on layer #%d: %s" % (layer, temp[layer].name)) self.logger.debug( "Checksum field `%s` on `%s` layer has correct value `%s`" % (cf, temp[layer].name, calc_sum))
def checkCapture(self, encap, isv4): self.pg0.assert_nothing_captured() out = self.pg1.get_capture(len(self.packets)) load = [0] * len(self.ass) self.info = None for p in out: try: asid = 0 gre = None if (encap == 'gre4'): ip = p[IP] asid = int(ip.dst.split(".")[3]) self.assertEqual(ip.version, 4) self.assertEqual(ip.flags, 0) self.assertEqual(ip.src, "39.40.41.42") self.assertEqual(ip.dst, "10.0.0.%u" % asid) self.assertEqual(ip.proto, 47) self.assertEqual(len(ip.options), 0) self.assertGreaterEqual(ip.ttl, 64) gre = p[GRE] self.checkInner(gre, isv4) elif (encap == 'gre6'): ip = p[IPv6] asid = ip.dst.split(":") asid = asid[len(asid) - 1] asid = 0 if asid == "" else int(asid) self.assertEqual(ip.version, 6) self.assertEqual(ip.tc, 0) self.assertEqual(ip.fl, 0) self.assertEqual(ip.src, "2004::1") self.assertEqual( socket.inet_pton(socket.AF_INET6, ip.dst), socket.inet_pton(socket.AF_INET6, "2002::%u" % asid)) self.assertEqual(ip.nh, 47) self.assertGreaterEqual(ip.hlim, 64) # self.assertEqual(len(ip.options), 0) gre = GRE(str(p[IPv6].payload)) self.checkInner(gre, isv4) if (encap == 'l3dsr'): ip = p[IP] asid = int(ip.dst.split(".")[3]) self.assertEqual(ip.version, 4) self.assertEqual(ip.flags, 0) self.assertEqual(ip.dst, "10.0.0.%u" % asid) self.assertEqual(ip.tos, 0x1c) self.assertEqual(len(ip.options), 0) load[asid] += 1 except: self.logger.error(ppp("Unexpected or invalid packet:", p)) raise # This is just to roughly check that the balancing algorithm # is not completly biased. for asid in self.ass: if load[asid] < len(self.packets) / (len(self.ass) * 2): self.logger.error("ASS is not balanced: load[%d] = %d" % (asid, load[asid])) raise Exception("Load Balancer algorithm is biased")
def test_tun_basic44(self, count=1): """ ipsec 4o4 tunnel basic test """ self.vapi.cli("clear errors") try: p = self.params[socket.AF_INET] vpp_tun_sa, scapy_tun_sa = self.configure_sa_tun(p) send_pkts = self.gen_encrypt_pkts(scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IP].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: try: decrypt_pkt = vpp_tun_sa.decrypt(recv_pkt[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug( ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) if (hasattr(p, "spd_policy_in_any")): pkts = p.spd_policy_in_any.get_stats()['packets'] self.assertEqual(pkts, count, "incorrect SPD any policy: expected %d != %d" % (count, pkts)) self.assert_packet_counter_equal(self.tun4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tun4_decrypt_node_name, count)
def verify_decapped_pppoe(self, src_if, capture, sent): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def verify_encrypted6(self, p, sa, rxs): for rx in rxs: self.assert_packet_checksums_valid(rx) self.assertEqual( len(rx) - len(Ether()) - len(IPv6()), rx[IPv6].plen) try: decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IPv6]) if not decrypt_pkt.haslayer(IPv6): decrypt_pkt = IPv6(decrypt_pkt[Raw].load) self.assert_packet_checksums_valid(decrypt_pkt) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) except: self.logger.debug(ppp("Unexpected packet:", rx)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise
def verify_encrypted(self, p, sa, rxs): for rx in rxs: try: pkt = sa.decrypt(rx[IP]) if not pkt.haslayer(IP): pkt = IP(pkt[Raw].load) self.assert_packet_checksums_valid(pkt) self.assert_equal(pkt[IP].dst, self.pg0.remote_ip4) self.assert_equal(pkt[IP].src, self.pg0.local_ip4) inner = pkt[IP].payload self.assertEqual(inner[IP][IP].dst, p.remote_tun_if_host) except (IndexError, AssertionError): self.logger.debug(ppp("Unexpected packet:", rx)) try: self.logger.debug(ppp("Decrypted packet:", pkt)) except: pass raise
def verify_tun_66(self, p, count=1): """ ipsec 6o6 tunnel basic test """ self.vapi.cli("clear errors") try: config_tun_params(p, self.encryption_type, self.tun_if) send_pkts = self.gen_encrypt_pkts6(p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip6, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: self.assertEqual( len(recv_pkt) - len(Ether()) - len(IPv6()), recv_pkt[IPv6].plen) try: decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IPv6]) if not decrypt_pkt.haslayer(IPv6): decrypt_pkt = IPv6(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec all")) self.verify_counters(p, count)
def verify_encrypted(self, p, sa, rxs): for rx in rxs: try: pkt = sa.decrypt(rx[IP]) if not pkt.haslayer(IP): pkt = IP(pkt[Raw].load) self.assert_packet_checksums_valid(pkt) self.assert_equal(pkt[IP].dst, self.pg0.remote_ip4) self.assert_equal(pkt[IP].src, self.pg0.local_ip4) self.assertTrue(pkt.haslayer(GRE)) e = pkt[Ether] self.assertEqual(e[Ether].dst, self.omac) self.assertEqual(e[IP].dst, "1.1.1.2") except (IndexError, AssertionError): self.logger.debug(ppp("Unexpected packet:", rx)) try: self.logger.debug(ppp("Decrypted packet:", pkt)) except: pass raise
def verify_encrypted(self, p, sa, rxs): decrypt_pkts = [] for rx in rxs: try: decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) decrypt_pkts.append(decrypt_pkt) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) except: self.logger.debug(ppp("Unexpected packet:", rx)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise pkts = reassemble4(decrypt_pkts) for pkt in pkts: self.assert_packet_checksums_valid(pkt)
def verify_capture(self, pg_if, capture): """ Verify captured input packet stream for defined interface. :param object pg_if: Interface to verify captured packet stream for. :param list capture: Captured packet stream. """ last_info = dict() for i in self.pg_interfaces: last_info[i.sw_if_index] = None dst_sw_if_index = pg_if.sw_if_index for packet in capture: payload_info = self.payload_to_info(packet[Raw]) src_sw_if_index = payload_info.src src_if = None for ifc in self.pg_interfaces: if ifc != pg_if: if ifc.sw_if_index == src_sw_if_index: src_if = ifc break if hasattr(src_if, "sub_if"): # Check VLAN tags and Ethernet header packet = src_if.sub_if.remove_dot1_layer(packet) self.assertTrue(Dot1Q not in packet) try: ip = packet[IP] udp = packet[UDP] packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (pg_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertTrue(next_info is not None) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data # Check standard fields self.assertEqual(ip.src, saved_packet[IP].src) self.assertEqual(ip.dst, saved_packet[IP].dst) self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for i in self.pg_interfaces: remaining_packet = self.get_next_packet_info_for_interface2( i, dst_sw_if_index, last_info[i.sw_if_index]) self.assertTrue( remaining_packet is None, "Port %u: Packet expected from source %u didn't arrive" % (dst_sw_if_index, i.sw_if_index), )
def resolve_ndp(self, pg_interface=None, timeout=1): """Resolve NDP using provided packet-generator interface :param pg_interface: interface used to resolve, if None then this interface is used :param timeout: how long to wait for response before giving up """ if pg_interface is None: pg_interface = self self.test.logger.info("Sending NDP request for %s on port %s" % (self.local_ip6, pg_interface.name)) ndp_req = self.create_ndp_req() pg_interface.add_stream(ndp_req) pg_interface.enable_capture() self.test.pg_start() now = time.time() deadline = now + timeout # Enabling IPv6 on an interface can generate more than the # ND reply we are looking for (namely MLD). So loop through # the replies to look for want we want. while now < deadline: try: captured_packet = pg_interface.wait_for_packet( deadline - now, filter_out_fn=None) except: self.test.logger.error( "Timeout while waiting for NDP response") raise ndp_reply = captured_packet.copy() # keep original for exception # Make Dot1AD packet content recognizable to scapy if ndp_reply.type == 0x88a8: self._test.logger.info( "Replacing EtherType: 0x88a8 with " "0x8100 and regenerating Ethernet header. ") ndp_reply.type = 0x8100 ndp_reply = Ether(scapy.compat.raw(ndp_reply)) try: ndp_na = ndp_reply[ICMPv6ND_NA] opt = ndp_na[ICMPv6NDOptDstLLAddr] self.test.logger.info("VPP %s MAC address is %s " % (self.name, opt.lladdr)) self._local_mac = opt.lladdr self.test.logger.debug(self.test.vapi.cli("show trace")) # we now have the MAC we've been after return except: self.test.logger.info( ppp("Unexpected response to NDP request:", captured_packet)) now = time.time() self.test.logger.debug(self.test.vapi.cli("show trace")) raise Exception("Timeout while waiting for NDP response")
def verify_capture(self, scapy_ip_family, capture, dropped_packet_indexes=None): """Verify captured packet stream. :param list capture: Captured packet stream. """ validate_scapy_ip_family(scapy_ip_family) if dropped_packet_indexes is None: dropped_packet_indexes = [] info = None seen = set() for packet in capture: try: self.logger.debug(ppp("Got packet:", packet)) ip = packet[scapy_ip_family] udp = packet[UDP] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index self.assertTrue( packet_index not in dropped_packet_indexes, ppp("Packet received, but should be dropped:", packet)) if packet_index in seen: raise Exception(ppp("Duplicate packet received", packet)) seen.add(packet_index) self.assertEqual(payload_info.dst, self.src_if.sw_if_index) info = self._packet_infos[packet_index] self.assertTrue(info is not None) self.assertEqual(packet_index, info.index) saved_packet = info.data self.assertEqual(ip.src, saved_packet[scapy_ip_family].src) self.assertEqual(ip.dst, saved_packet[scapy_ip_family].dst) self.assertEqual(udp.payload, saved_packet[UDP].payload) except Exception: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for index in self._packet_infos: self.assertTrue(index in seen or index in dropped_packet_indexes, "Packet with packet_index %d not received" % index)
def verify_capture(self, pg_if, capture): """ Verify captured input packet stream for defined interface. :param object pg_if: Interface to verify captured packet stream for. :param list capture: Captured packet stream. """ last_info = dict() for i in self.pg_interfaces: last_info[i.sw_if_index] = None dst_sw_if_index = pg_if.sw_if_index for packet in capture: payload_info = self.payload_to_info(packet[Raw]) src_sw_if_index = payload_info.src src_if = None for ifc in self.pg_interfaces: if ifc != pg_if: if ifc.sw_if_index == src_sw_if_index: src_if = ifc break if hasattr(src_if, 'sub_if'): # Check VLAN tags and Ethernet header packet = src_if.sub_if.remove_dot1_layer(packet) self.assertTrue(Dot1Q not in packet) try: ip = packet[IP] udp = packet[UDP] packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (pg_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertTrue(next_info is not None) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data # Check standard fields self.assertEqual(ip.src, saved_packet[IP].src) self.assertEqual(ip.dst, saved_packet[IP].dst) self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for i in self.pg_interfaces: remaining_packet = self.get_next_packet_info_for_interface2( i, dst_sw_if_index, last_info[i.sw_if_index]) self.assertTrue( remaining_packet is None, "Port %u: Packet expected from source %u didn't arrive" % (dst_sw_if_index, i.sw_if_index))
def verify_tcp_checksum(self): self.vapi.cli("test http server") p = self.params[socket.AF_INET] send = (Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac) / p.scapy_tun_sa.encrypt( IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4) / TCP(flags='S', dport=80))) self.logger.debug(ppp("Sending packet:", send)) recv = self.send_and_expect(self.tun_if, [send], self.tun_if) recv = recv[0] decrypted = p.vpp_tun_sa.decrypt(recv[IP]) self.assert_packet_checksums_valid(decrypted)
def verify_capture(self, capture, ip_class, dropped_packet_indexes=[]): """Verify captured packet stream. :param list capture: Captured packet stream. """ info = None seen = set() for packet in capture: try: sw_if_index = packet['sw_if_index'] punt_action = packet['punt_action'] packet = Ether(packet['packet']) self.logger.debug( ppp( "Got packet from %s, action %s" % (sw_if_index, punt_action), packet)) ip = packet[ip_class] udp = packet[UDP] payload_info = self.payload_to_info(str(packet[Raw])) packet_index = payload_info.index self.assertTrue( packet_index not in dropped_packet_indexes, ppp("Packet received, but should be dropped:", packet)) if packet_index in seen: raise Exception(ppp("Duplicate packet received", packet)) seen.add(packet_index) self.assertEqual(payload_info.dst, self.pg_if.sw_if_index) info = self._packet_infos[packet_index] self.assertTrue(info is not None) self.assertEqual(packet_index, info.index) saved_packet = info.data self.assertEqual(ip.src, saved_packet[ip_class].src) self.assertEqual(ip.dst, saved_packet[ip_class].dst) self.assertEqual(udp.payload, saved_packet[UDP].payload) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for index in self._packet_infos: self.assertTrue(index in seen or index in dropped_packet_indexes, "Packet with packet_index %d not received" % index)
def verify_tun_66(self, p, count=1): """ ipsec 6o6 tunnel basic test """ self.vapi.cli("clear errors") try: config_tun_params(p, self.encryption_type, self.tun_if) send_pkts = self.gen_encrypt_pkts6(p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip6, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: self.assertEqual(len(recv_pkt) - len(Ether()) - len(IPv6()), recv_pkt[IPv6].plen) try: decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IPv6]) if not decrypt_pkt.haslayer(IPv6): decrypt_pkt = IPv6(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug( ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) self.verify_counters(p, count)
def verify_tun_44(self, p, count=1): self.vapi.cli("clear errors") try: config_tun_params(p, self.encryption_type, self.tun_if) send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IP].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: try: decrypt_pkt = p.vpp_tun_sa.decrypt(recv_pkt[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) self.verify_counters(p, count)
def resolve_ndp(self, pg_interface=None, timeout=1, link_layer=False): """Resolve NDP using provided packet-generator interface :param pg_interface: interface used to resolve, if None then this interface is used :param timeout: how long to wait for response before giving up :param link_layer: resolve for global address if False (default) or for link-layer address if True """ if pg_interface is None: pg_interface = self addr = self.local_ip6_ll if link_layer else self.local_ip6 self.test.logger.info( "Sending NDP request for %s on port %s" % (addr, pg_interface.name) ) ndp_req = self.create_ndp_req(addr) pg_interface.add_stream(ndp_req) pg_interface.enable_capture() self.test.pg_start() now = time.time() deadline = now + timeout # Enabling IPv6 on an interface can generate more than the # ND reply we are looking for (namely MLD). So loop through # the replies to look for want we want. while now < deadline: try: captured_packet = pg_interface.wait_for_packet( deadline - now, filter_out_fn=None ) except: self.test.logger.error("Timeout while waiting for NDP response") raise ndp_reply = captured_packet.copy() # keep original for exception try: ndp_na = ndp_reply[ICMPv6ND_NA] opt = ndp_na[ICMPv6NDOptDstLLAddr] self.test.logger.info( "VPP %s MAC address is %s " % (self.name, opt.lladdr) ) self._local_mac = opt.lladdr self.test.logger.debug(self.test.vapi.cli("show trace")) # we now have the MAC we've been after return except: self.test.logger.info( ppp("Unexpected response to NDP request:", captured_packet) ) now = time.time() self.test.logger.debug(self.test.vapi.cli("show trace")) raise Exception("Timeout while waiting for NDP response")
def verify_decapped_4o4(self, src_if, capture, sent): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] tx_gre = tx[GRE] tx_ip = tx_gre[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) # IP processing post pop has decremented the TTL self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def verify_tunneled_vlano4(self, src_if, capture, sent, tunnel_src, tunnel_dst, vlan): try: self.assertEqual(len(capture), len(sent)) except: ppc("Unexpected packets captured:", capture) raise for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = rx[GRE] rx_l2 = rx_gre[Ether] rx_vlan = rx_l2[Dot1Q] rx_ip = rx_l2[IP] self.assertEqual(rx_vlan.vlan, vlan) tx_gre = tx[GRE] tx_l2 = tx_gre[Ether] tx_ip = tx_l2[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) # bridged, not L3 forwarded, so no TTL decrement self.assertEqual(rx_ip.ttl, tx_ip.ttl) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise
def test_tun_basic44(self, count=1): """ ipsec 4o4 tunnel basic test """ try: p = self.params[socket.AF_INET] vpp_tun_sa, scapy_tun_sa = self.configure_sa_tun(p) send_pkts = self.gen_encrypt_pkts(scapy_tun_sa, self.tun_if, src=p.remote_tun_if_host, dst=self.pg1.remote_ip4, count=count) recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1) for recv_pkt in recv_pkts: self.assert_equal(recv_pkt[IP].src, p.remote_tun_if_host) self.assert_equal(recv_pkt[IP].dst, self.pg1.remote_ip4) self.assert_packet_checksums_valid(recv_pkt) send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4, dst=p.remote_tun_if_host, count=count) recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if) for recv_pkt in recv_pkts: try: decrypt_pkt = vpp_tun_sa.decrypt(recv_pkt[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) self.assert_packet_checksums_valid(decrypt_pkt) except: self.logger.debug(ppp("Unexpected packet:", recv_pkt)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise finally: self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec"))
def verify_encrypted(self, p, sa, rxs): decrypt_pkts = [] for rx in rxs: self.assert_packet_checksums_valid(rx) self.assertEqual(len(rx) - len(Ether()), rx[IP].len) try: decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IP]) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) decrypt_pkts.append(decrypt_pkt) self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip4) self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host) except: self.logger.debug(ppp("Unexpected packet:", rx)) try: self.logger.debug(ppp("Decrypted packet:", decrypt_pkt)) except: pass raise pkts = reassemble4(decrypt_pkts) for pkt in pkts: self.assert_packet_checksums_valid(pkt)
def verify_tcp_checksum(self): self.vapi.cli("test http server") p = self.params[socket.AF_INET] config_tun_params(p, self.encryption_type, self.tun_if) send = (Ether(src=self.tun_if.remote_mac, dst=self.tun_if.local_mac) / p.scapy_tun_sa.encrypt(IP(src=p.remote_tun_if_host, dst=self.tun_if.local_ip4) / TCP(flags='S', dport=80))) self.logger.debug(ppp("Sending packet:", send)) recv = self.send_and_expect(self.tun_if, [send], self.tun_if) recv = recv[0] decrypted = p.vpp_tun_sa.decrypt(recv[IP]) self.assert_packet_checksums_valid(decrypted)
def verify_capture(self, rx_if, capture, ip_l=IP): """Verify captured input packet stream for defined interface. :param VppInterface rx_if: Interface to verify captured packet stream. :param list capture: Captured packet stream. :param Scapy ip_l: Required IP layer - IP or IPv6. (Default is IP.) """ self.logger.info("Verifying capture on interface %s" % rx_if.name) count = 0 host_counters = {} for host_mac in rx_if._hosts_by_mac: host_counters[host_mac] = 0 for packet in capture: try: ip_received = packet[ip_l] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index ip_sent = self._packet_infos[packet_index].data[ip_l] self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (rx_if.name, payload_info.src, packet_index)) # Check standard fields self.assertIn(packet.dst, rx_if._hosts_by_mac, "Destination MAC address %s shouldn't be routed " "via interface %s" % (packet.dst, rx_if.name)) self.assertEqual(packet.src, rx_if.local_mac) self.assertEqual(ip_received.src, ip_sent.src) self.assertEqual(ip_received.dst, ip_sent.dst) host_counters[packet.dst] += 1 self._packet_infos.pop(packet_index) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise # We expect packet routed via all host of pg interface for host_mac in host_counters: nr = host_counters[host_mac] self.assertNotEqual( nr, 0, "No packet routed via host %s" % host_mac) self.logger.info("%u packets routed via host %s of %s interface" % (nr, host_mac, rx_if.name)) count += nr self.logger.info("Total amount of %u packets routed via %s interface" % (count, rx_if.name)) return count
def verify_capture(self, dst_if, capture, proto_l=UDP): """Verify captured input packet stream for defined interface. :param VppInterface dst_if: Interface to verify captured packet stream. :param list capture: Captured packet stream. :param Scapy proto_l: Required IP protocol. Default protocol is UDP. """ self.logger.info("Verifying capture on interface %s" % dst_if.name) last_info = dict() for i in self.interfaces: last_info[i.sw_if_index] = None dst_sw_if_index = dst_if.sw_if_index for packet in capture: try: ip_received = packet[IP] proto_received = packet[proto_l] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) self.logger.debug( "Got packet on port %s: src=%u (id=%u)" % (dst_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertTrue(next_info is not None) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data ip_saved = saved_packet[IP] proto_saved = saved_packet[proto_l] # Check standard fields self.assertEqual(ip_received.src, ip_saved.src) self.assertEqual(ip_received.dst, ip_saved.dst) self.assertEqual(proto_received.sport, proto_saved.sport) self.assertEqual(proto_received.dport, proto_saved.dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for i in self.interfaces: remaining_packet = self.get_next_packet_info_for_interface2( i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index]) self.assertTrue(remaining_packet is None, "Interface %s: Packet expected from interface %s " "didn't arrive" % (dst_if.name, i.name))
def verify_capture(self, pg_if, capture): """ Verify captured input packet stream for defined interface. :param object pg_if: Interface to verify captured packet stream for. :param list capture: Captured packet stream. """ last_info = dict() for i in self.pg_interfaces: last_info[i.sw_if_index] = None dst_sw_if_index = pg_if.sw_if_index for packet in capture: try: ip = packet[IP] udp = packet[UDP] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (pg_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertIsNotNone(next_info) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data # Check standard fields self.assertEqual(ip.src, saved_packet[IP].src) self.assertEqual(ip.dst, saved_packet[IP].dst) self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for i in self.pg_interfaces: remaining_packet = self.get_next_packet_info_for_interface2( i, dst_sw_if_index, last_info[i.sw_if_index]) self.assertIsNone( remaining_packet, "Port %u: Packet expected from source %u didn't arrive" % (dst_sw_if_index, i.sw_if_index))
def create_stream(self, src_if, dst_if, packet_header, packet_sizes, count): """Create SRv6 input packet stream for defined interface. :param VppInterface src_if: Interface to create packet stream for :param VppInterface dst_if: destination interface of packet stream :param packet_header: Layer3 scapy packet headers, L2 is added when not provided, Raw(payload) with packet_info is added :param list packet_sizes: packet stream pckt sizes,sequentially applied to packets in stream have :param int count: number of packets in packet stream :return: list of packets """ self.logger.info("Creating packets") pkts = [] for i in range(0, count-1): payload_info = self.create_packet_info(src_if, dst_if) self.logger.debug( "Creating packet with index %d" % (payload_info.index)) payload = self.info_to_payload(payload_info) # add L2 header if not yet provided in packet_header if packet_header.getlayer(0).name == 'Ethernet': p = (packet_header / Raw(payload)) else: p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / packet_header / Raw(payload)) size = packet_sizes[i % len(packet_sizes)] self.logger.debug("Packet size %d" % (size)) self.extend_packet(p, size) # we need to store the packet with the automatic fields computed # read back the dumped packet (with str()) # to force computing these fields # probably other ways are possible p = Ether(scapy.compat.raw(p)) payload_info.data = p.copy() self.logger.debug(ppp("Created packet:", p)) pkts.append(p) self.logger.info("Done creating packets") return pkts
def verify_capture(self, dst_if): """ Verify captured input packet stream for defined interface. :param object dst_if: Interface to verify captured packet stream for. """ last_info = dict() for i in self.flows[dst_if]: last_info[i.sw_if_index] = None dst = dst_if.sw_if_index for packet in dst_if.get_capture(): try: ip = packet[IP] udp = packet[UDP] info = self.payload_to_info(packet[Raw]) self.assertEqual(info.dst, dst) self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (dst_if.name, info.src, info.index)) last_info[info.src] = self.get_next_packet_info_for_interface2( info.src, dst, last_info[info.src]) pkt_info = last_info[info.src] self.assertTrue(pkt_info is not None) self.assertEqual(info.index, pkt_info.index) # Check standard fields against saved data in pkt saved = pkt_info.data self.assertEqual(ip.src, saved[IP].src) self.assertEqual(ip.dst, saved[IP].dst) self.assertEqual(udp.sport, saved[UDP].sport) self.assertEqual(udp.dport, saved[UDP].dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise s = "" remaining = 0 for src in self.flows[dst_if]: remaining_packet = self.get_next_packet_info_for_interface2( src.sw_if_index, dst, last_info[src.sw_if_index]) if remaining_packet is None: s += "Port %u: Packet expected from source %u didn't arrive\n"\ % (dst, src.sw_if_index) remaining += 1 self.assertNotEqual(0, remaining, s)
def verify_capture_encrypted(self, capture, sa): for packet in capture: try: copy = packet.__class__(scapy.compat.raw(packet)) del copy[UDP].len copy = packet.__class__(scapy.compat.raw(copy)) self.assert_equal(packet[UDP].len, copy[UDP].len, "UDP header length") self.assert_packet_checksums_valid(packet) self.assertIn(ESP, packet[IP]) decrypt_pkt = sa.decrypt(packet[IP]) self.assert_packet_checksums_valid(decrypt_pkt) self.assert_equal(decrypt_pkt[IP].src, self.pg1.remote_ip4, "encrypted packet source address") self.assert_equal(decrypt_pkt[IP].dst, self.tun_if.remote_ip4, "encrypted packet destination address") except Exception: self.logger.error( ppp("Unexpected or invalid encrypted packet:", packet)) raise
def resolve_arp(self, pg_interface=None): """Resolve ARP using provided packet-generator interface :param pg_interface: interface used to resolve, if None then this interface is used """ if pg_interface is None: pg_interface = self self.test.logger.info("Sending ARP request for %s on port %s" % (self.local_ip4, pg_interface.name)) arp_req = self.create_arp_req() pg_interface.add_stream(arp_req) pg_interface.enable_capture() self.test.pg_start() self.test.logger.info(self.test.vapi.cli("show trace")) try: captured_packet = pg_interface.wait_for_packet(1) except: self.test.logger.info("No ARP received on port %s" % pg_interface.name) return arp_reply = captured_packet.copy() # keep original for exception # Make Dot1AD packet content recognizable to scapy if arp_reply.type == 0x88a8: arp_reply.type = 0x8100 arp_reply = Ether(scapy.compat.raw(arp_reply)) try: if arp_reply[ARP].op == ARP.is_at: self.test.logger.info("VPP %s MAC address is %s " % (self.name, arp_reply[ARP].hwsrc)) self._local_mac = arp_reply[ARP].hwsrc else: self.test.logger.info("No ARP received on port %s" % pg_interface.name) except: self.test.logger.error( ppp("Unexpected response to ARP request:", captured_packet)) raise
def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1, expected=True): """ wait for CFLOW packet and verify its correctness :param timeout: how long to wait :returns: tuple (packet, time spent waiting for packet) """ self.logger.info("IPFIX: Waiting for CFLOW packet") deadline = time.time() + timeout counter = 0 # self.logger.debug(self.vapi.ppcli("show flow table")) while True: counter += 1 # sanity check self.assert_in_range(counter, 0, 100, "number of packets ignored") time_left = deadline - time.time() try: if time_left < 0 and expected: # self.logger.debug(self.vapi.ppcli("show flow table")) raise CaptureTimeoutError( "Packet did not arrive within timeout") p = collector_intf.wait_for_packet(timeout=time_left) except CaptureTimeoutError: if expected: # self.logger.debug(self.vapi.ppcli("show flow table")) raise CaptureTimeoutError( "Packet did not arrive within timeout") else: return if not expected: raise CaptureTimeoutError("Packet arrived even not expected") self.assertEqual(p[Set].setID, set_id) # self.logger.debug(self.vapi.ppcli("show flow table")) self.logger.debug(ppp("IPFIX: Got packet:", p)) break return p
def test_syslog(self): """ Syslog Protocol test """ self.vapi.syslog_set_sender(src_address=self.pg0.local_ip4n, collector_address=self.pg0.remote_ip4n) config = self.vapi.syslog_get_sender() self.assertEqual(str(config.collector_address), self.pg0.remote_ip4) self.assertEqual(config.collector_port, 514) self.assertEqual(str(config.src_address), self.pg0.local_ip4) self.assertEqual(config.vrf_id, 0) self.assertEqual(config.max_msg_size, 480) appname = 'test' msgid = 'testMsg' msg = 'this is message' sd1 = {'exampleSDID@32473': {'iut': '3', 'eventSource': 'App', 'eventID': '1011'}} sd2 = {'exampleSDID@32473': {'iut': '3', 'eventSource': 'App', 'eventID': '1011'}, 'examplePriority@32473': {'class': 'high'}} self.pg_enable_capture(self.pg_interfaces) self.syslog_generate(SyslogFacility.local7, SyslogSeverity.info, appname, msgid, None, msg) capture = self.pg0.get_capture(1) try: self.assertEqual(capture[0][IP].src, self.pg0.local_ip4) self.assertEqual(capture[0][IP].dst, self.pg0.remote_ip4) self.assertEqual(capture[0][UDP].dport, 514) self.assert_packet_checksums_valid(capture[0], False) except: self.logger.error(ppp("invalid packet:", capture[0])) raise self.syslog_verify(capture[0][Raw].load, SyslogFacility.local7, SyslogSeverity.info, appname, msgid, None, msg) self.pg_enable_capture(self.pg_interfaces) self.vapi.syslog_set_filter(SYSLOG_SEVERITY.WARN) filter = self.vapi.syslog_get_filter() self.assertEqual(filter.severity, SYSLOG_SEVERITY.WARN) self.syslog_generate(SyslogFacility.local7, SyslogSeverity.info, appname, msgid, None, msg) self.pg0.assert_nothing_captured() self.pg_enable_capture(self.pg_interfaces) self.syslog_generate(SyslogFacility.local6, SyslogSeverity.warning, appname, msgid, sd1, msg) capture = self.pg0.get_capture(1) self.syslog_verify(capture[0][Raw].load, SyslogFacility.local6, SyslogSeverity.warning, appname, msgid, sd1, msg) self.vapi.syslog_set_sender(self.pg0.local_ip4n, self.pg0.remote_ip4n, collector_port=12345) config = self.vapi.syslog_get_sender() self.assertEqual(config.collector_port, 12345) self.pg_enable_capture(self.pg_interfaces) self.syslog_generate(SyslogFacility.local5, SyslogSeverity.err, appname, msgid, sd2, None) capture = self.pg0.get_capture(1) try: self.assertEqual(capture[0][UDP].dport, 12345) except: self.logger.error(ppp("invalid packet:", capture[0])) raise self.syslog_verify(capture[0][Raw].load, SyslogFacility.local5, SyslogSeverity.err, appname, msgid, sd2, None)
def checkCapture(self, encap, isv4): self.pg0.assert_nothing_captured() out = self.pg1.get_capture(len(self.packets)) load = [0] * len(self.ass) self.info = None for p in out: try: asid = 0 gre = None if (encap == 'gre4'): ip = p[IP] asid = int(ip.dst.split(".")[3]) self.assertEqual(ip.version, 4) self.assertEqual(ip.flags, 0) self.assertEqual(ip.src, "39.40.41.42") self.assertEqual(ip.dst, "10.0.0.%u" % asid) self.assertEqual(ip.proto, 47) self.assertEqual(len(ip.options), 0) gre = p[GRE] self.checkInner(gre, isv4) elif (encap == 'gre6'): ip = p[IPv6] asid = ip.dst.split(":") asid = asid[len(asid) - 1] asid = 0 if asid == "" else int(asid) self.assertEqual(ip.version, 6) self.assertEqual(ip.tc, 0) self.assertEqual(ip.fl, 0) self.assertEqual(ip.src, "2004::1") self.assertEqual( socket.inet_pton(socket.AF_INET6, ip.dst), socket.inet_pton(socket.AF_INET6, "2002::%u" % asid) ) self.assertEqual(ip.nh, 47) # self.assertEqual(len(ip.options), 0) gre = GRE(scapy.compat.raw(p[IPv6].payload)) self.checkInner(gre, isv4) elif (encap == 'l3dsr'): ip = p[IP] asid = int(ip.dst.split(".")[3]) self.assertEqual(ip.version, 4) self.assertEqual(ip.flags, 0) self.assertEqual(ip.dst, "10.0.0.%u" % asid) self.assertEqual(ip.tos, 0x1c) self.assertEqual(len(ip.options), 0) self.assert_ip_checksum_valid(p) if ip.proto == IP_PROTOS.tcp: self.assert_tcp_checksum_valid(p) elif ip.proto == IP_PROTOS.udp: self.assert_udp_checksum_valid(p) elif (encap == 'nat4'): ip = p[IP] asid = int(ip.dst.split(".")[3]) self.assertEqual(ip.version, 4) self.assertEqual(ip.flags, 0) self.assertEqual(ip.dst, "10.0.0.%u" % asid) self.assertEqual(ip.proto, 17) self.assertEqual(len(ip.options), 0) udp = p[UDP] self.assertEqual(udp.dport, 3307) elif (encap == 'nat6'): ip = p[IPv6] asid = ip.dst.split(":") asid = asid[len(asid) - 1] asid = 0 if asid == "" else int(asid) self.assertEqual(ip.version, 6) self.assertEqual(ip.tc, 0) self.assertEqual(ip.fl, 0) self.assertEqual( socket.inet_pton(socket.AF_INET6, ip.dst), socket.inet_pton(socket.AF_INET6, "2002::%u" % asid) ) self.assertEqual(ip.nh, 17) self.assertGreaterEqual(ip.hlim, 63) udp = UDP(scapy.compat.raw(p[IPv6].payload)) self.assertEqual(udp.dport, 3307) load[asid] += 1 except: self.logger.error(ppp("Unexpected or invalid packet:", p)) raise # This is just to roughly check that the balancing algorithm # is not completely biased. for asid in self.ass: if load[asid] < len(self.packets) / (len(self.ass) * 2): self.logger.error( "ASS is not balanced: load[%d] = %d" % (asid, load[asid])) raise Exception("Load Balancer algorithm is biased")
* 4 6D 0/1 0.702689 見 動詞,自立,*,*,一段,連用形,見る,ミ,ミ O た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ O * 5 6D 0/1 1.193842 きれい 名詞,形容動詞語幹,*,*,*,*,きれい,キレイ,キレイ O な 助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ O * 6 7D 0/1 0.000000 女性 名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ O に 助詞,格助詞,一般,*,*,*,に,ニ,ニ O * 7 -1D 0/1 0.000000 渡し 動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ O た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ O 。 記号,句点,*,*,*,*,。,。,。 O EOS ''' dg = jpdep.parse(cabocha_result) reset_deps(dg) jpdep.set_head_form(dg) dg.nodelist = [_node_map(n) for n in dg.nodelist] util.ppp( dg.nodelist) analyze_dependency(dg) print str(dg.tree()).decode('utf-8')
def send_packet(self, packet): self.logger.debug(ppp("Sending packet:", packet)) self.interface.add_stream(packet) self.pg_start()