示例#1
0
    def test_qos_mpls(self):
        """ QoS Mark/Record MPLS """

        #
        # 255 QoS for all input values
        #
        from_ext = 7
        from_ip = 6
        from_mpls = 5
        from_vlan = 4
        output = [scapy.compat.chb(from_ext)] * 256
        os1 = b''.join(output)
        output = [scapy.compat.chb(from_vlan)] * 256
        os2 = b''.join(output)
        output = [scapy.compat.chb(from_mpls)] * 256
        os3 = b''.join(output)
        output = [scapy.compat.chb(from_ip)] * 256
        os4 = b''.join(output)
        rows = [{'outputs': os1},
                {'outputs': os2},
                {'outputs': os3},
                {'outputs': os4}]

        self.vapi.qos_egress_map_update(1, rows)

        #
        # a route with 1 MPLS label
        #
        route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
                                    [VppRoutePath(self.pg1.remote_ip4,
                                                  self.pg1.sw_if_index,
                                                  labels=[32])])
        route_10_0_0_1.add_vpp_config()

        #
        # a route with 3 MPLS labels
        #
        route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
                                    [VppRoutePath(self.pg1.remote_ip4,
                                                  self.pg1.sw_if_index,
                                                  labels=[63, 33, 34])])
        route_10_0_0_3.add_vpp_config()

        #
        # enable IP QoS recording on the input Pg0 and MPLS egress marking
        # on Pg1
        #
        self.vapi.qos_record_enable_disable(self.pg0.sw_if_index,
                                            self.QOS_SOURCE.QOS_API_SOURCE_IP,
                                            1)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          self.QOS_SOURCE.QOS_API_SOURCE_MPLS,
                                          1,
                                          1)

        #
        # packet that will get one label added and 3 labels added resp.
        #
        p_1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
               IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) /
               UDP(sport=1234, dport=1234) /
               Raw(scapy.compat.chb(100) * NUM_PKTS))
        p_3 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
               IP(src=self.pg0.remote_ip4, dst="10.0.0.3", tos=1) /
               UDP(sport=1234, dport=1234) /
               Raw(scapy.compat.chb(100) * NUM_PKTS))

        rx = self.send_and_expect(self.pg0, p_1 * NUM_PKTS, self.pg1)

        #
        # only 3 bits of ToS value in MPLS make sure tos is correct
        # and the label and EOS bit have not been corrupted
        #
        for p in rx:
            self.assertEqual(p[MPLS].cos, from_ip)
            self.assertEqual(p[MPLS].label, 32)
            self.assertEqual(p[MPLS].s, 1)
        rx = self.send_and_expect(self.pg0, p_3 * NUM_PKTS, self.pg1)
        for p in rx:
            self.assertEqual(p[MPLS].cos, from_ip)
            self.assertEqual(p[MPLS].label, 63)
            self.assertEqual(p[MPLS].s, 0)
            h = p[MPLS].payload
            self.assertEqual(h[MPLS].cos, from_ip)
            self.assertEqual(h[MPLS].label, 33)
            self.assertEqual(h[MPLS].s, 0)
            h = h[MPLS].payload
            self.assertEqual(h[MPLS].cos, from_ip)
            self.assertEqual(h[MPLS].label, 34)
            self.assertEqual(h[MPLS].s, 1)

        #
        # enable MPLS QoS recording on the input Pg0 and IP egress marking
        # on Pg1
        #
        self.vapi.qos_record_enable_disable(
            self.pg0.sw_if_index,
            self.QOS_SOURCE.QOS_API_SOURCE_MPLS,
            1)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          self.QOS_SOURCE.QOS_API_SOURCE_IP,
                                          1,
                                          1)

        #
        # MPLS x-connect - COS according to pg1 map
        #
        route_32_eos = VppMplsRoute(self, 32, 1,
                                    [VppRoutePath(self.pg1.remote_ip4,
                                                  self.pg1.sw_if_index,
                                                  labels=[VppMplsLabel(33)])])
        route_32_eos.add_vpp_config()

        p_m1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                MPLS(label=32, cos=3, ttl=2) /
                IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) /
                UDP(sport=1234, dport=1234) /
                Raw(scapy.compat.chb(100) * NUM_PKTS))

        rx = self.send_and_expect(self.pg0, p_m1 * NUM_PKTS, self.pg1)
        for p in rx:
            self.assertEqual(p[MPLS].cos, from_mpls)
            self.assertEqual(p[MPLS].label, 33)
            self.assertEqual(p[MPLS].s, 1)

        #
        # MPLS deag - COS is copied from MPLS to IP
        #
        route_33_eos = VppMplsRoute(self, 33, 1,
                                    [VppRoutePath("0.0.0.0",
                                                  0xffffffff,
                                                  nh_table_id=0)])
        route_33_eos.add_vpp_config()

        route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
                                    [VppRoutePath(self.pg1.remote_ip4,
                                                  self.pg1.sw_if_index)])
        route_10_0_0_4.add_vpp_config()

        p_m2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                MPLS(label=33, ttl=2, cos=3) /
                IP(src=self.pg0.remote_ip4, dst="10.0.0.4", tos=1) /
                UDP(sport=1234, dport=1234) /
                Raw(scapy.compat.chb(100) * NUM_PKTS))

        rx = self.send_and_expect(self.pg0, p_m2 * NUM_PKTS, self.pg1)

        for p in rx:
            self.assertEqual(p[IP].tos, from_mpls)

        #
        # cleanup
        #
        self.vapi.qos_record_enable_disable(self.pg0.sw_if_index,
                                            self.QOS_SOURCE.QOS_API_SOURCE_IP,
                                            0)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          self.QOS_SOURCE.QOS_API_SOURCE_MPLS,
                                          1,
                                          0)
        self.vapi.qos_record_enable_disable(
            self.pg0.sw_if_index,
            self.QOS_SOURCE.QOS_API_SOURCE_MPLS,
            0)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          self.QOS_SOURCE.QOS_API_SOURCE_IP,
                                          1,
                                          0)
        self.vapi.qos_egress_map_delete(1)
