def test_encap_big_packet(self): """ Encapsulation test send big frame from pg1 Verify receipt of encapsulated frames on pg0 """ self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / IP(src='4.3.2.1', dst='1.2.3.4') / UDP(sport=20000, dport=10000) / Raw('\xa5' * 1450)) self.pg1.add_stream([frame]) self.pg0.enable_capture() self.pg_start() # Pick first received frame and check if it's correctly encapsulated. out = self.pg0.get_capture(2) ether = out[0] pkt = reassemble4(out) pkt = ether / pkt self.check_encapsulation(pkt, self.single_tunnel_bd) payload = self.decapsulate(pkt)
def test_encap_big_packet(self): """ Encapsulation test send big frame from pg1 Verify receipt of encapsulated frames on pg0 """ self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / IP(src='4.3.2.1', dst='1.2.3.4') / UDP(sport=20000, dport=10000) / Raw(b'\xa5' * 1450)) self.pg1.add_stream([frame]) self.pg0.enable_capture() self.pg_start() # Pick first received frame and check if it's correctly encapsulated. out = self.pg0.get_capture(2) ether = out[0] pkt = reassemble4(out) pkt = ether / pkt self.check_encapsulation(pkt, self.single_tunnel_vni) payload = self.decapsulate(pkt)
def encap_fragmented_packet(self): frame = ( Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01") / IP(src="4.3.2.1", dst="1.2.3.4") / UDP(sport=20000, dport=10000) / Raw(b"\xa5" * 1000) ) frags = util.fragment_rfc791(frame, 400) self.pg1.add_stream(frags) self.pg0.enable_capture() self.pg_start() out = self.pg0.get_capture(3) payload = [] for pkt in out: payload.append(self.decapsulate(pkt)) self.check_encapsulation(pkt, self.single_tunnel_vni) reassembled = util.reassemble4(payload) self.assertEqual(Ether(raw(frame))[IP], reassembled[IP])
def verify_encrypted(self, p, sa, rxs): decrypt_pkts = [] for rx in rxs: if p.nat_header: self.assertEqual(rx[UDP].dport, 4500) self.assert_packet_checksums_valid(rx) self.assertEqual(len(rx) - len(Ether()), rx[IP].len) try: rx_ip = rx[IP] decrypt_pkt = p.vpp_tun_sa.decrypt(rx_ip) if not decrypt_pkt.haslayer(IP): decrypt_pkt = IP(decrypt_pkt[Raw].load) if rx_ip.proto == socket.IPPROTO_ESP: self.verify_esp_padding(sa, rx_ip[ESP].data, decrypt_pkt) decrypt_pkts.append(decrypt_pkt) self.assert_equal(decrypt_pkt.src, p.tun_if.local_ip4) self.assert_equal(decrypt_pkt.dst, p.tun_if.remote_ip4) 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 test_encap_fragmented_packet(self): """ Encapsulation test send fragments from pg1 Verify receipt of encapsulated frames on pg0 """ frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / IP(src='4.3.2.1', dst='1.2.3.4') / UDP(sport=20000, dport=10000) / Raw(b'\xa5' * 1000)) frags = util.fragment_rfc791(frame, 400) self.pg1.add_stream(frags) self.pg0.enable_capture() self.pg_start() out = self.pg0.get_capture(3) payload = [] for pkt in out: payload.append(self.decapsulate(pkt)) self.check_encapsulation(pkt, self.single_tunnel_vni) reassembled = util.reassemble4(payload) self.assertEqual(Ether(raw(frame))[IP], reassembled[IP])
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 encap_big_packet(self): self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) frame = (Ether(src="00:00:00:00:00:02", dst="00:00:00:00:00:01") / IP(src="4.3.2.1", dst="1.2.3.4") / UDP(sport=20000, dport=10000) / Raw(b"\xa5" * 1450)) self.pg1.add_stream([frame]) self.pg0.enable_capture() self.pg_start() # Pick first received frame and check if it's correctly encapsulated. out = self.pg0.get_capture(2) ether = out[0] pkt = reassemble4(out) pkt = ether / pkt self.check_encapsulation(pkt, self.single_tunnel_vni) payload = self.decapsulate(pkt)
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 test_ipip4(self): """ ip{v4,v6} over ip4 test """ self.pg1.generate_remote_hosts(5) self.pg1.configure_ipv4_neighbors() e = VppEnum.vl_api_tunnel_encap_decap_flags_t d = VppEnum.vl_api_ip_dscp_t self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) self.p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100) # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits # are for the ECN. dscp = d.IP_API_DSCP_AF31 << 2 ecn = 3 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn # IPv4 transport that copies the DCSP from the payload tun_dscp = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip4, self.pg1.remote_hosts[0].ip4, flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP) tun_dscp.add_vpp_config() # IPv4 transport that copies the DCSP and ECN from the payload tun_dscp_ecn = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip4, self.pg1.remote_hosts[1].ip4, flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN)) tun_dscp_ecn.add_vpp_config() # IPv4 transport that copies the ECN from the payload and sets the # DF bit on encap. copies the ECN on decap tun_ecn = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip4, self.pg1.remote_hosts[2].ip4, flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN)) tun_ecn.add_vpp_config() # IPv4 transport that sets a fixed DSCP in the encap and copies # the DF bit tun = VppIpIpTunInterface( self, self.pg0, self.pg0.local_ip4, self.pg1.remote_hosts[3].ip4, dscp=d.IP_API_DSCP_AF11, flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF) tun.add_vpp_config() # array of all the tunnels tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun] # addresses for prefixes routed via each tunnel a4s = ["" for i in range(len(tuns))] a6s = ["" for i in range(len(tuns))] # IP headers with each combination of DSCp/ECN tested p_ip6s = [ IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp), IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp_ecn), IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=ecn), IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=0xff) ] p_ip4s = [ IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags='DF'), IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn), IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn), IP(src="1.2.3.4", dst="130.67.0.1", tos=0xff) ] # Configure each tunnel for i, t in enumerate(tuns): # Set interface up and enable IP on it self.vapi.sw_interface_set_flags(t.sw_if_index, 1) self.vapi.sw_interface_set_unnumbered( sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=t.sw_if_index) # prefix for route / destination address for packets a4s[i] = "130.67.%d.0" % i a6s[i] = "dead:%d::" % i # Add IPv4 and IPv6 routes via tunnel interface ip4_via_tunnel = VppIpRoute(self, a4s[i], 24, [ VppRoutePath("0.0.0.0", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) ip4_via_tunnel.add_vpp_config() ip6_via_tunnel = VppIpRoute(self, a6s[i], 64, [ VppRoutePath("::", t.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) ip6_via_tunnel.add_vpp_config() # # Encapsulation # # tun_dscp copies only the dscp # expected TC values are thus only the DCSP value is present from the # inner exp_tcs = [dscp, dscp, 0, 0xfc] p_ip44_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, tos=tc) for tc in exp_tcs ] p_ip64_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, proto='ipv6', id=0, tos=tc) for tc in exp_tcs ] # IPv4 in to IPv4 tunnel self.verify_ip4ip4_encaps(a4s[0], p_ip4s, p_ip44_encaps) # IPv6 in to IPv4 tunnel self.verify_ip6ip4_encaps(a6s[0], p_ip6s, p_ip64_encaps) # tun_dscp_ecn copies the dscp and the ecn exp_tcs = [dscp, dscp_ecn, ecn, 0xff] p_ip44_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, tos=tc) for tc in exp_tcs ] p_ip64_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, proto='ipv6', id=0, tos=tc) for tc in exp_tcs ] self.verify_ip4ip4_encaps(a4s[1], p_ip4s, p_ip44_encaps) self.verify_ip6ip4_encaps(a6s[1], p_ip6s, p_ip64_encaps) # tun_ecn copies only the ecn and always sets DF exp_tcs = [0, ecn, ecn, ecn] p_ip44_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_ecn.dst, flags='DF', tos=tc) for tc in exp_tcs ] p_ip64_encaps = [ IP(src=self.pg0.local_ip4, dst=tun_ecn.dst, flags='DF', proto='ipv6', id=0, tos=tc) for tc in exp_tcs ] self.verify_ip4ip4_encaps(a4s[2], p_ip4s, p_ip44_encaps) self.verify_ip6ip4_encaps(a6s[2], p_ip6s, p_ip64_encaps) # tun sets a fixed dscp and copies DF fixed_dscp = tun.dscp << 2 flags = ['DF', 0, 0, 0] p_ip44_encaps = [ IP(src=self.pg0.local_ip4, dst=tun.dst, flags=f, tos=fixed_dscp) for f in flags ] p_ip64_encaps = [ IP(src=self.pg0.local_ip4, dst=tun.dst, proto='ipv6', id=0, tos=fixed_dscp) for i in range(len(p_ip4s)) ] self.verify_ip4ip4_encaps(a4s[3], p_ip4s, p_ip44_encaps) self.verify_ip6ip4_encaps(a6s[3], p_ip6s, p_ip64_encaps) # # Decapsulation # n_packets_decapped = 0 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) # IPv4 tunnel to IPv4 tcs = [0, dscp, dscp_ecn, ecn] # one overlay packet and all combinations of its encap p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) p_ip4_encaps = [ IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs ] # for each encap tun will produce the same inner packet because it does # not copy up fields from the payload for p_ip4_encap in p_ip4_encaps: p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload) p4_reply = (p_ip4 / self.p_payload) p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0) n_packets_decapped += N_PACKETS for p in rx: self.validate(p[1], p4_reply) self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # tun_ecn copies the ECN bits from the encap to the inner p_ip4_encaps = [ IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs ] p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip4_encaps))] p_ip4_replys[2].tos = ecn p_ip4_replys[3].tos = ecn for i, p_ip4_encap in enumerate(p_ip4_encaps): p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload) p4_reply = (p_ip4_replys[i] / self.p_payload) p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0) n_packets_decapped += N_PACKETS for p in rx: self.validate(p[1], p4_reply) self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # IPv4 tunnel to IPv6 # for each encap tun will produce the same inner packet because it does # not copy up fields from the payload p_ip4_encaps = [ IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs ] p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) for p_ip4_encap in p_ip4_encaps: p6 = (self.p_ether / p_ip4_encap / p_ip6 / self.p_payload) p6_reply = (p_ip6 / self.p_payload) p6_reply.hlim = 63 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0) n_packets_decapped += N_PACKETS for p in rx: self.validate(p[1], p6_reply) self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # IPv4 tunnel to IPv6 # tun_ecn copies the ECN bits from the encap to the inner p_ip4_encaps = [ IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs ] p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip4_encaps))] p_ip6_replys[2].tc = ecn p_ip6_replys[3].tc = ecn for i, p_ip4_encap in enumerate(p_ip4_encaps): p6 = (self.p_ether / p_ip4_encap / p_ip6 / self.p_payload) p6_reply = (p_ip6_replys[i] / self.p_payload) p6_reply.hlim = 63 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0) n_packets_decapped += N_PACKETS for p in rx: self.validate(p[1], p6_reply) self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # # Fragmentation / Reassembly and Re-fragmentation # rv = self.vapi.ip_reassembly_enable_disable( sw_if_index=self.pg1.sw_if_index, enable_ip4=1) self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=1000, max_reassembly_length=1000, expire_walk_interval_ms=10000, is_ip6=0) # Send lots of fragments, verify reassembled packet frags, p4_reply = self.generate_ip4_frags(3131, 1400) f = [] for i in range(0, 1000): f.extend(frags) self.pg1.add_stream(f) self.pg_enable_capture() self.pg_start() rx = self.pg0.get_capture(1000) n_packets_decapped += 1000 for p in rx: self.validate(p[1], p4_reply) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) f = [] r = [] for i in range(1, 90): frags, p4_reply = self.generate_ip4_frags(i * 100, 1000) f.extend(frags) r.extend(p4_reply) self.pg_enable_capture() self.pg1.add_stream(f) self.pg_start() rx = self.pg0.get_capture(89) i = 0 for p in rx: self.validate(p[1], r[i]) i += 1 # Now try with re-fragmentation # # Send fragments to tunnel head-end, for the tunnel head end # to reassemble and then refragment # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(6) reass_pkt = reassemble4(rx) p4_reply.id = 256 self.validate(reass_pkt, p4_reply) self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(2) reass_pkt = reassemble4(rx) p4_reply.id = 512 self.validate(reass_pkt, p4_reply) # send large packets through the tunnel, expect them to be fragmented self.vapi.sw_interface_set_mtu(tun_dscp.sw_if_index, [600, 0, 0, 0]) p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="1.2.3.4", dst="130.67.0.1", tos=42) / UDP(sport=1234, dport=1234) / Raw(b'Q' * 1000)) rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30) inners = [] for p in rx: inners.append(p[IP].payload) reass_pkt = reassemble4(inners) for p in reass_pkt: self.assert_packet_checksums_valid(p) self.assertEqual(p[IP].ttl, 63)
def test_ip4_mtu(self): """ IP4 MTU test """ p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') current_mtu = self.get_mtu(self.pg1.sw_if_index) p_payload = UDP(sport=1234, dport=1234) / self.payload(current_mtu - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4_reply = p_ip4 / p_payload p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1) for p in rx: self.validate(p[1], p4_reply) # MTU self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) self.assertEqual(576, self.get_mtu(self.pg1.sw_if_index)) # Should fail. Too large MTU p_icmp4 = ICMP(type='dest-unreach', code='fragmentation-needed', nexthopmtu=576, chksum=0x2dbb) icmp4_reply = (IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, ttl=254, len=576, id=0) / p_icmp4 / p_ip4 / p_payload) icmp4_reply[1].ttl -= 1 n = icmp4_reply.__class__(icmp4_reply) s = bytes(icmp4_reply) icmp4_reply = s[0:576] rx = self.send_and_expect(self.pg0, p4 * 11, self.pg0) for p in rx: # p.show2() # n.show2() self.validate_bytes(bytes(p[1]), icmp4_reply) # Now with DF off. Expect fragments. # First go with 1500 byte packets. p_payload = UDP(sport=1234, dport=1234) / self.payload(1500 - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4.flags = 0 p4_reply = p_ip4 / p_payload p4_reply.ttl = 62 # check this p4_reply.flags = 0 p4_reply.id = 256 self.pg_enable_capture() self.pg0.add_stream(p4 * 1) self.pg_start() rx = self.pg1.get_capture(3) reass_pkt = reassemble4(rx) self.validate(reass_pkt, p4_reply) ''' # Now what happens with a 9K frame p_payload = UDP(sport=1234, dport=1234) / self.payload( current_mtu - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4.flags = 0 p4_reply = p_ip4 / p_payload p4_reply.ttl = 62 # check this p4_reply.flags = 0 p4_reply.id = 512 self.pg_enable_capture() self.pg0.add_stream(p4*1) self.pg_start() rx = self.pg1.get_capture(16) reass_pkt = reassemble4(rx) reass_pkt.show2() p4_reply.show2() self.validate(reass_pkt, p4_reply) ''' # Reset MTU self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [current_mtu, 0, 0, 0])
def test_ip4_mtu(self): """ IP4 MTU test """ p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') current_mtu = self.get_mtu(self.pg1.sw_if_index) p_payload = UDP(sport=1234, dport=1234) / self.payload( current_mtu - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4_reply = p_ip4 / p_payload p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg0, p4*11, self.pg1) for p in rx: self.validate(p[1], p4_reply) # MTU self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) self.assertEqual(576, self.get_mtu(self.pg1.sw_if_index)) # Should fail. Too large MTU p_icmp4 = ICMP(type='dest-unreach', code='fragmentation-needed', nexthopmtu=576, chksum=0x2dbb) icmp4_reply = (IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, ttl=254, len=576, id=0) / p_icmp4 / p_ip4 / p_payload) icmp4_reply[1].ttl -= 1 n = icmp4_reply.__class__(icmp4_reply) s = bytes(icmp4_reply) icmp4_reply = s[0:576] rx = self.send_and_expect(self.pg0, p4*11, self.pg0) for p in rx: # p.show2() # n.show2() self.validate_bytes(bytes(p[1]), icmp4_reply) # Now with DF off. Expect fragments. # First go with 1500 byte packets. p_payload = UDP(sport=1234, dport=1234) / self.payload( 1500 - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4.flags = 0 p4_reply = p_ip4 / p_payload p4_reply.ttl = 62 # check this p4_reply.flags = 0 p4_reply.id = 256 self.pg_enable_capture() self.pg0.add_stream(p4*1) self.pg_start() rx = self.pg1.get_capture(3) reass_pkt = reassemble4(rx) self.validate(reass_pkt, p4_reply) ''' # Now what happens with a 9K frame p_payload = UDP(sport=1234, dport=1234) / self.payload( current_mtu - 20 - 8) p4 = p_ether / p_ip4 / p_payload p4.flags = 0 p4_reply = p_ip4 / p_payload p4_reply.ttl = 62 # check this p4_reply.flags = 0 p4_reply.id = 512 self.pg_enable_capture() self.pg0.add_stream(p4*1) self.pg_start() rx = self.pg1.get_capture(16) reass_pkt = reassemble4(rx) reass_pkt.show2() p4_reply.show2() self.validate(reass_pkt, p4_reply) ''' # Reset MTU self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [current_mtu, 0, 0, 0])
def test_ipip4(self): """ ip{v4,v6} over ip4 test """ p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42) p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42) p_payload = UDP(sport=1234, dport=1234) # IPv4 transport rv = ipip_add_tunnel(self, self.pg0.local_ip4, self.pg1.remote_ip4, tc_tos=0xFF) sw_if_index = rv.sw_if_index # Set interface up and enable IP on it self.vapi.sw_interface_set_flags(sw_if_index, 1) self.vapi.sw_interface_set_unnumbered( sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=sw_if_index) # Add IPv4 and IPv6 routes via tunnel interface ip4_via_tunnel = VppIpRoute( self, "130.67.0.0", 16, [ VppRoutePath( "0.0.0.0", sw_if_index, proto=DpoProto.DPO_PROTO_IP4) ], is_ip6=0) ip4_via_tunnel.add_vpp_config() ip6_via_tunnel = VppIpRoute( self, "dead::", 16, [VppRoutePath("::", sw_if_index, proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1) ip6_via_tunnel.add_vpp_config() # IPv6 in to IPv4 tunnel p6 = (p_ether / p_ip6 / p_payload) p_inner_ip6 = p_ip6 p_inner_ip6.hlim -= 1 p6_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, proto='ipv6', id=0, tos=42) / p_inner_ip6 / p_payload) p6_reply.ttl -= 1 rx = self.send_and_expect(self.pg0, p6 * 10, self.pg1) for p in rx: self.validate(p[1], p6_reply) # IPv4 in to IPv4 tunnel p4 = (p_ether / p_ip4 / p_payload) p_ip4_inner = p_ip4 p_ip4_inner.ttl -= 1 p4_reply = ( IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, tos=42) / p_ip4_inner / p_payload) p4_reply.ttl -= 1 p4_reply.id = 0 rx = self.send_and_expect(self.pg0, p4 * 10, self.pg1) for p in rx: self.validate(p[1], p4_reply) # Decapsulation p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) # IPv4 tunnel to IPv4 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) p4 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) / p_ip4 / p_payload) p4_reply = (p_ip4 / p_payload) p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg1, p4 * 10, self.pg0) for p in rx: self.validate(p[1], p4_reply) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 10) # IPv4 tunnel to IPv6 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) p6 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) / p_ip6 / p_payload) p6_reply = (p_ip6 / p_payload) p6_reply.hlim = 63 rx = self.send_and_expect(self.pg1, p6 * 10, self.pg0) for p in rx: self.validate(p[1], p6_reply) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 20) # # Fragmentation / Reassembly and Re-fragmentation # rv = self.vapi.ip_reassembly_enable_disable( sw_if_index=self.pg1.sw_if_index, enable_ip4=1) self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=1000, max_reassembly_length=1000, expire_walk_interval_ms=10000, is_ip6=0) # Send lots of fragments, verify reassembled packet frags, p4_reply = self.generate_ip4_frags(3131, 1400) f = [] for i in range(0, 1000): f.extend(frags) self.pg1.add_stream(f) self.pg_enable_capture() self.pg_start() rx = self.pg0.get_capture(1000) for p in rx: self.validate(p[1], p4_reply) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 1020) f = [] r = [] for i in range(1, 90): frags, p4_reply = self.generate_ip4_frags(i * 100, 1000) f.extend(frags) r.extend(p4_reply) self.pg_enable_capture() self.pg1.add_stream(f) self.pg_start() rx = self.pg0.get_capture(89) i = 0 for p in rx: self.validate(p[1], r[i]) i += 1 # Now try with re-fragmentation # # Send fragments to tunnel head-end, for the tunnel head end # to reassemble and then refragment # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(6) reass_pkt = reassemble4(rx) p4_reply.ttl -= 1 p4_reply.id = 256 self.validate(reass_pkt, p4_reply) self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(2) reass_pkt = reassemble4(rx) p4_reply.ttl -= 1 p4_reply.id = 512 self.validate(reass_pkt, p4_reply)
def test_ipip4(self): """ ip{v4,v6} over ip4 test """ p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42) p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42) p_payload = UDP(sport=1234, dport=1234) # IPv4 transport rv = self.vapi.ipip_add_tunnel( src_address=self.pg0.local_ip4n, dst_address=self.pg1.remote_ip4n, is_ipv6=0, tc_tos=0xFF) sw_if_index = rv.sw_if_index # Set interface up and enable IP on it self.vapi.sw_interface_set_flags(sw_if_index, 1) self.vapi.sw_interface_set_unnumbered( sw_if_index=self.pg0.sw_if_index, unnumbered_sw_if_index=sw_if_index) # Add IPv4 and IPv6 routes via tunnel interface ip4_via_tunnel = VppIpRoute( self, "130.67.0.0", 16, [VppRoutePath("0.0.0.0", sw_if_index, proto=DpoProto.DPO_PROTO_IP4)], is_ip6=0) ip4_via_tunnel.add_vpp_config() ip6_via_tunnel = VppIpRoute( self, "dead::", 16, [VppRoutePath("::", sw_if_index, proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1) ip6_via_tunnel.add_vpp_config() # IPv6 in to IPv4 tunnel p6 = (p_ether / p_ip6 / p_payload) p_inner_ip6 = p_ip6 p_inner_ip6.hlim -= 1 p6_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, proto='ipv6', id=0, tos=42) / p_inner_ip6 / p_payload) p6_reply.ttl -= 1 rx = self.send_and_expect(self.pg0, p6 * 10, self.pg1) for p in rx: self.validate(p[1], p6_reply) # IPv4 in to IPv4 tunnel p4 = (p_ether / p_ip4 / p_payload) p_ip4_inner = p_ip4 p_ip4_inner.ttl -= 1 p4_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, tos=42) / p_ip4_inner / p_payload) p4_reply.ttl -= 1 p4_reply.id = 0 rx = self.send_and_expect(self.pg0, p4 * 10, self.pg1) for p in rx: self.validate(p[1], p4_reply) # Decapsulation p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) # IPv4 tunnel to IPv4 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) p4 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) / p_ip4 / p_payload) p4_reply = (p_ip4 / p_payload) p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg1, p4 * 10, self.pg0) for p in rx: self.validate(p[1], p4_reply) err = self.statistics.get_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 10) # IPv4 tunnel to IPv6 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) p6 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) / p_ip6 / p_payload) p6_reply = (p_ip6 / p_payload) p6_reply.hlim = 63 rx = self.send_and_expect(self.pg1, p6 * 10, self.pg0) for p in rx: self.validate(p[1], p6_reply) err = self.statistics.get_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 20) # # Fragmentation / Reassembly and Re-fragmentation # rv = self.vapi.ip_reassembly_enable_disable( sw_if_index=self.pg1.sw_if_index, enable_ip4=1) # Send lots of fragments, verify reassembled packet frags, p4_reply = self.generate_ip4_frags(3131, 1400) f = [] for i in range(0, 1000): f.extend(frags) self.pg1.add_stream(f) self.pg_enable_capture() self.pg_start() rx = self.pg0.get_capture(1000) for p in rx: self.validate(p[1], p4_reply) err = self.statistics.get_counter( '/err/ipip4-input/packets decapsulated') self.assertEqual(err, 1020) f = [] r = [] for i in range(1, 90): frags, p4_reply = self.generate_ip4_frags(i * 100, 1000) f.extend(frags) r.extend(p4_reply) self.pg_enable_capture() self.pg1.add_stream(f) self.pg_start() rx = self.pg0.get_capture(89) i = 0 for p in rx: self.validate(p[1], r[i]) i += 1 # Now try with re-fragmentation # # Send fragments to tunnel head-end, for the tunnel head end # to reassemble and then refragment # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(6) reass_pkt = reassemble4(rx) p4_reply.ttl -= 1 p4_reply.id = 256 self.validate(reass_pkt, p4_reply) self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0]) frags, p4_reply = self.generate_ip4_frags(3123, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg0.get_capture(2) reass_pkt = reassemble4(rx) p4_reply.ttl -= 1 p4_reply.id = 512 self.validate(reass_pkt, p4_reply)