def generate_ip4_frags(self, payload_length, fragment_size): p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length) p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) outer_ip4 = (p_ether / IP( src=self.pg1.remote_ip4, id=RandShort(), dst=self.pg0.local_ip4) / p_ip4 / p_payload) frags = fragment(outer_ip4, fragment_size) p4_reply = (p_ip4 / p_payload) p4_reply.ttl -= 1 return frags, p4_reply
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 test_encap(self): """ ip{v4,v6} over ip6 test encap """ p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP') p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42) p_payload = UDP(sport=1234, dport=1234) # Encapsulation # IPv6 in to IPv6 tunnel p6 = (p_ether / p_ip6 / p_payload) p6_reply = ( IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64) / p_ip6 / p_payload) p6_reply[1].hlim -= 1 rx = self.send_and_expect(self.pg0, p6 * 11, self.pg1) for p in rx: self.validate(p[1], p6_reply) # IPv4 in to IPv6 tunnel p4 = (p_ether / p_ip4 / p_payload) p4_reply = ( IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=64) / p_ip4 / p_payload) p4_reply[1].ttl -= 1 rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1) for p in rx: self.validate(p[1], p4_reply)
def test_decap(self): """ ip{v4,v6} over ip6 test decap """ p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP') p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) p_payload = UDP(sport=1234, dport=1234) # Decapsulation # IPv6 tunnel to IPv4 p4 = (p_ether / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6) / p_ip4 / p_payload) p4_reply = (p_ip4 / p_payload) p4_reply.ttl -= 1 rx = self.send_and_expect(self.pg1, p4 * 11, self.pg0) for p in rx: self.validate(p[1], p4_reply) # IPv6 tunnel to IPv6 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) p6 = (p_ether / IPv6(src=self.pg1.remote_ip6, dst=self.pg0.local_ip6) / p_ip6 / p_payload) p6_reply = (p_ip6 / p_payload) p6_reply.hlim = 63 rx = self.send_and_expect(self.pg1, p6 * 11, self.pg0) for p in rx: self.validate(p[1], p6_reply)
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 test_mipip4(self): """ p2mp IPv4 tunnel Tests """ for itf in self.pg_interfaces: # # one underlay nh for each overlay/tunnel peer # itf.generate_remote_hosts(4) itf.configure_ipv4_neighbors() # # Create an p2mo IPIP tunnel. # - set it admin up # - assign an IP Addres # - Add a route via the tunnel # ipip_if = VppIpIpTunInterface( self, itf, itf.local_ip4, "0.0.0.0", mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP)) ipip_if.add_vpp_config() ipip_if.admin_up() ipip_if.config_ip4() ipip_if.generate_remote_hosts(4) self.logger.info(self.vapi.cli("sh adj")) self.logger.info(self.vapi.cli("sh ip fib")) # # ensure we don't match to the tunnel if the source address # is all zeros # # tx = self.create_tunnel_stream_4o4(self.pg0, # "0.0.0.0", # itf.local_ip4, # self.pg0.local_ip4, # self.pg0.remote_ip4) # self.send_and_assert_no_replies(self.pg0, tx) # # for-each peer # for ii in range(1, 4): route_addr = "4.4.4.%d" % ii # # route traffic via the peer # route_via_tun = VppIpRoute(self, route_addr, 32, [ VppRoutePath(ipip_if._remote_hosts[ii].ip4, ipip_if.sw_if_index) ]) route_via_tun.add_vpp_config() # # Add a TEIB entry resolves the peer # teib = VppTeib(self, ipip_if, ipip_if._remote_hosts[ii].ip4, itf._remote_hosts[ii].ip4) teib.add_vpp_config() self.logger.info( self.vapi.cli("sh adj nbr ipip0 %s" % ipip_if._remote_hosts[ii].ip4)) # # Send a packet stream that is routed into the tunnel # - packets are IPIP encapped # inner = (IP(dst=route_addr, src="5.5.5.5") / UDP(sport=1234, dport=1234) / Raw(b'0x44' * 100)) tx_e = [ (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner) for x in range(63) ] rxs = self.send_and_expect(self.pg0, tx_e, itf) for rx in rxs: self.assertEqual(rx[IP].src, itf.local_ip4) self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4) tx_i = [ (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=itf._remote_hosts[ii].ip4, dst=itf.local_ip4) / IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / UDP(sport=1234, dport=1234) / Raw(b'0x44' * 100)) for x in range(63) ] self.logger.info(self.vapi.cli("sh ipip tunnel-hash")) rx = self.send_and_expect(self.pg0, tx_i, self.pg0) # # delete and re-add the TEIB # teib.remove_vpp_config() self.send_and_assert_no_replies(self.pg0, tx_e) self.send_and_assert_no_replies(self.pg0, tx_i) teib.add_vpp_config() rx = self.send_and_expect(self.pg0, tx_e, itf) for rx in rxs: self.assertEqual(rx[IP].src, itf.local_ip4) self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4) rx = self.send_and_expect(self.pg0, tx_i, self.pg0) ipip_if.admin_down() ipip_if.unconfig_ip4()
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_frag(self): """ ip{v4,v6} over ip6 test frag """ p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP') p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4) p_payload = UDP(sport=1234, dport=1234) # # Fragmentation / Reassembly and Re-fragmentation # rv = self.vapi.ip_reassembly_enable_disable( sw_if_index=self.pg1.sw_if_index, enable_ip6=1) self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=1000, max_reassembly_length=1000, expire_walk_interval_ms=10000, is_ip6=1) # Send lots of fragments, verify reassembled packet before_cnt = self.statistics.get_err_counter( '/err/ipip6-input/packets decapsulated') frags, p6_reply = self.generate_ip6_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], p6_reply) cnt = self.statistics.get_err_counter( '/err/ipip6-input/packets decapsulated') self.assertEqual(cnt, before_cnt + 1000) f = [] r = [] # TODO: Check out why reassembly of atomic fragments don't work for i in range(10, 90): frags, p6_reply = self.generate_ip6_frags(i * 100, 1000) f.extend(frags) r.extend(p6_reply) self.pg_enable_capture() self.pg1.add_stream(f) self.pg_start() rx = self.pg0.get_capture(80) i = 0 for p in rx: self.validate(p[1], r[i]) i += 1 # Simple fragmentation p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) # IPv6 in to IPv6 tunnel p_payload = UDP(sport=1234, dport=1234) / self.payload(1300) p6 = (p_ether / p_ip6 / p_payload) p6_reply = ( IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63) / p_ip6 / p_payload) p6_reply[1].hlim -= 1 self.pg_enable_capture() self.pg0.add_stream(p6) self.pg_start() rx = self.pg1.get_capture(2) # Scapy defragment doesn't deal well with multiple layers # of same type / Ethernet header first f = [p[1] for p in rx] reass_pkt = defragment6(f) self.validate(reass_pkt, p6_reply) # Now try with re-fragmentation # # Send large fragments to tunnel head-end, for the tunnel head end # to reassemble and then refragment out the tunnel again. # Hair-pinning # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200) self.pg_enable_capture() self.pg1.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(7) f = [p[1] for p in rx] reass_pkt = defragment6(f) p6_reply.id = 256 self.validate(reass_pkt, p6_reply)
def test_gro(self): """ GRO test """ n_packets = 124 # # Send 1500 bytes frame with gro disabled # p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') / TCP(sport=1234, dport=4321) / Raw(b'\xa5' * 1460)) rxs = self.send_and_expect(self.pg0, n_packets * p4, self.pg1) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) # # Send 1500 bytes frame with gro enabled on # output interfaces support GRO # p = [] s = 0 for n in range(0, n_packets): p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4, flags='DF') / TCP(sport=1234, dport=4321, seq=s, ack=n, flags='A') / Raw(b'\xa5' * 1460))) s += 1460 rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2) i = 0 for rx in rxs: i += 1 self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx[IP].len, 64280) # 1460 * 44 + 40 < 65536 self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) self.assertEqual(rx[TCP].ack, (44 * i - 1)) p4_temp = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=4321, flags='F')) rxs = self.send_and_expect(self.pg2, 100 * [p4_temp], self.pg0, n_rx=100) rx_coalesce = self.pg2.get_capture(1, timeout=1) rx0 = rx_coalesce[0] self.assertEqual(rx0[Ether].src, self.pg2.local_mac) self.assertEqual(rx0[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx0[IP].src, self.pg0.remote_ip4) self.assertEqual(rx0[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx0[IP].len, 52600) # 1460 * 36 + 40 self.assertEqual(rx0[TCP].sport, 1234) self.assertEqual(rx0[TCP].dport, 4321) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].len, 40) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321)
def test_gso_ipip(self): """ GSO IPIP test """ self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) # # enable ipip4 # self.ipip4.add_vpp_config() # Set interface up and enable IP on it self.ipip4.admin_up() self.ipip4.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip4_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip4_tunnel.add_vpp_config() # # IPv4/IPv4 - IPIP # p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 4) # ipencap inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.ip6_via_ip4_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip4_tunnel.add_vpp_config() # # IPv4/IPv6 - IPIP # p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p67], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 41) # ipv6 inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip # tunnel - IPSec use case # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0) self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index) rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 4) # ipencap inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipip4 # self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, enable_disable=0) self.ip4_via_ip4_tunnel.remove_vpp_config() self.ip6_via_ip4_tunnel.remove_vpp_config() self.ipip4.remove_vpp_config() # # enable ipip6 # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) self.ipip6.add_vpp_config() # Set interface up and enable IP on it self.ipip6.admin_up() self.ipip6.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip6_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip6_tunnel.add_vpp_config() # # IPv6/IPv4 - IPIP # p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p48], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "IP") inner = rx[IPv6].payload self.assertEqual(rx[IPv6].plen, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.ip6_via_ip6_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip6_tunnel.add_vpp_config() # # IPv6/IPv6 - IPIP # p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p68], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6") inner = rx[IPv6].payload self.assertEqual(rx[IPv6].plen, len(inner)) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipip6 # self.ip4_via_ip6_tunnel.remove_vpp_config() self.ip6_via_ip6_tunnel.remove_vpp_config() self.ipip6.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
def test_gso_vxlan(self): """ GSO VXLAN test """ self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2 # into BD. # # # enable ipv4/vxlan # self.vxlan.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) # # IPv4/IPv4 - VXLAN # p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p45], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv4/IPv6 - VXLAN # p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p65], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipv4/vxlan # self.vxlan.remove_vpp_config() # # enable ipv6/vxlan # self.vxlan2.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan2.sw_if_index, bd_id=self.single_tunnel_bd) # # IPv6/IPv4 - VXLAN # p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p46], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv6/IPv6 - VXLAN # p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p66], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipv4/vxlan # self.vxlan2.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
def test_gso_ipsec(self): """ GSO IPSEC test """ # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. # # # enable ipip4 # self.ipip4.add_vpp_config() self.vapi.feature_gso_enable_disable( sw_if_index=self.ipip4.sw_if_index, enable_disable=1) # Add IPv4 routes via tunnel interface self.ip4_via_ip4_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip4_tunnel.add_vpp_config() # IPSec config self.ipv4_params = IPsecIPv4Params() self.encryption_type = ESP config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4) self.tun_sa_in_v4 = VppIpsecSA( self, self.ipv4_params.vpp_tun_sa_id, self.ipv4_params.vpp_tun_spi, self.ipv4_params.auth_algo_vpp_id, self.ipv4_params.auth_key, self.ipv4_params.crypt_algo_vpp_id, self.ipv4_params.crypt_key, VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP) self.tun_sa_in_v4.add_vpp_config() self.tun_sa_out_v4 = VppIpsecSA( self, self.ipv4_params.scapy_tun_sa_id, self.ipv4_params.scapy_tun_spi, self.ipv4_params.auth_algo_vpp_id, self.ipv4_params.auth_key, self.ipv4_params.crypt_algo_vpp_id, self.ipv4_params.crypt_key, VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP) self.tun_sa_out_v4.add_vpp_config() self.tun_protect_v4 = VppIpsecTunProtect(self, self.ipip4, self.tun_sa_out_v4, [self.tun_sa_in_v4]) self.tun_protect_v4.add_vpp_config() # Set interface up and enable IP on it self.ipip4.admin_up() self.ipip4.set_unnumbered(self.pg0.sw_if_index) # # IPv4/IPv4 - IPSEC # ipsec44 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].proto, 50) # ESP self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi) inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP]) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") size += inner[IP].len - 20 - 20 self.assertEqual(size, 65200) self.ip6_via_ip4_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip4_tunnel.add_vpp_config() # # IPv4/IPv6 - IPSEC # ipsec46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].proto, 50) # ESP self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi) inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP]) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") size += inner[IPv6].plen - 20 self.assertEqual(size, 65200) # disable IPSec self.tun_protect_v4.remove_vpp_config() self.tun_sa_in_v4.remove_vpp_config() self.tun_sa_out_v4.remove_vpp_config() # # disable ipip4 # self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, enable_disable=0) self.ip4_via_ip4_tunnel.remove_vpp_config() self.ip6_via_ip4_tunnel.remove_vpp_config() self.ipip4.remove_vpp_config() # # enable ipip6 # self.ipip6.add_vpp_config() self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index, enable_disable=1) # Set interface up and enable IP on it self.ipip6.admin_up() self.ipip6.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip6_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip6_tunnel.add_vpp_config() # IPSec config self.ipv6_params = IPsecIPv6Params() self.encryption_type = ESP config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6) self.tun_sa_in_v6 = VppIpsecSA( self, self.ipv6_params.vpp_tun_sa_id, self.ipv6_params.vpp_tun_spi, self.ipv6_params.auth_algo_vpp_id, self.ipv6_params.auth_key, self.ipv6_params.crypt_algo_vpp_id, self.ipv6_params.crypt_key, VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP) self.tun_sa_in_v6.add_vpp_config() self.tun_sa_out_v6 = VppIpsecSA( self, self.ipv6_params.scapy_tun_sa_id, self.ipv6_params.scapy_tun_spi, self.ipv6_params.auth_algo_vpp_id, self.ipv6_params.auth_key, self.ipv6_params.crypt_algo_vpp_id, self.ipv6_params.crypt_key, VppEnum.vl_api_ipsec_proto_t.IPSEC_API_PROTO_ESP) self.tun_sa_out_v6.add_vpp_config() self.tun_protect_v6 = VppIpsecTunProtect(self, self.ipip6, self.tun_sa_out_v6, [self.tun_sa_in_v6]) self.tun_protect_v6.add_vpp_config() # # IPv6/IPv4 - IPSEC # ipsec64 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header") self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi) inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6]) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") size += inner[IP].len - 20 - 20 self.assertEqual(size, 65200) self.ip6_via_ip6_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip6_tunnel.add_vpp_config() # # IPv6/IPv6 - IPSEC # ipsec66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header") self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi) inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6]) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") size += inner[IPv6].plen - 20 self.assertEqual(size, 65200) # disable IPSec self.tun_protect_v6.remove_vpp_config() self.tun_sa_in_v6.remove_vpp_config() self.tun_sa_out_v6.remove_vpp_config() # # disable ipip6 # self.ip4_via_ip6_tunnel.remove_vpp_config() self.ip6_via_ip6_tunnel.remove_vpp_config() self.ipip6.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
def test_gro(self): """GRO test""" n_packets = 124 # # Send 1500 bytes frame with gro disabled # p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321) / Raw(b"\xa5" * 1460)) rxs = self.send_and_expect(self.pg0, n_packets * p4, self.pg1) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) # # Send 1500 bytes frame with gro enabled on # output interfaces support GRO # p = [] s = 0 for n in range(0, n_packets): p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321, seq=s, ack=n, flags="A") / Raw(b"\xa5" * 1460))) s += 1460 rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2) i = 0 for rx in rxs: i += 1 self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx[IP].len, 64280) # 1460 * 44 + 40 < 65536 self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) self.assertEqual(rx[TCP].ack, (44 * i - 1)) p4_temp = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321, flags="F")) rxs = self.send_and_expect(self.pg2, 100 * [p4_temp], self.pg0, n_rx=100) rx_coalesce = self.pg2.get_capture(1, timeout=1) rx0 = rx_coalesce[0] self.assertEqual(rx0[Ether].src, self.pg2.local_mac) self.assertEqual(rx0[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx0[IP].src, self.pg0.remote_ip4) self.assertEqual(rx0[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx0[IP].len, 52600) # 1460 * 36 + 40 self.assertEqual(rx0[TCP].sport, 1234) self.assertEqual(rx0[TCP].dport, 4321) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].len, 40) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) # # Same test with IPv6 # p = [] s = 0 for n in range(0, 88): p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg2.remote_ip6) / TCP(sport=1234, dport=4321, seq=s, ack=n, flags="A") / Raw(b"\xa5" * 1460))) s += 1460 p[-1][TCP].flags = "AP" # push to flush second packet rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2) i = 0 for rx in rxs: i += 1 self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].plen, 64260) # 1460 * 44 + 20 < 65536 self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) self.assertEqual(rx[TCP].ack, (44 * i - 1)) # # Send a series of 1500 bytes packets each followed by a packet with a # PSH flag. Verify that GRO stops everytime a PSH flag is encountered # p = [] s = 0 for n in range(0, n_packets): p.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321, seq=s, ack=2 * n, flags="A") / Raw(b"\xa5" * 1460))) s += 1460 p.append(( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321, seq=s, ack=2 * n + 1, flags="AP") / Raw(b"\xa5" * 1340))) s += 1340 rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=n_packets) i = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx[IP].len, 40 + 1460 + 1340) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) self.assertEqual(rx[TCP].ack, (2 * i + 1)) i += 1 # # Send a series of 1500 bytes packets each followed by a short packet # with padding. Verify that GRO removes the padding and stops on short # packets # p = [] s = 0 for n in range(0, n_packets): i = self.pg0 p.append( (Ether(src=i.remote_mac, dst=i.local_mac) / IP(src=i.remote_ip4, dst=self.pg2.remote_ip4, flags="DF") / TCP(sport=1234, dport=4321, seq=s, ack=2 * n, flags="A") / Raw(b"\xa5" * 1459))) s += 1459 p2 = (Ether(src=i.remote_mac, dst=i.local_mac) / IP( src=i.remote_ip4, dst=self.pg2.remote_ip4, flags="DF", len=41) / TCP( sport=1234, dport=4321, seq=s, ack=2 * n + 1, flags="A") / Raw(b"\xa5")) # first compute csum of pkt w/o padding to work around scapy bug p2 = Ether(bytes(p2)) p.append(p2 / Raw(b"\xa5" * 5)) # 1 byte data + 5 bytes padding s += 1 rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=n_packets) i = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IP].src, self.pg0.remote_ip4) self.assertEqual(rx[IP].dst, self.pg2.remote_ip4) self.assertEqual(rx[IP].len, 40 + 1459 + 1) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 4321) self.assertEqual(rx[TCP].ack, (2 * i + 1)) i += 1
def test_gso(self): """ GSO test """ # # Send jumbo frame with gso disabled and DF bit is set # self.create_pg_interfaces(range(2)) for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw('\xa5' * 65200)) rxs = self.send_and_expect(self.pg0, [p4], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[ICMP].type, 3) # "dest-unreach" self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed" # # Send jumbo frame with gso enabled and DF bit is set # input and output interfaces support GSO # self.create_pg_interfaces(range(2, 4), 1, 1460) for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() p41 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw('\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p41], self.pg3) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg3.remote_ip4) self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # Send jumbo frame with gso enabled only on input interface # and DF bit is set. GSO packet will be chunked into gso_size # data payload # self.create_pg_interfaces(range(4, 5)) for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() p42 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg4.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw('\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p42], self.pg4, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg4.local_mac) self.assertEqual(rx[Ether].dst, self.pg4.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg4.remote_ip4) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) size = rxs[44][TCP].seq + rxs[44][IP].len - 20 - 20 self.assertEqual(size, 65200) # # Send jumbo frame with gso enabled only on input interface # and DF bit is unset. GSO packet will be fragmented. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw('\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p43], self.pg1, 119) size = 0 for rx in rxs: rx.show() self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) size += rx[IP].len - 20 size -= 20 # TCP header self.assertEqual(size, 65200)
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_mpls(self): """ MPLS over ip{6,4} test """ tbl = VppMplsTable(self, 0) tbl.add_vpp_config() 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) f = FibPathProto # IPv4 transport tun4 = VppIpIpTunInterface(self, self.pg1, self.pg1.local_ip4, self.pg1.remote_ip4).add_vpp_config() tun4.admin_up() tun4.config_ip4() tun4.enable_mpls() # IPv6 transport tun6 = VppIpIpTunInterface(self, self.pg1, self.pg1.local_ip6, self.pg1.remote_ip6).add_vpp_config() tun6.admin_up() tun6.config_ip6() tun6.enable_mpls() # ip routes into the tunnels with output labels r4 = VppIpRoute(self, "1.1.1.1", 32, [ VppRoutePath( tun4.remote_ip4, tun4.sw_if_index, labels=[VppMplsLabel(44)]) ]).add_vpp_config() r6 = VppIpRoute(self, "1::1", 128, [ VppRoutePath( tun6.remote_ip6, tun6.sw_if_index, labels=[VppMplsLabel(66)]) ]).add_vpp_config() # deag MPLS routes from the tunnel r4 = VppMplsRoute( self, 44, 1, [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index) ]).add_vpp_config() r6 = VppMplsRoute( self, 66, 1, [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index)], eos_proto=f.FIB_PATH_NH_PROTO_IP6).add_vpp_config() # # Tunnel Encap # p4 = (self.p_ether / IP(src="2.2.2.2", dst="1.1.1.1") / self.p_payload) rxs = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1) for rx in rxs: self.assertEqual(rx[IP].src, self.pg1.local_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assertEqual(rx[MPLS].label, 44) inner = rx[MPLS].payload self.assertEqual(inner.src, "2.2.2.2") self.assertEqual(inner.dst, "1.1.1.1") p6 = (self.p_ether / IPv6(src="2::2", dst="1::1") / self.p_payload) rxs = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1) for rx in rxs: self.assertEqual(rx[IPv6].src, self.pg1.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) self.assertEqual(rx[MPLS].label, 66) inner = rx[MPLS].payload self.assertEqual(inner.src, "2::2") self.assertEqual(inner.dst, "1::1") # # Tunnel Decap # p4 = (self.p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) / MPLS(label=44, ttl=4) / IP(src="1.1.1.1", dst="2.2.2.2") / self.p_payload) rxs = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0) for rx in rxs: self.assertEqual(rx[IP].src, "1.1.1.1") self.assertEqual(rx[IP].dst, "2.2.2.2") p6 = (self.p_ether / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) / MPLS(label=66, ttl=4) / IPv6(src="1::1", dst="2::2") / self.p_payload) rxs = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].src, "1::1") self.assertEqual(rx[IPv6].dst, "2::2") tun4.disable_mpls() tun6.disable_mpls()
def test_ipip6(self): """ ip{v4,v6} over ip6 test """ # that's annoying self.destroy_tunnel() self.pg1.generate_remote_hosts(5) self.pg1.configure_ipv6_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_ip6, self.pg1.remote_hosts[0].ip6, 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_ip6, self.pg1.remote_hosts[1].ip6, 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_ip6, self.pg1.remote_hosts[2].ip6, 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_ip6, self.pg1.remote_hosts[3].ip6, 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 for inner packets 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_ip6_encaps = [ IPv6(src=self.pg0.local_ip6, dst=tun_dscp.dst, tc=tc) for tc in exp_tcs ] # IPv4 in to IPv4 tunnel self.verify_ip4ip6_encaps(a4s[0], p_ip4s, p_ip6_encaps) # IPv6 in to IPv4 tunnel self.verify_ip6ip6_encaps(a6s[0], p_ip6s, p_ip6_encaps) # tun_dscp_ecn copies the dscp and the ecn exp_tcs = [dscp, dscp_ecn, ecn, 0xff] p_ip6_encaps = [ IPv6(src=self.pg0.local_ip6, dst=tun_dscp_ecn.dst, tc=tc) for tc in exp_tcs ] self.verify_ip4ip6_encaps(a4s[1], p_ip4s, p_ip6_encaps) self.verify_ip6ip6_encaps(a6s[1], p_ip6s, p_ip6_encaps) # tun_ecn copies only the ecn and always sets DF exp_tcs = [0, ecn, ecn, ecn] p_ip6_encaps = [ IPv6(src=self.pg0.local_ip6, dst=tun_ecn.dst, tc=tc) for tc in exp_tcs ] self.verify_ip4ip6_encaps(a4s[2], p_ip4s, p_ip6_encaps) self.verify_ip6ip6_encaps(a6s[2], p_ip6s, p_ip6_encaps) # tun sets a fixed dscp fixed_dscp = tun.dscp << 2 p_ip6_encaps = [ IPv6(src=self.pg0.local_ip6, dst=tun.dst, tc=fixed_dscp) for i in range(len(p_ip4s)) ] self.verify_ip4ip6_encaps(a4s[3], p_ip4s, p_ip6_encaps) self.verify_ip6ip6_encaps(a6s[3], p_ip6s, p_ip6_encaps) # # Decapsulation # n_packets_decapped = self.statistics.get_err_counter( '/err/ipip6-input/packets decapsulated') self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) # IPv6 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_ip6_encaps = [ IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=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_ip6_encap in p_ip6_encaps: p6 = (self.p_ether / p_ip6_encap / p_ip4 / self.p_payload) p4_reply = (p_ip4 / self.p_payload) p4_reply.ttl -= 1 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], p4_reply) self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip6-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # tun_ecn copies the ECN bits from the encap to the inner p_ip6_encaps = [ IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs ] p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip6_encaps))] p_ip4_replys[2].tos = ecn p_ip4_replys[3].tos = ecn for i, p_ip6_encap in enumerate(p_ip6_encaps): p6 = (self.p_ether / p_ip6_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, p6 * 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/ipip6-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # IPv6 tunnel to IPv6 # for each encap tun will produce the same inner packet because it does # not copy up fields from the payload p_ip6_encaps = [ IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs ] p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6) for p_ip6_encap in p_ip6_encaps: p6 = (self.p_ether / p_ip6_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/ipip6-input/packets decapsulated') self.assertEqual(err, n_packets_decapped) # IPv6 tunnel to IPv6 # tun_ecn copies the ECN bits from the encap to the inner p_ip6_encaps = [ IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=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_ip6_encaps))] p_ip6_replys[2].tc = ecn p_ip6_replys[3].tc = ecn for i, p_ip6_encap in enumerate(p_ip6_encaps): p6 = (self.p_ether / p_ip6_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/ipip6-input/packets decapsulated') self.assertEqual(err, n_packets_decapped)
def test_gso(self): """ GSO test """ # # Send jumbo frame with gso disabled and DF bit is set # p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg0, [p4], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[ICMP].type, 3) # "dest-unreach" self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed" # # Send checksum offload frames # p40 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 1460)) rxs = self.send_and_expect(self.pg2, 100 * [p40], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) payload_len = rx[IP].len - 20 - 20 self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 1440)) rxs = self.send_and_expect(self.pg2, 100 * [p60], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) # # Send jumbo frame with gso enabled and DF bit is set # input and output interfaces support GSO # self.vapi.feature_gso_enable_disable(self.pg3.sw_if_index) p41 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 100 * [p41], self.pg3, 100) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg3.remote_ip4) self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # ipv6 # p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 100 * [p61], self.pg3, 100) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6) self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # Send jumbo frame with gso enabled only on input interface # and DF bit is set. GSO packet will be chunked into gso_size # data payload # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) p42 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p42], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # ipv6 # p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p62], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # Send jumbo frame with gso enabled only on input interface # and DF bit is unset. GSO packet will be fragmented. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index) p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p43], self.pg1, 5 * 119) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assert_ip_checksum_valid(rx) size += rx[IP].len - 20 size -= 20 * 5 # TCP header self.assertEqual(size, 65200 * 5) # # IPv6 # Send jumbo frame with gso enabled only on input interface. # ICMPv6 Packet Too Big will be sent back to sender. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p63], self.pg2, 5) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6") self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280) self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6) self.assertEqual(rx[IPerror6].plen - 20, 65200) # # Send jumbo frame with gso enabled only on input interface with 9K MTU # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0]) p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg4, 5 * [p44], self.pg1, 165) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg4.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv6 # p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg4, 5 * [p64], self.pg1, 170) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0) self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index, enable_disable=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__(str(icmp4_reply)) s = str(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(str(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 = reassemble(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 = reassemble(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 = 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( ip_sw_if_index=self.pg0.sw_if_index, 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) # 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)