示例#2
0
    def test_udp_encap(self):
        """ UDP Encap test
        """

        #
        # construct a UDP encap object through each of the peers
        # v4 through the first two peears, v6 through the second.
        #
        udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4,
                                  self.pg0.remote_ip4, 330, 440)
        udp_encap_1 = VppUdpEncap(self,
                                  self.pg1.local_ip4,
                                  self.pg1.remote_ip4,
                                  331,
                                  441,
                                  table_id=1)
        udp_encap_2 = VppUdpEncap(self,
                                  self.pg2.local_ip6,
                                  self.pg2.remote_ip6,
                                  332,
                                  442,
                                  table_id=2)
        udp_encap_3 = VppUdpEncap(self,
                                  self.pg3.local_ip6,
                                  self.pg3.remote_ip6,
                                  333,
                                  443,
                                  table_id=3)
        udp_encap_0.add_vpp_config()
        udp_encap_1.add_vpp_config()
        udp_encap_2.add_vpp_config()
        udp_encap_3.add_vpp_config()

        self.logger.info(self.vapi.cli("sh udp encap"))

        self.assertTrue(find_udp_encap(self, udp_encap_2))
        self.assertTrue(find_udp_encap(self, udp_encap_3))
        self.assertTrue(find_udp_encap(self, udp_encap_0))
        self.assertTrue(find_udp_encap(self, udp_encap_1))

        #
        # Routes via each UDP encap object - all combinations of v4 and v6.
        #
        route_4o4 = VppIpRoute(self, "1.1.0.1", 32, [
            VppRoutePath("0.0.0.0",
                         0xFFFFFFFF,
                         is_udp_encap=1,
                         next_hop_id=udp_encap_0.id)
        ])
        route_4o6 = VppIpRoute(self, "1.1.2.1", 32, [
            VppRoutePath("0.0.0.0",
                         0xFFFFFFFF,
                         is_udp_encap=1,
                         next_hop_id=udp_encap_2.id)
        ])
        route_6o4 = VppIpRoute(self,
                               "2001::1",
                               128, [
                                   VppRoutePath("0.0.0.0",
                                                0xFFFFFFFF,
                                                is_udp_encap=1,
                                                next_hop_id=udp_encap_1.id)
                               ],
                               is_ip6=1)
        route_6o6 = VppIpRoute(self,
                               "2001::3",
                               128, [
                                   VppRoutePath("0.0.0.0",
                                                0xFFFFFFFF,
                                                is_udp_encap=1,
                                                next_hop_id=udp_encap_3.id)
                               ],
                               is_ip6=1)
        route_4o4.add_vpp_config()
        route_4o6.add_vpp_config()
        route_6o6.add_vpp_config()
        route_6o4.add_vpp_config()

        #
        # 4o4 encap
        #
        p_4o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IP(src="2.2.2.2", dst="1.1.0.1") /
                 UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        rx = self.send_and_expect(self.pg0, p_4o4 * 65, self.pg0)
        for p in rx:
            self.validate_outer4(p, udp_encap_0)
            p = IP(p["UDP"].payload.load)
            self.validate_inner4(p, p_4o4)
        self.assertEqual(udp_encap_0.get_stats()['packets'], 65)

        #
        # 4o6 encap
        #
        p_4o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IP(src="2.2.2.2", dst="1.1.2.1") /
                 UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        rx = self.send_and_expect(self.pg0, p_4o6 * 65, self.pg2)
        for p in rx:
            self.validate_outer6(p, udp_encap_2)
            p = IP(p["UDP"].payload.load)
            self.validate_inner4(p, p_4o6)
        self.assertEqual(udp_encap_2.get_stats()['packets'], 65)

        #
        # 6o4 encap
        #
        p_6o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src="2001::100", dst="2001::1") /
                 UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        rx = self.send_and_expect(self.pg0, p_6o4 * 65, self.pg1)
        for p in rx:
            self.validate_outer4(p, udp_encap_1)
            p = IPv6(p["UDP"].payload.load)
            self.validate_inner6(p, p_6o4)
        self.assertEqual(udp_encap_1.get_stats()['packets'], 65)

        #
        # 6o6 encap
        #
        p_6o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src="2001::100", dst="2001::3") /
                 UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        rx = self.send_and_expect(self.pg0, p_6o6 * 65, self.pg3)
        for p in rx:
            self.validate_outer6(p, udp_encap_3)
            p = IPv6(p["UDP"].payload.load)
            self.validate_inner6(p, p_6o6)
        self.assertEqual(udp_encap_3.get_stats()['packets'], 65)

        #
        # A route with an output label
        # the TTL of the inner packet is decremented on LSP ingress
        #
        route_4oMPLSo4 = VppIpRoute(self, "1.1.2.22", 32, [
            VppRoutePath("0.0.0.0",
                         0xFFFFFFFF,
                         is_udp_encap=1,
                         next_hop_id=1,
                         labels=[VppMplsLabel(66)])
        ])
        route_4oMPLSo4.add_vpp_config()

        p_4omo4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                   IP(src="2.2.2.2", dst="1.1.2.22") /
                   UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        rx = self.send_and_expect(self.pg0, p_4omo4 * 65, self.pg1)
        for p in rx:
            self.validate_outer4(p, udp_encap_1)
            p = MPLS(p["UDP"].payload.load)
            self.validate_inner4(p, p_4omo4, ttl=63)
        self.assertEqual(udp_encap_1.get_stats()['packets'], 130)
