Пример #1
0
 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
Пример #2
0
    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])
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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])
Пример #6
0
    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()
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
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)
Пример #10
0
    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)
Пример #11
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)
Пример #12
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)
Пример #13
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
Пример #14
0
    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)
Пример #15
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)
Пример #16
0
    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()
Пример #17
0
    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)
Пример #18
0
    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)
Пример #19
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])
Пример #20
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)