示例#3
0
    def test_sr_mpls(self):
        """ SR MPLS """

        #
        # A simple MPLS xconnect - neos label in label out
        #
        route_32_eos = VppMplsRoute(self, 32, 0, [
            VppRoutePath(self.pg0.remote_ip4,
                         self.pg0.sw_if_index,
                         labels=[VppMplsLabel(32)])
        ])
        route_32_eos.add_vpp_config()

        #
        # A binding SID with only one label
        #
        self.vapi.sr_mpls_policy_add(999, 1, 0, [32])

        #
        # A labeled IP route that resolves thru the binding SID
        #
        ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, [
            VppRoutePath("0.0.0.0",
                         0xffffffff,
                         nh_via_label=999,
                         labels=[VppMplsLabel(55)])
        ])
        ip_10_0_0_1.add_vpp_config()

        tx = self.create_stream_ip4(self.pg1, "10.0.0.1")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_labelled_ip4(
            self.pg0, rx, tx,
            [VppMplsLabel(32), VppMplsLabel(55)])

        #
        # An unlabeled IP route that resolves thru the binding SID
        #
        ip_10_0_0_1 = VppIpRoute(
            self, "10.0.0.2", 32,
            [VppRoutePath("0.0.0.0", 0xffffffff, nh_via_label=999)])
        ip_10_0_0_1.add_vpp_config()

        tx = self.create_stream_ip4(self.pg1, "10.0.0.2")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_labelled_ip4(self.pg0, rx, tx, [VppMplsLabel(32)])

        self.vapi.sr_mpls_policy_del(999)

        #
        # this time the SID has many labels pushed
        #
        self.vapi.sr_mpls_policy_add(999, 1, 0, [32, 33, 34])

        tx = self.create_stream_ip4(self.pg1, "10.0.0.1")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_labelled_ip4(self.pg0, rx, tx, [
            VppMplsLabel(32),
            VppMplsLabel(33),
            VppMplsLabel(34),
            VppMplsLabel(55)
        ])
        tx = self.create_stream_ip4(self.pg1, "10.0.0.2")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_labelled_ip4(
            self.pg0, rx, tx,
            [VppMplsLabel(32),
             VppMplsLabel(33),
             VppMplsLabel(34)])

        #
        # Resolve an MPLS tunnel via the SID
        #
        mpls_tun = VppMPLSTunnelInterface(self, [
            VppRoutePath("0.0.0.0",
                         0xffffffff,
                         nh_via_label=999,
                         labels=[VppMplsLabel(44),
                                 VppMplsLabel(46)])
        ])
        mpls_tun.add_vpp_config()
        mpls_tun.admin_up()

        #
        # add an unlabelled route through the new tunnel
        #
        route_10_0_0_3 = VppIpRoute(
            self, "10.0.0.3", 32,
            [VppRoutePath("0.0.0.0", mpls_tun._sw_if_index)])
        route_10_0_0_3.add_vpp_config()
        self.logger.info(self.vapi.cli("sh mpls tun 0"))
        self.logger.info(self.vapi.cli("sh adj 21"))

        tx = self.create_stream_ip4(self.pg1, "10.0.0.3")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [
            VppMplsLabel(32),
            VppMplsLabel(33),
            VppMplsLabel(34),
            VppMplsLabel(44),
            VppMplsLabel(46)
        ])

        #
        # add a labelled route through the new tunnel
        #
        route_10_0_0_3 = VppIpRoute(self, "10.0.0.4", 32, [
            VppRoutePath(
                "0.0.0.0", mpls_tun._sw_if_index, labels=[VppMplsLabel(55)])
        ])
        route_10_0_0_3.add_vpp_config()

        tx = self.create_stream_ip4(self.pg1, "10.0.0.4")
        rx = self.send_and_expect(self.pg1, tx, self.pg0)
        self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [
            VppMplsLabel(32),
            VppMplsLabel(33),
            VppMplsLabel(34),
            VppMplsLabel(44),
            VppMplsLabel(46),
            VppMplsLabel(55)
        ])

        self.vapi.sr_mpls_policy_del(999)
示例#4
0
    def bier_midpoint(self, hdr_len_id, n_bytes, max_bp):
        """BIER midpoint"""

        #
        # Add a BIER table for sub-domain 0, set 0, and BSL 256
        #
        bti = VppBierTableID(0, 0, hdr_len_id)
        bt = VppBierTable(self, bti, 77)
        bt.add_vpp_config()

        #
        # A packet with no bits set gets dropped
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             MPLS(label=77, ttl=255) / BIER(length=hdr_len_id) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
             UDP(sport=1234, dport=1234) / Raw())
        pkts = [p]

        self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String")

        #
        # Add a BIER route for each bit-position in the table via a different
        # next-hop. Testing whether the BIER walk and replicate forwarding
        # function works for all bit posisitons.
        #
        nh_routes = []
        bier_routes = []
        for i in range(1, max_bp + 1):
            nh = "10.0.%d.%d" % (i / 255, i % 255)
            nh_routes.append(
                VppIpRoute(self, nh, 32, [
                    VppRoutePath(self.pg1.remote_ip4,
                                 self.pg1.sw_if_index,
                                 labels=[VppMplsLabel(2000 + i)])
                ]))
            nh_routes[-1].add_vpp_config()

            bier_routes.append(
                VppBierRoute(self, bti, i, [
                    VppRoutePath(
                        nh, 0xffffffff, labels=[VppMplsLabel(100 + i)])
                ]))
            bier_routes[-1].add_vpp_config()

        #
        # A packet with all bits set gets replicated once for each bit
        #
        pkt_sizes = [64, 1400]

        for pkt_size in pkt_sizes:
            p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                 MPLS(label=77, ttl=255) /
                 BIER(length=hdr_len_id,
                      BitString=scapy.compat.chb(255) * n_bytes) /
                 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
                 UDP(sport=1234, dport=1234) /
                 Raw(scapy.compat.chb(5) * pkt_size))
            pkts = p

            self.pg0.add_stream(pkts)
            self.pg_enable_capture(self.pg_interfaces)
            self.pg_start()

            rx = self.pg1.get_capture(max_bp)

            for rxp in rx:
                #
                # The packets are not required to be sent in bit-position order
                # when we setup the routes above we used the bit-position to
                # construct the out-label. so use that here to determine the BP
                #
                olabel = rxp[MPLS]
                bp = olabel.label - 2000

                blabel = olabel[MPLS].payload
                self.assertEqual(blabel.label, 100 + bp)
                self.assertEqual(blabel.ttl, 254)

                bier_hdr = blabel[MPLS].payload

                self.assertEqual(bier_hdr.id, 5)
                self.assertEqual(bier_hdr.version, 0)
                self.assertEqual(bier_hdr.length, hdr_len_id)
                self.assertEqual(bier_hdr.entropy, 0)
                self.assertEqual(bier_hdr.OAM, 0)
                self.assertEqual(bier_hdr.RSV, 0)
                self.assertEqual(bier_hdr.DSCP, 0)
                self.assertEqual(bier_hdr.Proto, 5)

                # The bit-string should consist only of the BP given by i.
                byte_array = [b'\0'] * (n_bytes)
                byte_val = scapy.compat.chb(1 << (bp - 1) % 8)
                byte_pos = n_bytes - (((bp - 1) // 8) + 1)
                byte_array[byte_pos] = byte_val
                bitstring = ''.join([scapy.compat.chb(x) for x in byte_array])

                self.assertEqual(len(bitstring), len(bier_hdr.BitString))
                self.assertEqual(bitstring, bier_hdr.BitString)

        #
        # cleanup. not strictly necessary, but it's much quicker this way
        # because the bier_fib_dump and ip_fib_dump will be empty when the
        # auto-cleanup kicks in
        #
        for br in bier_routes:
            br.remove_vpp_config()
        for nhr in nh_routes:
            nhr.remove_vpp_config()
示例#5
0
    def test_bier_head_o_udp(self):
        """BIER head over UDP"""

        #
        # Add a BIER table for sub-domain 1, set 0, and BSL 256
        #
        bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256)
        bt = VppBierTable(self, bti, 77)
        bt.add_vpp_config()

        #
        # 1 bit positions via 1 next hops
        #
        nh1 = "10.0.0.1"
        ip_route = VppIpRoute(self, nh1, 32, [
            VppRoutePath(self.pg1.remote_ip4,
                         self.pg1.sw_if_index,
                         labels=[VppMplsLabel(2001)])
        ])
        ip_route.add_vpp_config()

        udp_encap = VppUdpEncap(self, self.pg0.local_ip4, nh1, 330, 8138)
        udp_encap.add_vpp_config()

        bier_route = VppBierRoute(self, bti, 1, [
            VppRoutePath("0.0.0.0",
                         0xFFFFFFFF,
                         type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                         next_hop_id=udp_encap.id)
        ])
        bier_route.add_vpp_config()

        #
        # An 2 imposition objects with all bit-positions set
        # only use the second, but creating 2 tests with a non-zero
        # value index in the route add
        #
        bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32)
        bi.add_vpp_config()
        bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32)
        bi2.add_vpp_config()

        #
        # Add a multicast route that will forward into the BIER doamin
        #
        route_ing_232_1_1_1 = VppIpMRoute(
            self,
            "0.0.0.0",
            "232.1.1.1",
            32,
            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
            paths=[
                VppMRoutePath(self.pg0.sw_if_index,
                              MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
                VppMRoutePath(0xffffffff,
                              MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
                              proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
                              type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
                              bier_imp=bi2.bi_index)
            ])
        route_ing_232_1_1_1.add_vpp_config()

        #
        # inject a packet an IP. We expect it to be BIER and UDP encapped,
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234))

        self.pg0.add_stream([p])
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        #
        # Encap Stack is, eth, IP, UDP, BIFT, BIER
        #
        self.assertEqual(rx[0][IP].src, self.pg0.local_ip4)
        self.assertEqual(rx[0][IP].dst, nh1)
        self.assertEqual(rx[0][UDP].sport, 330)
        self.assertEqual(rx[0][UDP].dport, 8138)
        self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256)
        self.assertEqual(rx[0][BIFT].sd, 1)
        self.assertEqual(rx[0][BIFT].set, 0)
        self.assertEqual(rx[0][BIFT].ttl, 64)
        self.assertEqual(rx[0][BIER].length, 2)
示例#6
0
    def test_bier_head(self):
        """BIER head"""

        #
        # Add a BIER table for sub-domain 0, set 0, and BSL 256
        #
        bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256)
        bt = VppBierTable(self, bti, 77)
        bt.add_vpp_config()

        #
        # 2 bit positions via two next hops
        #
        nh1 = "10.0.0.1"
        nh2 = "10.0.0.2"
        ip_route_1 = VppIpRoute(self, nh1, 32, [
            VppRoutePath(self.pg1.remote_ip4,
                         self.pg1.sw_if_index,
                         labels=[VppMplsLabel(2001)])
        ])
        ip_route_2 = VppIpRoute(self, nh2, 32, [
            VppRoutePath(self.pg1.remote_ip4,
                         self.pg1.sw_if_index,
                         labels=[VppMplsLabel(2002)])
        ])
        ip_route_1.add_vpp_config()
        ip_route_2.add_vpp_config()

        bier_route_1 = VppBierRoute(
            self, bti, 1,
            [VppRoutePath(nh1, 0xffffffff, labels=[VppMplsLabel(101)])])
        bier_route_2 = VppBierRoute(
            self, bti, 2,
            [VppRoutePath(nh2, 0xffffffff, labels=[VppMplsLabel(102)])])
        bier_route_1.add_vpp_config()
        bier_route_2.add_vpp_config()

        #
        # An imposition object with both bit-positions set
        #
        bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32)
        bi.add_vpp_config()

        #
        # Add a multicast route that will forward into the BIER doamin
        #
        route_ing_232_1_1_1 = VppIpMRoute(
            self,
            "0.0.0.0",
            "232.1.1.1",
            32,
            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
            paths=[
                VppMRoutePath(self.pg0.sw_if_index,
                              MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
                VppMRoutePath(0xffffffff,
                              MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
                              proto=FibPathProto.FIB_PATH_NH_PROTO_BIER,
                              type=FibPathType.FIB_PATH_TYPE_BIER_IMP,
                              bier_imp=bi.bi_index)
            ])
        route_ing_232_1_1_1.add_vpp_config()

        #
        # inject an IP packet. We expect it to be BIER encapped and
        # replicated.
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234))

        self.pg0.add_stream([p])
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(2)

        #
        # Encap Stack is; eth, MPLS, MPLS, BIER
        #
        igp_mpls = rx[0][MPLS]
        self.assertEqual(igp_mpls.label, 2001)
        self.assertEqual(igp_mpls.ttl, 64)
        self.assertEqual(igp_mpls.s, 0)
        bier_mpls = igp_mpls[MPLS].payload
        self.assertEqual(bier_mpls.label, 101)
        self.assertEqual(bier_mpls.ttl, 64)
        self.assertEqual(bier_mpls.s, 1)
        self.assertEqual(rx[0][BIER].length, 2)

        igp_mpls = rx[1][MPLS]
        self.assertEqual(igp_mpls.label, 2002)
        self.assertEqual(igp_mpls.ttl, 64)
        self.assertEqual(igp_mpls.s, 0)
        bier_mpls = igp_mpls[MPLS].payload
        self.assertEqual(bier_mpls.label, 102)
        self.assertEqual(bier_mpls.ttl, 64)
        self.assertEqual(bier_mpls.s, 1)
        self.assertEqual(rx[0][BIER].length, 2)
示例#7
0
    def test_bier_load_balance(self):
        """BIER load-balance"""

        #
        # Add a BIER table for sub-domain 0, set 0, and BSL 256
        #
        bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64)
        bt = VppBierTable(self, bti, 77)
        bt.add_vpp_config()

        #
        # packets with varying entropy
        #
        pkts = []
        for ii in range(257):
            pkts.append(
                (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                 MPLS(label=77, ttl=255) /
                 BIER(length=BIERLength.BIER_LEN_64,
                      entropy=ii,
                      BitString=scapy.compat.chb(255) * 16) /
                 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
                 UDP(sport=1234, dport=1234) / Raw()))

        #
        # 4 next hops
        #
        nhs = [{
            'ip': "10.0.0.1",
            'label': 201
        }, {
            'ip': "10.0.0.2",
            'label': 202
        }, {
            'ip': "10.0.0.3",
            'label': 203
        }, {
            'ip': "10.0.0.4",
            'label': 204
        }]

        for nh in nhs:
            ipr = VppIpRoute(self, nh['ip'], 32, [
                VppRoutePath(self.pg1.remote_ip4,
                             self.pg1.sw_if_index,
                             labels=[VppMplsLabel(nh['label'])])
            ])
            ipr.add_vpp_config()

        bier_route = VppBierRoute(self, bti, 1, [
            VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]),
            VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])
        ])
        bier_route.add_vpp_config()

        rx = self.send_and_expect(self.pg0, pkts, self.pg1)

        #
        # we should have recieved a packet from each neighbor
        #
        for nh in nhs[:2]:
            self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))

        #
        # add the other paths
        #
        bier_route.update_paths([
            VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]),
            VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]),
            VppRoutePath(nhs[2]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]),
            VppRoutePath(nhs[3]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])
        ])

        rx = self.send_and_expect(self.pg0, pkts, self.pg1)

        for nh in nhs:
            self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))

        #
        # remove first two paths
        #
        bier_route.remove_path(
            VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]))
        bier_route.remove_path(
            VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]))

        rx = self.send_and_expect(self.pg0, pkts, self.pg1)
        for nh in nhs[2:]:
            self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx))

        #
        # remove the last of the paths, deleteing the entry
        #
        bier_route.remove_all_paths()

        self.send_and_assert_no_replies(self.pg0, pkts)
示例#8
0
文件: test_ipip.py 项目: zzqcn/vpp
    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()
示例#9
0
文件: test_gre.py 项目: zxt2012bs/vpp
    def test_gre(self):
        """ GRE IPv4 tunnel Tests """

        #
        # Create an L3 GRE tunnel.
        #  - set it admin up
        #  - assign an IP Addres
        #  - Add a route via the tunnel
        #
        gre_if = VppGreInterface(self,
                                 self.pg0.local_ip4,
                                 "1.1.1.2")
        gre_if.add_vpp_config()

        #
        # The double create (create the same tunnel twice) should fail,
        # and we should still be able to use the original
        #
        try:
            gre_if.add_vpp_config()
        except Exception:
            pass
        else:
            self.fail("Double GRE tunnel add does not fail")

        gre_if.admin_up()
        gre_if.config_ip4()

        route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
                                   [VppRoutePath("0.0.0.0",
                                                 gre_if.sw_if_index)])

        route_via_tun.add_vpp_config()

        #
        # Send a packet stream that is routed into the tunnel
        #  - they are all dropped since the tunnel's destintation IP
        #    is unresolved - or resolves via the default route - which
        #    which is a drop.
        #
        tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")

        self.send_and_assert_no_replies(self.pg0, tx)

        #
        # Add a route that resolves the tunnel's destination
        #
        route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
                                   [VppRoutePath(self.pg0.remote_ip4,
                                                 self.pg0.sw_if_index)])
        route_tun_dst.add_vpp_config()

        #
        # Send a packet stream that is routed into the tunnel
        #  - packets are GRE encapped
        #
        tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
        rx = self.send_and_expect(self.pg0, tx, self.pg0)
        self.verify_tunneled_4o4(self.pg0, rx, tx,
                                 self.pg0.local_ip4, "1.1.1.2")

        #
        # Send tunneled packets that match the created tunnel and
        # are decapped and forwarded
        #
        tx = self.create_tunnel_stream_4o4(self.pg0,
                                           "1.1.1.2",
                                           self.pg0.local_ip4,
                                           self.pg0.local_ip4,
                                           self.pg0.remote_ip4)
        rx = self.send_and_expect(self.pg0, tx, self.pg0)
        self.verify_decapped_4o4(self.pg0, rx, tx)

        #
        # Send tunneled packets that do not match the tunnel's src
        #
        self.vapi.cli("clear trace")
        tx = self.create_tunnel_stream_4o4(self.pg0,
                                           "1.1.1.3",
                                           self.pg0.local_ip4,
                                           self.pg0.local_ip4,
                                           self.pg0.remote_ip4)
        self.send_and_assert_no_replies(
            self.pg0, tx,
            remark="GRE packets forwarded despite no SRC address match")

        #
        # Configure IPv6 on the PG interface so we can route IPv6
        # packets
        #
        self.pg0.config_ip6()
        self.pg0.resolve_ndp()

        #
        # Send IPv6 tunnel encapslated packets
        #  - dropped since IPv6 is not enabled on the tunnel
        #
        tx = self.create_tunnel_stream_6o4(self.pg0,
                                           "1.1.1.2",
                                           self.pg0.local_ip4,
                                           self.pg0.local_ip6,
                                           self.pg0.remote_ip6)
        self.send_and_assert_no_replies(self.pg0, tx,
                                        "IPv6 GRE packets forwarded "
                                        "despite IPv6 not enabled on tunnel")

        #
        # Enable IPv6 on the tunnel
        #
        gre_if.config_ip6()

        #
        # Send IPv6 tunnel encapslated packets
        #  - forwarded since IPv6 is enabled on the tunnel
        #
        tx = self.create_tunnel_stream_6o4(self.pg0,
                                           "1.1.1.2",
                                           self.pg0.local_ip4,
                                           self.pg0.local_ip6,
                                           self.pg0.remote_ip6)
        rx = self.send_and_expect(self.pg0, tx, self.pg0)
        self.verify_decapped_6o4(self.pg0, rx, tx)

        #
        # Send v6 packets for v4 encap
        #
        route6_via_tun = VppIpRoute(
            self, "2001::1", 128,
            [VppRoutePath("::",
                          gre_if.sw_if_index,
                          proto=DpoProto.DPO_PROTO_IP6)])
        route6_via_tun.add_vpp_config()

        tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
        rx = self.send_and_expect(self.pg0, tx, self.pg0)

        self.verify_tunneled_6o4(self.pg0, rx, tx,
                                 self.pg0.local_ip4, "1.1.1.2")

        #
        # add a labelled route through the tunnel
        #
        label_via_tun = VppIpRoute(self, "5.4.3.2", 32,
                                   [VppRoutePath("0.0.0.0",
                                                 gre_if.sw_if_index,
                                                 labels=[VppMplsLabel(33)])])
        label_via_tun.add_vpp_config()

        tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.2")
        rx = self.send_and_expect(self.pg0, tx, self.pg0)
        self.verify_tunneled_4o4(self.pg0, rx, tx,
                                 self.pg0.local_ip4, "1.1.1.2")

        #
        # an MPLS tunnel over the GRE tunnel add a route through
        # the mpls tunnel
        #
        mpls_tun = VppMPLSTunnelInterface(
            self,
            [VppRoutePath("0.0.0.0",
                          gre_if.sw_if_index,
                          labels=[VppMplsLabel(44),
                                  VppMplsLabel(46)])])
        mpls_tun.add_vpp_config()
        mpls_tun.admin_up()

        label_via_mpls = VppIpRoute(self, "5.4.3.1", 32,
                                    [VppRoutePath("0.0.0.0",
                                                  mpls_tun.sw_if_index,
                                                  labels=[VppMplsLabel(33)])])
        label_via_mpls.add_vpp_config()

        tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.1")
        rx = self.send_and_expect(self.pg0, tx, self.pg0)
        self.verify_tunneled_4o4(self.pg0, rx, tx,
                                 self.pg0.local_ip4, "1.1.1.2")

        mpls_tun_l2 = VppMPLSTunnelInterface(
            self,
            [VppRoutePath("0.0.0.0",
                          gre_if.sw_if_index,
                          labels=[VppMplsLabel(44),
                                  VppMplsLabel(46)])],
            is_l2=1)
        mpls_tun_l2.add_vpp_config()
        mpls_tun_l2.admin_up()

        #
        # test case cleanup
        #
        route_tun_dst.remove_vpp_config()
        route_via_tun.remove_vpp_config()
        route6_via_tun.remove_vpp_config()
        label_via_mpls.remove_vpp_config()
        label_via_tun.remove_vpp_config()
        mpls_tun.remove_vpp_config()
        mpls_tun_l2.remove_vpp_config()
        gre_if.remove_vpp_config()

        self.pg0.unconfig_ip6()
示例#10
0
    def test_udp_encap(self):
        """UDP Encap test"""

        #
        # construct a UDP encap object through each of the peers
        # v4 through the first two peers, v6 through the second.
        # The last encap is v4 and is used to check the codepath
        # where 2 different udp encap objects are processed at the
        # same time
        #
        udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4,
                                  self.pg0.remote_ip4, 330, 440)
        udp_encap_1 = VppUdpEncap(self,
                                  self.pg1.local_ip4,
                                  self.pg1.remote_ip4,
                                  331,
                                  441,
                                  table_id=1)
        udp_encap_2 = VppUdpEncap(self,
                                  self.pg2.local_ip6,
                                  self.pg2.remote_ip6,
                                  332,
                                  442,
                                  table_id=2)
        udp_encap_3 = VppUdpEncap(self,
                                  self.pg3.local_ip6,
                                  self.pg3.remote_ip6,
                                  333,
                                  443,
                                  table_id=3)
        udp_encap_4 = VppUdpEncap(self, self.pg0.local_ip4,
                                  self.pg0.remote_ip4, 334, 444)
        udp_encap_0.add_vpp_config()
        udp_encap_1.add_vpp_config()
        udp_encap_2.add_vpp_config()
        udp_encap_3.add_vpp_config()
        udp_encap_4.add_vpp_config()

        self.logger.info(self.vapi.cli("sh udp encap"))

        self.assertTrue(find_udp_encap(self, udp_encap_2))
        self.assertTrue(find_udp_encap(self, udp_encap_3))
        self.assertTrue(find_udp_encap(self, udp_encap_0))
        self.assertTrue(find_udp_encap(self, udp_encap_1))
        self.assertTrue(find_udp_encap(self, udp_encap_4))

        #
        # Routes via each UDP encap object - all combinations of v4 and v6.
        #
        route_4o4 = VppIpRoute(
            self,
            "1.1.0.1",
            24,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=udp_encap_0.id,
                    proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
                )
            ],
            table_id=1,
        )
        # specific route to match encap4, to test encap of 2 packets using 2
        # different encap
        route_4o4_2 = VppIpRoute(
            self,
            "1.1.0.2",
            32,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=udp_encap_4.id,
                    proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
                )
            ],
            table_id=1,
        )
        route_4o6 = VppIpRoute(
            self,
            "1.1.2.1",
            32,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=udp_encap_2.id,
                    proto=FibPathProto.FIB_PATH_NH_PROTO_IP4,
                )
            ],
        )
        route_6o4 = VppIpRoute(
            self,
            "2001::1",
            128,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=udp_encap_1.id,
                    proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
                )
            ],
        )
        route_6o6 = VppIpRoute(
            self,
            "2001::3",
            128,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=udp_encap_3.id,
                    proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
                )
            ],
        )
        route_4o6.add_vpp_config()
        route_6o6.add_vpp_config()
        route_6o4.add_vpp_config()
        route_4o4.add_vpp_config()
        route_4o4_2.add_vpp_config()

        #
        # 4o4 encap
        # we add a single packet matching the last encap at the beginning of
        # the packet vector so that we encap 2 packets with different udp
        # encap object at the same time
        #
        p_4o4 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
                 IP(src="2.2.2.2", dst="1.1.0.1") /
                 UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        p_4o4_2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
                   IP(src="2.2.2.2", dst="1.1.0.2") /
                   UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        rx = self.send_and_expect(self.pg1,
                                  p_4o4_2 * 1 + p_4o4 * (NUM_PKTS - 1),
                                  self.pg0)
        # checking encap4 magic packet
        p = rx.pop(0)
        self.validate_outer4(p, udp_encap_4)
        p = IP(p["UDP"].payload.load)
        self.validate_inner4(p, p_4o4_2)
        self.assertEqual(udp_encap_4.get_stats()["packets"], 1)
        # checking remaining packets for encap0
        for p in rx:
            self.validate_outer4(p, udp_encap_0)
            p = IP(p["UDP"].payload.load)
            self.validate_inner4(p, p_4o4)
        self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS - 1)

        #
        # 4o6 encap
        #
        p_4o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IP(src="2.2.2.2", dst="1.1.2.1") /
                 UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        rx = self.send_and_expect(self.pg0, p_4o6 * NUM_PKTS, self.pg2)
        for p in rx:
            self.validate_outer6(p, udp_encap_2)
            p = IP(p["UDP"].payload.load)
            self.validate_inner4(p, p_4o6)
        self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS)

        #
        # 6o4 encap
        #
        p_6o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src="2001::100", dst="2001::1") /
                 UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        rx = self.send_and_expect(self.pg0, p_6o4 * NUM_PKTS, self.pg1)
        for p in rx:
            self.validate_outer4(p, udp_encap_1)
            p = IPv6(p["UDP"].payload.load)
            self.validate_inner6(p, p_6o4)
        self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS)

        #
        # 6o6 encap
        #
        p_6o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src="2001::100", dst="2001::3") /
                 UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        rx = self.send_and_expect(self.pg0, p_6o6 * NUM_PKTS, self.pg3)
        for p in rx:
            self.validate_outer6(p, udp_encap_3)
            p = IPv6(p["UDP"].payload.load)
            self.validate_inner6(p, p_6o6)
        self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS)

        #
        # A route with an output label
        # the TTL of the inner packet is decremented on LSP ingress
        #
        route_4oMPLSo4 = VppIpRoute(
            self,
            "1.1.2.22",
            32,
            [
                VppRoutePath(
                    "0.0.0.0",
                    0xFFFFFFFF,
                    type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                    next_hop_id=1,
                    labels=[VppMplsLabel(66)],
                )
            ],
        )
        route_4oMPLSo4.add_vpp_config()

        p_4omo4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                   IP(src="2.2.2.2", dst="1.1.2.22") /
                   UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100))
        rx = self.send_and_expect(self.pg0, p_4omo4 * NUM_PKTS, self.pg1)
        for p in rx:
            self.validate_outer4(p, udp_encap_1)
            p = MPLS(p["UDP"].payload.load)
            self.validate_inner4(p, p_4omo4, ttl=63)
        self.assertEqual(udp_encap_1.get_stats()["packets"], 2 * NUM_PKTS)