Exemple #1
0
 def RCVD_INFORM(self,pkt):
     print"now build the DHCP ACK"
     ackinstance = DHCP_ACK()
     ack = ackinstance.p
     ack[Ether].dst = pkt[Ether].src
     ack[BOOTP].xid    = pkt[BOOTP].xid
     if pkt[BOOTP].flags == 1:
         ack[BOOTP].flags  = 1
     if self.offerip == '':
         ack[BOOTP].yiaddr = self.ippool[0]
     else:
         ack[BOOTP].yiaddr = self.offerip
     ack[BOOTP].chaddr = pkt[Ether].src
     ack[MSGTYPE].type  = 5
     ack[DHCP].options.pop(2)
     
     np = compute_pad(ack)                      #compute the number of pads
     if np == 1:
         pad      = PAD()
         pad.code = 0
         ack[DHCP].options.append(pad)
         
     else:
         raw      = Raw()
         raw.load = '\x00'*np
         #p[DHCP].options.insert(4,raw)
         ack[DHCP].options.append(raw)
         print "now show the DHCP ACK"
         ack.show2()
         print"now send the DHCP ACK"
         sendp(ack)
Exemple #2
0
 def __init__(self):
     DHCP_OFFER.__init__(self)
     self.p[DHCP].options.remove(self.leasetime)
     self.p[DHCP].options.remove(self.submask)
     self.p[DHCP].options.remove(self.router)
     self.p[DHCP].options.remove(self.dns)
     try:
          self.p[DHCP].options.remove(self.pad)
     except:
         self.p[DHCP].options.remove(self.raw)
     
     self.np = compute_pad(self.p)                      #compute the number of pads
     
     if self.np == 1:
         pad      = PAD()
         pad.code = 0
         self.p[DHCP].options.append(pad)
         
     else:
         raw      = Raw()
         raw.load = '\x00'*self.np       
         self.p[DHCP].options.append(raw)
Exemple #3
0
    def test_punt_socket_traffic_multi_ports_single_socket(self):
        """ Punt socket traffic multi ports and single socket"""

        pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
        af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
        udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
        punt_l4 = {
            'type': pt_l4,
            'punt': {
                'l4': {
                    'af': af_ip6,
                    'protocol': udp_proto,
                }
            }
        }

        #
        # create stream of packets with each port
        #
        pkts = []
        for port in self.ports:
            # choose port from port list
            pkt = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                   IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
                   UDP(sport=9876, dport=port) / Raw('\xa5' * 100))
            pkts += pkt * self.nr_packets

        #
        # no punt socket
        #
        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), 0)

        #
        # configure a punt socket
        #
        self.socket_client_create(b"%s/socket_multi" %
                                  six.ensure_binary(self.tempdir))
        for p in self.ports:
            self.vapi.punt_socket_register(
                set_port(punt_l4, p),
                b"%s/socket_multi" % six.ensure_binary(self.tempdir))
        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), len(self.ports))

        #
        # expect punt socket and no packets on pg0
        #
        self.vapi.cli("clear errors")
        self.vapi.cli("clear trace")
        self.pg0.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        # give a chance to punt socket to collect all packets
        self.sleep(1)
        self.pg0.get_capture(0)
        rx = self.socket_client_close()

        for p in self.ports:
            self.verify_udp_pkts(rx, self.nr_packets, p)
            self.vapi.punt_socket_deregister(set_port(punt_l4, p))
        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), 0)
Exemple #4
0
    def test_punt(self):
        """ Exception Path testing """

        #
        # dump the punt registered reasons
        #  search for a few we know should be there
        #
        rs = self.vapi.punt_reason_dump()

        reasons = [
            "ipsec6-no-such-tunnel", "ipsec4-no-such-tunnel",
            "ipsec4-spi-o-udp-0"
        ]

        for reason in reasons:
            found = False
            for r in rs:
                if r.reason.name == reason:
                    found = True
                    break
            self.assertTrue(found)

        #
        # Using the test CLI we will hook in a exception path to
        # send ACL deny packets out of pg0 and pg1.
        # the ACL is src,dst = 1.1.1.1,1.1.1.2
        #
        ip_1_1_1_2 = VppIpRoute(
            self, "1.1.1.2", 32,
            [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)])
        ip_1_1_1_2.add_vpp_config()
        ip_1_2 = VppIpRoute(self, "1::2", 128, [
            VppRoutePath(self.pg3.remote_ip6,
                         self.pg3.sw_if_index,
                         proto=DpoProto.DPO_PROTO_IP6)
        ])
        ip_1_2.add_vpp_config()

        p4 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
              IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))
        p6 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
              IPv6(src="1::1", dst="1::2") / UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))
        self.send_and_expect(self.pg2, p4 * 1, self.pg3)
        self.send_and_expect(self.pg2, p6 * 1, self.pg3)

        #
        # apply the punting features
        #
        self.vapi.cli("test punt pg2")

        #
        # dump the punt reasons to learn the IDs assigned
        #
        rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
        r4 = rs[0].reason.id
        rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
        r6 = rs[0].reason.id

        #
        # pkts now dropped
        #
        self.send_and_assert_no_replies(self.pg2, p4 * NUM_PKTS)
        self.send_and_assert_no_replies(self.pg2, p6 * NUM_PKTS)

        #
        # Check state:
        #  1 - node error counters
        #  2 - per-reason counters
        #    2, 3 are the index of the assigned punt reason
        #
        stats = self.statistics.get_err_counter(
            "/err/punt-dispatch/No registrations")
        self.assertEqual(stats, 2 * NUM_PKTS)

        stats = self.statistics.get_counter("/net/punt")
        self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
        self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)

        #
        # use the test CLI to test a client that punts exception
        # packets out of pg0
        #
        self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
        self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)

        rx4s = self.send_and_expect(self.pg2, p4 * NUM_PKTS, self.pg0)
        rx6s = self.send_and_expect(self.pg2, p6 * NUM_PKTS, self.pg0)

        #
        # check the packets come out IP unmodified but destined to pg0 host
        #
        for rx in rx4s:
            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
            self.assertEqual(p4[IP].dst, rx[IP].dst)
            self.assertEqual(p4[IP].ttl, rx[IP].ttl)
        for rx in rx6s:
            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)

        stats = self.statistics.get_counter("/net/punt")
        self.assertEqual(stats[0][r4]['packets'], 2 * NUM_PKTS)
        self.assertEqual(stats[0][r6]['packets'], 2 * NUM_PKTS)

        #
        # add another registration for the same reason to send packets
        # out of pg1
        #
        self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
        self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)

        self.vapi.cli("clear trace")
        self.pg2.add_stream(p4 * NUM_PKTS)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rxd = self.pg0.get_capture(NUM_PKTS)
        for rx in rxd:
            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
            self.assertEqual(p4[IP].dst, rx[IP].dst)
            self.assertEqual(p4[IP].ttl, rx[IP].ttl)
        rxd = self.pg1.get_capture(NUM_PKTS)
        for rx in rxd:
            self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg1.local_mac)
            self.assertEqual(p4[IP].dst, rx[IP].dst)
            self.assertEqual(p4[IP].ttl, rx[IP].ttl)

        self.vapi.cli("clear trace")
        self.pg2.add_stream(p6 * NUM_PKTS)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rxd = self.pg0.get_capture(NUM_PKTS)
        for rx in rxd:
            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
        rxd = self.pg1.get_capture(NUM_PKTS)
        for rx in rxd:
            self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
            self.assertEqual(rx[Ether].src, self.pg1.local_mac)
            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)

        stats = self.statistics.get_counter("/net/punt")
        self.assertEqual(stats[0][r4]['packets'], 3 * NUM_PKTS)
        self.assertEqual(stats[0][r6]['packets'], 3 * NUM_PKTS)

        self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
        self.logger.info(self.vapi.cli("show punt client"))
        self.logger.info(self.vapi.cli("show punt reason"))
        self.logger.info(self.vapi.cli("show punt stats"))
        self.logger.info(self.vapi.cli("show punt db"))
Exemple #5
0
def zero_mutable_fields(pkt, sending=False):
    """
    When using AH, all "mutable" fields must be "zeroed" before calculating
    the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields.

    @param pkt: an IP(v6) packet containing an AH layer.
                NOTE: The packet will be modified
    @param sending: if true, ipv6 routing headers will not be reordered
    """

    if pkt.haslayer(AH):
        pkt[AH].icv = chr(0) * len(pkt[AH].icv)
    else:
        raise TypeError('no AH layer found')

    if pkt.version == 4:
        # the tos field has been replaced by DSCP and ECN
        # Routers may rewrite the DS field as needed to provide a
        # desired local or end-to-end service
        pkt.tos = 0
        # an intermediate router might set the DF bit, even if the source
        # did not select it.
        pkt.flags = 0
        # changed en route as a normal course of processing by routers
        pkt.ttl = 0
        # will change if any of these other fields change
        pkt.chksum = 0

        immutable_opts = []
        for opt in pkt.options:
            if opt.option in IMMUTABLE_IPV4_OPTIONS:
                immutable_opts.append(opt)
            else:
                immutable_opts.append(Raw(chr(0) * len(opt)))
        pkt.options = immutable_opts

    else:
        # holds DSCP and ECN
        pkt.tc = 0
        # The flow label described in AHv1 was mutable, and in RFC 2460 [DH98]
        # was potentially mutable. To retain compatibility with existing AH
        # implementations, the flow label is not included in the ICV in AHv2.
        pkt.fl = 0
        # same as ttl
        pkt.hlim = 0

        next_hdr = pkt.payload

        while isinstance(
                next_hdr,
            (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)):
            if isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt)):
                for opt in next_hdr.options:
                    if opt.otype & 0x20:
                        # option data can change en-route and must be zeroed
                        opt.optdata = chr(0) * opt.optlen
            elif isinstance(next_hdr, IPv6ExtHdrRouting) and sending:
                # The sender must order the field so that it appears as it
                # will at the receiver, prior to performing the ICV computation.
                next_hdr.segleft = 0
                if next_hdr.addresses:
                    final = next_hdr.addresses.pop()
                    next_hdr.addresses.insert(0, pkt.dst)
                    pkt.dst = final
            else:
                break

            next_hdr = next_hdr.payload

    return pkt
Exemple #6
0
    def test_fif6(self):
        """ Fragments in fragments (6o6) """
        # TODO this should be ideally in setUpClass, but then we hit a bug
        # with VppIpRoute incorrectly reporting it's present when it's not
        # so we need to manually remove the vpp config, thus we cannot have
        # it shared for multiple test cases
        self.tun_ip6 = "1002::1"

        self.gre6 = VppGre6Interface(self, self.src_if.local_ip6, self.tun_ip6)
        self.gre6.add_vpp_config()
        self.gre6.admin_up()
        self.gre6.config_ip6()

        self.vapi.ip_reassembly_enable_disable(
            sw_if_index=self.gre6.sw_if_index, enable_ip6=True)

        self.route6 = VppIpRoute(self,
                                 self.tun_ip6,
                                 128, [
                                     VppRoutePath(self.src_if.remote_ip6,
                                                  self.src_if.sw_if_index,
                                                  proto=DpoProto.DPO_PROTO_IP6)
                                 ],
                                 is_ip6=1)
        self.route6.add_vpp_config()

        self.reset_packet_infos()
        for i in range(test_packet_count):
            info = self.create_packet_info(self.src_if, self.dst_if)
            payload = self.info_to_payload(info)
            # Ethernet header here is only for size calculation, thus it
            # doesn't matter how it's initialized. This is to ensure that
            # reassembled packet is not > 9000 bytes, so that it's not dropped
            p = (Ether() /
                 IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6) /
                 UDP(sport=1234, dport=5678) / Raw(payload))
            size = self.packet_sizes[(i // 2) % len(self.packet_sizes)]
            self.extend_packet(p, size, self.padding)
            info.data = p[IPv6]  # use only IPv6 part, without ethernet header

        fragments = [
            x for _, i in self._packet_infos.iteritems()
            for x in fragment_rfc8200(i.data, i.index, 400)
        ]

        encapped_fragments = \
            [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
             IPv6(src=self.tun_ip6, dst=self.src_if.local_ip6) /
                GRE() /
                p
                for p in fragments]

        fragmented_encapped_fragments = \
            [x for p in encapped_fragments for x in (
                fragment_rfc8200(
                    p,
                    2 * len(self._packet_infos) + p[IPv6ExtHdrFragment].id,
                    200)
                if IPv6ExtHdrFragment in p else [p]
            )
            ]

        self.src_if.add_stream(fragmented_encapped_fragments)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        self.src_if.assert_nothing_captured()
        packets = self.dst_if.get_capture(len(self._packet_infos))
        self.verify_capture(packets, IPv6)

        # TODO remove gre vpp config by hand until VppIpRoute gets fixed
        # so that it's query_vpp_config() works as it should
        self.gre6.remove_vpp_config()
Exemple #7
0
    def test_arp_duplicates(self):
        """ ARP Duplicates"""

        #
        # Generate some hosts on the LAN
        #
        self.pg1.generate_remote_hosts(3)

        #
        # Add host 1 on pg1 and pg2
        #
        arp_pg1 = VppNeighbor(self, self.pg1.sw_if_index,
                              self.pg1.remote_hosts[1].mac,
                              self.pg1.remote_hosts[1].ip4)
        arp_pg1.add_vpp_config()
        arp_pg2 = VppNeighbor(self, self.pg2.sw_if_index, self.pg2.remote_mac,
                              self.pg1.remote_hosts[1].ip4)
        arp_pg2.add_vpp_config()

        #
        # IP packet destined for pg1 remote host arrives on pg1 again.
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4) /
             UDP(sport=1234, dport=1234) / Raw())

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

        rx1 = self.pg1.get_capture(1)

        self.verify_ip(rx1[0], self.pg1.local_mac,
                       self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4,
                       self.pg1.remote_hosts[1].ip4)

        #
        # remove the duplicate on pg1
        # packet stream shoud generate ARPs out of pg1
        #
        arp_pg1.remove_vpp_config()

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

        rx1 = self.pg1.get_capture(1)

        self.verify_arp_req(rx1[0], self.pg1.local_mac, self.pg1.local_ip4,
                            self.pg1.remote_hosts[1].ip4)

        #
        # Add it back
        #
        arp_pg1.add_vpp_config()

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

        rx1 = self.pg1.get_capture(1)

        self.verify_ip(rx1[0], self.pg1.local_mac,
                       self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4,
                       self.pg1.remote_hosts[1].ip4)
Exemple #8
0
    def test_arp_incomplete(self):
        """ ARP Incomplete"""
        self.pg1.generate_remote_hosts(3)

        p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4) /
              UDP(sport=1234, dport=1234) / Raw())
        p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4) /
              UDP(sport=1234, dport=1234) / Raw())

        #
        # a packet to an unresolved destination generates an ARP request
        #
        rx = self.send_and_expect(self.pg0, [p0], self.pg1)
        self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4,
                            self.pg1._remote_hosts[1].ip4)

        #
        # add a neighbour for remote host 1
        #
        static_arp = VppNeighbor(self,
                                 self.pg1.sw_if_index,
                                 self.pg1.remote_hosts[1].mac,
                                 self.pg1.remote_hosts[1].ip4,
                                 is_static=1)
        static_arp.add_vpp_config()

        #
        # change the interface's MAC
        #
        mac = [
            chr(0x00),
            chr(0x00),
            chr(0x00),
            chr(0x33),
            chr(0x33),
            chr(0x33)
        ]
        mac_string = ''.join(mac)

        self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
                                               mac_string)

        #
        # now ARP requests come from the new source mac
        #
        rx = self.send_and_expect(self.pg0, [p1], self.pg1)
        self.verify_arp_req(rx[0], "00:00:00:33:33:33", self.pg1.local_ip4,
                            self.pg1._remote_hosts[2].ip4)

        #
        # packets to the resolved host also have the new source mac
        #
        rx = self.send_and_expect(self.pg0, [p0], self.pg1)
        self.verify_ip(rx[0], "00:00:00:33:33:33",
                       self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4,
                       self.pg1.remote_hosts[1].ip4)

        #
        # set the mac address on the inteface that does not have a
        # configured subnet and thus no glean
        #
        self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
                                               mac_string)
Exemple #9
0
    def create_stream(
        self,
        mac_type,
        ip_type,
        packet_count,
        src_if,
        dst_if,
        traffic,
        is_ip6,
        tags=PERMIT_TAGS,
    ):
        # exact MAC and exact IP
        # exact MAC and subnet of IPs
        # exact MAC and wildcard IP
        # wildcard MAC and exact IP
        # wildcard MAC and subnet of IPs
        # wildcard MAC and wildcard IP
        # OUI restricted MAC and exact IP
        # OUI restricted MAC and subnet of IPs
        # OUI restricted MAC and wildcard IP

        packets = []
        macip_rules = []
        acl_rules = []
        ip_permit = ""
        mac_permit = ""
        dst_mac = ""
        mac_rule = "00:00:00:00:00:00"
        mac_mask = "00:00:00:00:00:00"
        for p in range(0, packet_count):
            remote_dst_index = p % len(dst_if.remote_hosts)
            remote_dst_host = dst_if.remote_hosts[remote_dst_index]

            dst_port = 1234 + p
            src_port = 4321 + p
            is_permit = self.PERMIT if p % 3 == 0 else self.DENY
            denyMAC = True if not is_permit and p % 3 == 1 else False
            denyIP = True if not is_permit and p % 3 == 2 else False
            if not is_permit and ip_type == self.WILD_IP:
                denyMAC = True
            if not is_permit and mac_type == self.WILD_MAC:
                denyIP = True

            if traffic == self.BRIDGED:
                if is_permit:
                    src_mac = remote_dst_host._mac
                    dst_mac = "de:ad:00:00:00:00"
                    src_ip4 = remote_dst_host.ip4
                    dst_ip4 = src_if.remote_ip4
                    src_ip6 = remote_dst_host.ip6
                    dst_ip6 = src_if.remote_ip6
                    ip_permit = src_ip6 if is_ip6 else src_ip4
                    mac_permit = src_mac
                if denyMAC:
                    mac = src_mac.split(":")
                    mac[0] = format(int(mac[0], 16) + 1, "02x")
                    src_mac = ":".join(mac)
                    if is_ip6:
                        src_ip6 = ip_permit
                    else:
                        src_ip4 = ip_permit
                if denyIP:
                    if ip_type != self.WILD_IP:
                        src_mac = mac_permit
                    src_ip4 = remote_dst_host.ip4
                    dst_ip4 = src_if.remote_ip4
                    src_ip6 = remote_dst_host.ip6
                    dst_ip6 = src_if.remote_ip6
            else:
                if is_permit:
                    src_mac = remote_dst_host._mac
                    dst_mac = src_if.local_mac
                    src_ip4 = src_if.remote_ip4
                    dst_ip4 = remote_dst_host.ip4
                    src_ip6 = src_if.remote_ip6
                    dst_ip6 = remote_dst_host.ip6
                    ip_permit = src_ip6 if is_ip6 else src_ip4
                    mac_permit = src_mac
                if denyMAC:
                    mac = src_mac.split(":")
                    mac[0] = format(int(mac[0], 16) + 1, "02x")
                    src_mac = ":".join(mac)
                    if is_ip6:
                        src_ip6 = ip_permit
                    else:
                        src_ip4 = ip_permit
                if denyIP:
                    src_mac = remote_dst_host._mac
                    if ip_type != self.WILD_IP:
                        src_mac = mac_permit
                    src_ip4 = remote_dst_host.ip4
                    dst_ip4 = src_if.remote_ip4
                    src_ip6 = remote_dst_host.ip6
                    dst_ip6 = src_if.remote_ip6

            if is_permit:
                info = self.create_packet_info(src_if, dst_if)
                payload = self.info_to_payload(info)
            else:
                payload = "to be blocked"

            if mac_type == self.WILD_MAC:
                mac = src_mac.split(":")
                for i in range(1, 5):
                    mac[i] = format(random.randint(0, 255), "02x")
                src_mac = ":".join(mac)

            # create packet
            packet = Ether(src=src_mac, dst=dst_mac)
            ip_rule = src_ip6 if is_ip6 else src_ip4
            if is_ip6:
                if ip_type != self.EXACT_IP:
                    sub_ip = list(unpack("<16B", inet_pton(AF_INET6, ip_rule)))
                    if ip_type == self.WILD_IP:
                        sub_ip[0] = random.randint(240, 254)
                        sub_ip[1] = random.randint(230, 239)
                        sub_ip[14] = random.randint(100, 199)
                        sub_ip[15] = random.randint(200, 255)
                    elif ip_type == self.SUBNET_IP:
                        if denyIP:
                            sub_ip[2] = int(sub_ip[2]) + 1
                        sub_ip[14] = random.randint(100, 199)
                        sub_ip[15] = random.randint(200, 255)
                    packed_src_ip6 = b"".join([scapy.compat.chb(x) for x in sub_ip])
                    src_ip6 = inet_ntop(AF_INET6, packed_src_ip6)
                packet /= IPv6(src=src_ip6, dst=dst_ip6)
            else:
                if ip_type != self.EXACT_IP:
                    sub_ip = ip_rule.split(".")
                    if ip_type == self.WILD_IP:
                        sub_ip[0] = random.randint(1, 49)
                        sub_ip[1] = random.randint(50, 99)
                        sub_ip[2] = random.randint(100, 199)
                        sub_ip[3] = random.randint(200, 255)
                    elif ip_type == self.SUBNET_IP:
                        if denyIP:
                            sub_ip[1] = int(sub_ip[1]) + 1
                        sub_ip[2] = random.randint(100, 199)
                        sub_ip[3] = random.randint(200, 255)
                    src_ip4 = ".".join(["{!s}".format(x) for x in sub_ip])
                packet /= IP(src=src_ip4, dst=dst_ip4, frag=0, flags=0)

            packet /= UDP(sport=src_port, dport=dst_port) / Raw(payload)

            packet[Raw].load += b" mac:%s" % src_mac.encode("utf-8")

            size = self.pg_if_packet_sizes[p % len(self.pg_if_packet_sizes)]
            if isinstance(src_if, VppSubInterface):
                size = size + 4
            if isinstance(src_if, VppDot1QSubint):
                if src_if is self.subifs[0]:
                    if tags == self.PERMIT_TAGS:
                        packet = src_if.add_dot1q_layer(packet, 10)
                    else:
                        packet = src_if.add_dot1q_layer(packet, 11)
                else:
                    if tags == self.PERMIT_TAGS:
                        packet = src_if.add_dot1q_layer(packet, 30)
                    else:
                        packet = src_if.add_dot1q_layer(packet, 33)
            elif isinstance(src_if, VppDot1ADSubint):
                if src_if is self.subifs[1]:
                    if tags == self.PERMIT_TAGS:
                        packet = src_if.add_dot1ad_layer(packet, 300, 400)
                    else:
                        packet = src_if.add_dot1ad_layer(packet, 333, 444)
                else:
                    if tags == self.PERMIT_TAGS:
                        packet = src_if.add_dot1ad_layer(packet, 600, 700)
                    else:
                        packet = src_if.add_dot1ad_layer(packet, 666, 777)
            self.extend_packet(packet, size)
            packets.append(packet)

            # create suitable MACIP rule
            if mac_type == self.EXACT_MAC:
                mac_rule = src_mac
                mac_mask = "ff:ff:ff:ff:ff:ff"
            elif mac_type == self.WILD_MAC:
                mac_rule = "00:00:00:00:00:00"
                mac_mask = "00:00:00:00:00:00"
            elif mac_type == self.OUI_MAC:
                mac = src_mac.split(":")
                mac[3] = mac[4] = mac[5] = "00"
                mac_rule = ":".join(mac)
                mac_mask = "ff:ff:ff:00:00:00"

            if is_ip6:
                if ip_type == self.WILD_IP:
                    ip = "0::0"
                else:
                    ip = src_ip6
                    if ip_type == self.SUBNET_IP:
                        sub_ip = list(unpack("<16B", inet_pton(AF_INET6, ip)))
                        for i in range(8, 16):
                            sub_ip[i] = 0
                        packed_ip = b"".join([scapy.compat.chb(x) for x in sub_ip])
                        ip = inet_ntop(AF_INET6, packed_ip)
            else:
                if ip_type == self.WILD_IP:
                    ip = "0.0.0.0"
                else:
                    ip = src_ip4
                    if ip_type == self.SUBNET_IP:
                        sub_ip = ip.split(".")
                        sub_ip[2] = sub_ip[3] = "0"
                        ip = ".".join(sub_ip)

            prefix_len = 128 if is_ip6 else 32
            if ip_type == self.WILD_IP:
                prefix_len = 0
            elif ip_type == self.SUBNET_IP:
                prefix_len = 64 if is_ip6 else 16
            ip_rule = inet_pton(AF_INET6 if is_ip6 else AF_INET, ip)

            # create suitable ACL rule
            if is_permit:
                rule_l4_sport = packet[UDP].sport
                rule_l4_dport = packet[UDP].dport
                rule_family = AF_INET6 if packet.haslayer(IPv6) else AF_INET
                rule_prefix_len = 128 if packet.haslayer(IPv6) else 32
                rule_l3_layer = IPv6 if packet.haslayer(IPv6) else IP
                if packet.haslayer(IPv6):
                    rule_l4_proto = packet[UDP].overload_fields[IPv6]["nh"]
                else:
                    rule_l4_proto = packet[IP].proto

                src_network = ip_network((packet[rule_l3_layer].src, rule_prefix_len))
                dst_network = ip_network((packet[rule_l3_layer].dst, rule_prefix_len))
                acl_rule = AclRule(
                    is_permit=is_permit,
                    proto=rule_l4_proto,
                    src_prefix=src_network,
                    dst_prefix=dst_network,
                    sport_from=rule_l4_sport,
                    sport_to=rule_l4_sport,
                    dport_from=rule_l4_dport,
                    dport_to=rule_l4_dport,
                )
                acl_rules.append(acl_rule)

            if mac_type == self.WILD_MAC and ip_type == self.WILD_IP and p > 0:
                continue

            if is_permit:
                macip_rule = MacipRule(
                    is_permit=is_permit,
                    src_prefix=ip_network((ip_rule, prefix_len)),
                    src_mac=MACAddress(mac_rule).packed,
                    src_mac_mask=MACAddress(mac_mask).packed,
                )
                macip_rules.append(macip_rule)

        # deny all other packets
        if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP):
            network = IPv6Network((0, 0)) if is_ip6 else IPv4Network((0, 0))
            macip_rule = MacipRule(
                is_permit=0,
                src_prefix=network,
                src_mac=MACAddress("00:00:00:00:00:00").packed,
                src_mac_mask=MACAddress("00:00:00:00:00:00").packed,
            )
            macip_rules.append(macip_rule)

        network = IPv6Network((0, 0)) if is_ip6 else IPv4Network((0, 0))
        acl_rule = AclRule(
            is_permit=0,
            src_prefix=network,
            dst_prefix=network,
            sport_from=0,
            sport_to=0,
            dport_from=0,
            dport_to=0,
        )
        acl_rules.append(acl_rule)
        return {"stream": packets, "macip_rules": macip_rules, "acl_rules": acl_rules}
Exemple #10
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(sw_if_index=self.pg3.sw_if_index,
                                             enable_disable=1)
        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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=1)
        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(sw_if_index=self.pg1.sw_if_index,
                                             enable_disable=1)

        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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=0)
        self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
                                             enable_disable=0)
Exemple #11
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)
Exemple #12
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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=1)

        #
        # 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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=0)
        self.vapi.feature_gso_enable_disable(
            sw_if_index=self.ipip4.sw_if_index, enable_disable=1)

        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(
            sw_if_index=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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=1)
        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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=0)
Exemple #13
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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=1)

        #
        # 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, ignore_zero_checksum=False)
            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, ignore_zero_checksum=False)
            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, ignore_zero_checksum=False)
            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, ignore_zero_checksum=False)
            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(sw_if_index=self.pg0.sw_if_index,
                                             enable_disable=0)
Exemple #14
0
    def test_ip_load_balance(self):
        """ IP Load-Balancing """

        #
        # An array of packets that differ only in the destination port
        #
        port_ip_pkts = []
        port_mpls_pkts = []

        #
        # An array of packets that differ only in the source address
        #
        src_ip_pkts = []
        src_mpls_pkts = []

        for ii in range(65):
            port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
                           UDP(sport=1234, dport=1234 + ii) /
                           Raw('\xa5' * 100))
            port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
                                       dst=self.pg0.local_mac) /
                                 port_ip_hdr))
            port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
                                         dst=self.pg0.local_mac) /
                                   MPLS(label=66, ttl=2) /
                                   port_ip_hdr))

            src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
                          UDP(sport=1234, dport=1234) /
                          Raw('\xa5' * 100))
            src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
                                      dst=self.pg0.local_mac) /
                                src_ip_hdr))
            src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
                                        dst=self.pg0.local_mac) /
                                  MPLS(label=66, ttl=2) /
                                  src_ip_hdr))

        route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
                                    [VppRoutePath(self.pg1.remote_ip4,
                                                  self.pg1.sw_if_index),
                                     VppRoutePath(self.pg2.remote_ip4,
                                                  self.pg2.sw_if_index)])
        route_10_0_0_1.add_vpp_config()

        binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
        binding.add_vpp_config()

        #
        # inject the packet on pg0 - expect load-balancing across the 2 paths
        #  - since the default hash config is to use IP src,dst and port
        #    src,dst
        # We are not going to ensure equal amounts of packets across each link,
        # since the hash algorithm is statistical and therefore this can never
        # be guaranteed. But wuth 64 different packets we do expect some
        # balancing. So instead just ensure there is traffic on each link.
        #
        self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
                                            [self.pg1, self.pg2])
        self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
                                            [self.pg1, self.pg2])
        self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
                                            [self.pg1, self.pg2])
        self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
                                            [self.pg1, self.pg2])

        #
        # change the flow hash config so it's only IP src,dst
        #  - now only the stream with differing source address will
        #    load-balance
        #
        self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0)

        self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
                                            [self.pg1, self.pg2])
        self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
                                            [self.pg1, self.pg2])

        self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)

        #
        # change the flow hash config back to defaults
        #
        self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1)

        #
        # Recursive prefixes
        #  - testing that 2 stages of load-balancing occurs and there is no
        #    polarisation (i.e. only 2 of 4 paths are used)
        #
        port_pkts = []
        src_pkts = []

        for ii in range(257):
            port_pkts.append((Ether(src=self.pg0.remote_mac,
                                    dst=self.pg0.local_mac) /
                              IP(dst="1.1.1.1", src="20.0.0.1") /
                              UDP(sport=1234, dport=1234 + ii) /
                              Raw('\xa5' * 100)))
            src_pkts.append((Ether(src=self.pg0.remote_mac,
                                   dst=self.pg0.local_mac) /
                             IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
                             UDP(sport=1234, dport=1234) /
                             Raw('\xa5' * 100)))

        route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
                                    [VppRoutePath(self.pg3.remote_ip4,
                                                  self.pg3.sw_if_index),
                                     VppRoutePath(self.pg4.remote_ip4,
                                                  self.pg4.sw_if_index)])
        route_10_0_0_2.add_vpp_config()

        route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
                                   [VppRoutePath("10.0.0.2", 0xffffffff),
                                    VppRoutePath("10.0.0.1", 0xffffffff)])
        route_1_1_1_1.add_vpp_config()

        #
        # inject the packet on pg0 - expect load-balancing across all 4 paths
        #
        self.vapi.cli("clear trace")
        self.send_and_expect_load_balancing(self.pg0, port_pkts,
                                            [self.pg1, self.pg2,
                                             self.pg3, self.pg4])
        self.send_and_expect_load_balancing(self.pg0, src_pkts,
                                            [self.pg1, self.pg2,
                                             self.pg3, self.pg4])

        #
        # Recursive prefixes
        #  - testing that 2 stages of load-balancing, no choices
        #
        port_pkts = []

        for ii in range(257):
            port_pkts.append((Ether(src=self.pg0.remote_mac,
                                    dst=self.pg0.local_mac) /
                              IP(dst="1.1.1.2", src="20.0.0.2") /
                              UDP(sport=1234, dport=1234 + ii) /
                              Raw('\xa5' * 100)))

        route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
                                    [VppRoutePath(self.pg3.remote_ip4,
                                                  self.pg3.sw_if_index)])
        route_10_0_0_3.add_vpp_config()

        route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
                                   [VppRoutePath("10.0.0.3", 0xffffffff)])
        route_1_1_1_2.add_vpp_config()

        #
        # inject the packet on pg0 - expect load-balancing across all 4 paths
        #
        self.vapi.cli("clear trace")
        self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
Exemple #15
0
    def test_ip_sub_nets(self):
        """ IP Sub Nets """

        #
        # Configure a covering route to forward so we know
        # when we are dropping
        #
        cover_route = VppIpRoute(self, "10.0.0.0", 8,
                                 [VppRoutePath(self.pg1.remote_ip4,
                                               self.pg1.sw_if_index)])
        cover_route.add_vpp_config()

        p = (Ether(src=self.pg1.remote_mac,
                   dst=self.pg1.local_mac) /
             IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
             UDP(sport=1234, dport=1234) /
             Raw('\xa5' * 100))

        self.pg1.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)

        #
        # Configure some non-/24 subnets on an IP interface
        #
        ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")

        self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
                                               ip_addr_n,
                                               16)

        pn = (Ether(src=self.pg1.remote_mac,
                    dst=self.pg1.local_mac) /
              IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
              UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))
        pb = (Ether(src=self.pg1.remote_mac,
                    dst=self.pg1.local_mac) /
              IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
              UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))

        self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
        self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")

        # remove the sub-net and we are forwarding via the cover again
        self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
                                               ip_addr_n,
                                               16,
                                               is_add=0)
        self.pg1.add_stream(pn)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
        self.pg1.add_stream(pb)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)

        #
        # A /31 is a special case where the 'other-side' is an attached host
        # packets to that peer generate ARP requests
        #
        ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")

        self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
                                               ip_addr_n,
                                               31)

        pn = (Ether(src=self.pg1.remote_mac,
                    dst=self.pg1.local_mac) /
              IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
              UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))

        self.pg1.add_stream(pn)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)
        rx[ARP]

        # remove the sub-net and we are forwarding via the cover again
        self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
                                               ip_addr_n,
                                               31,
                                               is_add=0)
        self.pg1.add_stream(pn)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
Exemple #16
0
    def test_ip_disabled(self):
        """ IP Disabled """

        #
        # An (S,G).
        # one accepting interface, pg0, 2 forwarding interfaces
        #
        route_232_1_1_1 = VppIpMRoute(
            self,
            "0.0.0.0",
            "232.1.1.1", 32,
            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
            [VppMRoutePath(self.pg1.sw_if_index,
                           MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
             VppMRoutePath(self.pg0.sw_if_index,
                           MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
        route_232_1_1_1.add_vpp_config()

        pu = (Ether(src=self.pg1.remote_mac,
                    dst=self.pg1.local_mac) /
              IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
              UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))
        pm = (Ether(src=self.pg1.remote_mac,
                    dst=self.pg1.local_mac) /
              IP(src="10.10.10.10", dst="232.1.1.1") /
              UDP(sport=1234, dport=1234) /
              Raw('\xa5' * 100))

        #
        # PG1 does not forward IP traffic
        #
        self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
        self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")

        #
        # IP enable PG1
        #
        self.pg1.config_ip4()

        #
        # Now we get packets through
        #
        self.pg1.add_stream(pu)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)

        self.pg1.add_stream(pm)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)

        #
        # Disable PG1
        #
        self.pg1.unconfig_ip4()

        #
        # PG1 does not forward IP traffic
        #
        self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
        self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
Exemple #17
0
    def test_bond_traffic(self):
        """ Bond traffic test """

        # topology
        #
        # RX->              TX->
        #
        # pg2 ------+        +------pg0 (slave)
        #           |        |
        #          BondEthernet0 (10.10.10.1)
        #           |        |
        # pg3 ------+        +------pg1 (slave)
        #

        # create interface (BondEthernet0)
        #        self.logger.info("create bond")
        bond0_mac = "02:fe:38:30:59:3c"
        mac = mactobinary(bond0_mac)
        bond0 = VppBondInterface(self,
                                 mode=3,
                                 lb=1,
                                 use_custom_mac=1,
                                 mac_address=mac)
        bond0.add_vpp_config()
        bond0.admin_up()
        bond0_addr = socket.inet_pton(socket.AF_INET, "10.10.10.1")
        self.vapi.sw_interface_add_del_address(bond0.sw_if_index, bond0_addr,
                                               24)

        self.pg2.config_ip4()
        self.pg2.resolve_arp()
        self.pg3.config_ip4()
        self.pg3.resolve_arp()

        self.logger.info(self.vapi.cli("show interface"))
        self.logger.info(self.vapi.cli("show interface address"))
        self.logger.info(self.vapi.cli("show ip arp"))

        # enslave pg0 and pg1 to BondEthernet0
        self.logger.info("bond enslave interface pg0 to BondEthernet0")
        bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
                                         is_passive=0,
                                         is_long_timeout=0)
        self.logger.info("bond enslave interface pg1 to BondEthernet0")
        bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
                                         is_passive=0,
                                         is_long_timeout=0)

        # verify both slaves in BondEthernet0
        if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
        self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
        self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))

        # generate a packet from pg2 -> BondEthernet0 -> pg1
        # BondEthernet0 TX hashes this packet to pg1
        p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
              IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
              UDP(sport=1235, dport=1235) / Raw('\xa5' * 100))
        self.pg2.add_stream(p2)

        # generate a packet from pg3 -> BondEthernet0 -> pg0
        # BondEthernet0 TX hashes this packet to pg0
        # notice the ip address and ports are different than p2 packet
        p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
              IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
              UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        self.pg3.add_stream(p3)

        self.pg_enable_capture(self.pg_interfaces)

        # set up the static arp entries pointing to the BondEthernet0 interface
        # so that it does not try to resolve the ip address
        self.logger.info(
            self.vapi.cli(
                "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
        self.logger.info(
            self.vapi.cli(
                "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))

        # clear the interface counters
        self.logger.info(self.vapi.cli("clear interfaces"))

        self.pg_start()

        self.logger.info("check the interface counters")

        # verify counters

        # BondEthernet0 tx bytes = 284
        intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
        found = 0
        for intf in intfs:
            if "tx bytes" in intf and "284" in intf:
                found = 1
        self.assertEqual(found, 1)

        # BondEthernet0 tx bytes = 284
        intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
        found = 0
        for intf in intfs:
            if "tx bytes" in intf and "284" in intf:
                found = 1
        self.assertEqual(found, 1)

        # pg2 rx bytes = 142
        intfs = self.vapi.cli("show interface pg2").split("\n")
        found = 0
        for intf in intfs:
            if "rx bytes" in intf and "142" in intf:
                found = 1
        self.assertEqual(found, 1)

        # pg3 rx bytes = 142
        intfs = self.vapi.cli("show interface pg3").split("\n")
        found = 0
        for intf in intfs:
            if "rx bytes" in intf and "142" in intf:
                found = 1
        self.assertEqual(found, 1)

        bond0.remove_vpp_config()
Exemple #18
0
    frame = frame / IP(dst=ip_dst, src=ip_src, tos=tos_val, ttl=ttl)

    return add_payload(frame, size, pattern)


## Utility to create dummy protocols frames #######################################################

pdu_info = {
    'stp': {
        'mac': '01:80:c2:00:00:00',
        'load': LLC() / STP()
    },
    'rstp': {
        'mac': '01:80:c2:00:00:00',
        'load': LLC() / STP(version=2) / Raw('\0')
    },
    'lldp': {
        'mac': '01:80:c2:00:00:0e',
        'type': 0x88cc,
        'load': Raw('\0' * 282)
    },
    'lacp': {
        'mac': '01:80:c2:00:00:02',
        'type': 0x8809,
        'load': Raw('\x01') / Raw('\0' * 109)
    },
    'marker': {
        'mac': '01:80:c2:00:00:02',
        'type': 0x8809,
        'load': Raw('\x02') / Raw('\0' * 49)
Exemple #19
0
    def test_cflow_packet(self):
        """verify cflow packet fields"""
        self.logger.info("FFP_TEST_START_0000")
        self.pg_enable_capture(self.pg_interfaces)
        self.pkts = []

        ipfix = VppCFLOW(test=self, intf='pg8', datapath="ip4",
                         layer='l2 l3 l4', active=2)
        ipfix.add_vpp_config()

        route_9001 = VppIpRoute(self, "9.0.0.0", 24,
                                [VppRoutePath(self.pg8._remote_hosts[0].ip4,
                                              self.pg8.sw_if_index)])
        route_9001.add_vpp_config()

        ipfix_decoder = IPFIXDecoder()
        templates = ipfix.verify_templates(ipfix_decoder, count=1)

        self.pkts = [(Ether(dst=self.pg7.local_mac,
                            src=self.pg7.remote_mac) /
                      IP(src=self.pg7.remote_ip4, dst="9.0.0.100") /
                      TCP(sport=1234, dport=4321, flags=80) /
                      Raw('\xa5' * 100))]

        nowUTC = int(time.time())
        nowUNIX = nowUTC+2208988800
        self.send_packets(src_if=self.pg7, dst_if=self.pg8)

        cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
        self.collector.get_capture(2)

        if cflow[0].haslayer(IPFIX):
            self.assertEqual(cflow[IPFIX].version, 10)
            self.assertEqual(cflow[IPFIX].observationDomainID, 1)
            self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
            self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
        if cflow.haslayer(Data):
            record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
            # ingress interface
            self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
            # egress interface
            self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
            # packets
            self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
            # src mac
            self.assertEqual(':'.join(re.findall('..', record[56].encode(
                'hex'))), self.pg8.local_mac)
            # dst mac
            self.assertEqual(':'.join(re.findall('..', record[80].encode(
                'hex'))), self.pg8.remote_mac)
            flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
            # flow start timestamp
            self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
            flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
            # flow end timestamp
            self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
            # ethernet type
            self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
            # src ip
            self.assertEqual('.'.join(re.findall('..', record[8].encode(
                                      'hex'))),
                             '.'.join('{:02x}'.format(int(n)) for n in
                                      self.pg7.remote_ip4.split('.')))
            # dst ip
            self.assertEqual('.'.join(re.findall('..', record[12].encode(
                                      'hex'))),
                             '.'.join('{:02x}'.format(int(n)) for n in
                                      "9.0.0.100".split('.')))
            # protocol (TCP)
            self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
            # src port
            self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
            # dst port
            self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
            # tcp flags
            self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)

        ipfix.remove_vpp_config()
        self.logger.info("FFP_TEST_FINISH_0000")
Exemple #20
0
def fragment_rfc8200(packet, identification, fragsize, logger=null_logger):
    """
    Fragment an IPv6 packet per RFC 8200
    :param packet: packet to fragment
    :param fragsize: size at which to fragment
    :note: IP options are not supported
    :returns: list of fragments
    """
    packet = packet.__class__(scapy.compat.raw(packet))  # recalc. all values
    if len(packet) <= fragsize:
        return [packet]
    logger.debug(ppp("Fragmenting packet:", packet))
    pkts = []
    counter = 0
    routing_hdr = None
    hop_by_hop_hdr = None
    upper_layer = None
    seen_ipv6 = False
    ipv6_nr = -1
    l = packet.getlayer(counter)
    while l is not None:
        if l.__class__ is IPv6:
            if seen_ipv6:
                # ignore 2nd IPv6 header and everything below..
                break
            ipv6_nr = counter
            seen_ipv6 = True
        elif l.__class__ is IPv6ExtHdrFragment:
            raise Exception("Already fragmented")
        elif l.__class__ is IPv6ExtHdrRouting:
            routing_hdr = counter
        elif l.__class__ is IPv6ExtHdrHopByHop:
            hop_by_hop_hdr = counter
        elif (seen_ipv6 and not upper_layer
              and not l.__class__.__name__.startswith("IPv6ExtHdr")):
            upper_layer = counter
        counter = counter + 1
        l = packet.getlayer(counter)

    logger.debug(
        "Layers seen: IPv6(#%s), Routing(#%s), HopByHop(#%s), upper(#%s)" %
        (ipv6_nr, routing_hdr, hop_by_hop_hdr, upper_layer))

    if upper_layer is None:
        raise Exception("Upper layer header not found in IPv6 packet")

    last_per_fragment_hdr = ipv6_nr
    if routing_hdr is None:
        if hop_by_hop_hdr is not None:
            last_per_fragment_hdr = hop_by_hop_hdr
    else:
        last_per_fragment_hdr = routing_hdr
    logger.debug("Last per-fragment hdr is #%s" % (last_per_fragment_hdr))

    per_fragment_headers = packet.copy()
    per_fragment_headers[last_per_fragment_hdr].remove_payload()
    logger.debug(ppp("Per-fragment headers:", per_fragment_headers))

    ext_and_upper_layer = packet.getlayer(last_per_fragment_hdr)[1]
    hex_payload = scapy.compat.raw(ext_and_upper_layer)
    logger.debug("Payload length is %s" % len(hex_payload))
    logger.debug(ppp("Ext and upper layer:", ext_and_upper_layer))

    fragment_ext_hdr = IPv6ExtHdrFragment()
    logger.debug(ppp("Fragment header:", fragment_ext_hdr))

    len_ext_and_upper_layer_payload = len(ext_and_upper_layer.payload)
    if not len_ext_and_upper_layer_payload and hasattr(ext_and_upper_layer,
                                                       "data"):
        len_ext_and_upper_layer_payload = len(ext_and_upper_layer.data)

    if (len(per_fragment_headers) + len(fragment_ext_hdr) +
            len(ext_and_upper_layer) - len_ext_and_upper_layer_payload >
            fragsize):
        raise Exception("Cannot fragment this packet - MTU too small "
                        "(%s, %s, %s, %s, %s)" % (
                            len(per_fragment_headers),
                            len(fragment_ext_hdr),
                            len(ext_and_upper_layer),
                            len_ext_and_upper_layer_payload,
                            fragsize,
                        ))

    orig_nh = packet[IPv6].nh
    p = per_fragment_headers
    del p[IPv6].plen
    del p[IPv6].nh
    p = p / fragment_ext_hdr
    del p[IPv6ExtHdrFragment].nh
    first_payload_len_nfb = int((fragsize - len(p)) / 8)
    p = p / Raw(hex_payload[:first_payload_len_nfb * 8])
    del p[IPv6].plen
    p[IPv6ExtHdrFragment].nh = orig_nh
    p[IPv6ExtHdrFragment].id = identification
    p[IPv6ExtHdrFragment].offset = 0
    p[IPv6ExtHdrFragment].m = 1
    p = p.__class__(scapy.compat.raw(p))
    logger.debug(ppp("Fragment %s:" % len(pkts), p))
    pkts.append(p)
    offset = first_payload_len_nfb * 8
    logger.debug("Offset after first fragment: %s" % offset)
    while len(hex_payload) > offset:
        p = per_fragment_headers
        del p[IPv6].plen
        del p[IPv6].nh
        p = p / fragment_ext_hdr
        del p[IPv6ExtHdrFragment].nh
        l_nfb = int((fragsize - len(p)) / 8)
        p = p / Raw(hex_payload[offset:offset + l_nfb * 8])
        p[IPv6ExtHdrFragment].nh = orig_nh
        p[IPv6ExtHdrFragment].id = identification
        p[IPv6ExtHdrFragment].offset = int(offset / 8)
        p[IPv6ExtHdrFragment].m = 1
        p = p.__class__(scapy.compat.raw(p))
        logger.debug(ppp("Fragment %s:" % len(pkts), p))
        pkts.append(p)
        offset = offset + l_nfb * 8

    pkts[-1][IPv6ExtHdrFragment].m = 0  # reset more-flags in last fragment

    return pkts
Exemple #21
0
    def test_arp(self):
        """ ARP """

        #
        # Generate some hosts on the LAN
        #
        self.pg1.generate_remote_hosts(11)

        #
        # Send IP traffic to one of these unresolved hosts.
        #  expect the generation of an ARP request
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
             UDP(sport=1234, dport=1234) / Raw())

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

        rx = self.pg1.get_capture(1)

        self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4,
                            self.pg1._remote_hosts[1].ip4)

        #
        # And a dynamic ARP entry for host 1
        #
        dyn_arp = VppNeighbor(self, self.pg1.sw_if_index,
                              self.pg1.remote_hosts[1].mac,
                              self.pg1.remote_hosts[1].ip4)
        dyn_arp.add_vpp_config()

        #
        # now we expect IP traffic forwarded
        #
        dyn_p = (
            Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
            IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
            UDP(sport=1234, dport=1234) / Raw())

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

        rx = self.pg1.get_capture(1)

        self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[1].mac,
                       self.pg0.remote_ip4, self.pg1._remote_hosts[1].ip4)

        #
        # And a Static ARP entry for host 2
        #
        static_arp = VppNeighbor(self,
                                 self.pg1.sw_if_index,
                                 self.pg1.remote_hosts[2].mac,
                                 self.pg1.remote_hosts[2].ip4,
                                 is_static=1)
        static_arp.add_vpp_config()

        static_p = (
            Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
            IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4) /
            UDP(sport=1234, dport=1234) / Raw())

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

        rx = self.pg1.get_capture(1)

        self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[2].mac,
                       self.pg0.remote_ip4, self.pg1._remote_hosts[2].ip4)

        #
        # flap the link. dynamic ARPs get flush, statics don't
        #
        self.pg1.admin_down()
        self.pg1.admin_up()

        self.pg0.add_stream(static_p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)

        self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[2].mac,
                       self.pg0.remote_ip4, self.pg1._remote_hosts[2].ip4)

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

        rx = self.pg1.get_capture(1)
        self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4,
                            self.pg1._remote_hosts[1].ip4)

        #
        # Send an ARP request from one of the so-far unlearned remote hosts
        #
        p = (
            Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) /
            ARP(op="who-has",
                hwsrc=self.pg1._remote_hosts[3].mac,
                pdst=self.pg1.local_ip4,
                psrc=self.pg1._remote_hosts[3].ip4))

        self.pg1.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg1.local_mac,
                             self.pg1._remote_hosts[3].mac, self.pg1.local_ip4,
                             self.pg1._remote_hosts[3].ip4)

        #
        # VPP should have learned the mapping for the remote host
        #
        self.assertTrue(
            find_nbr(self, self.pg1.sw_if_index,
                     self.pg1._remote_hosts[3].ip4))
        #
        # Fire in an ARP request before the interface becomes IP enabled
        #
        self.pg2.generate_remote_hosts(4)

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg2.remote_hosts[3].ip4))
        pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
              Dot1Q(vlan=0) / ARP(op="who-has",
                                  hwsrc=self.pg2.remote_mac,
                                  pdst=self.pg1.local_ip4,
                                  psrc=self.pg2.remote_hosts[3].ip4))
        self.send_and_assert_no_replies(self.pg2, p,
                                        "interface not IP enabled")

        #
        # Make pg2 un-numbered to pg1
        #
        self.pg2.set_unnumbered(self.pg1.sw_if_index)

        unnum = self.vapi.ip_unnumbered_dump()
        self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
        self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)

        #
        # We should respond to ARP requests for the unnumbered to address
        # once an attached route to the source is known
        #
        self.send_and_assert_no_replies(
            self.pg2, p, "ARP req for unnumbered address - no source")

        attached_host = VppIpRoute(
            self, self.pg2.remote_hosts[3].ip4, 32,
            [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)])
        attached_host.add_vpp_config()

        self.pg2.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac,
                             self.pg1.local_ip4, self.pg2.remote_hosts[3].ip4)

        self.pg2.add_stream(pt)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac,
                             self.pg1.local_ip4, self.pg2.remote_hosts[3].ip4)

        #
        # A neighbor entry that has no associated FIB-entry
        #
        arp_no_fib = VppNeighbor(self,
                                 self.pg1.sw_if_index,
                                 self.pg1.remote_hosts[4].mac,
                                 self.pg1.remote_hosts[4].ip4,
                                 is_no_fib_entry=1)
        arp_no_fib.add_vpp_config()

        #
        # check we have the neighbor, but no route
        #
        self.assertTrue(
            find_nbr(self, self.pg1.sw_if_index,
                     self.pg1._remote_hosts[4].ip4))
        self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32))
        #
        # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
        # from within pg1's subnet
        #
        arp_unnum = VppNeighbor(self, self.pg2.sw_if_index,
                                self.pg1.remote_hosts[5].mac,
                                self.pg1.remote_hosts[5].ip4)
        arp_unnum.add_vpp_config()

        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4) /
             UDP(sport=1234, dport=1234) / Raw())

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

        rx = self.pg2.get_capture(1)

        self.verify_ip(rx[0], self.pg2.local_mac, self.pg1.remote_hosts[5].mac,
                       self.pg0.remote_ip4, self.pg1._remote_hosts[5].ip4)

        #
        # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
        # with the unnumbered interface's address as the source
        #
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg1.remote_hosts[6].ip4))

        self.pg2.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac,
                             self.pg1.local_ip4, self.pg1.remote_hosts[6].ip4)

        #
        # An attached host route out of pg2 for an undiscovered hosts generates
        # an ARP request with the unnumbered address as the source
        #
        att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
                               [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)])
        att_unnum.add_vpp_config()

        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4) /
             UDP(sport=1234, dport=1234) / Raw())

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

        rx = self.pg2.get_capture(1)

        self.verify_arp_req(rx[0], self.pg2.local_mac, self.pg1.local_ip4,
                            self.pg1._remote_hosts[7].ip4)

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg1.remote_hosts[7].ip4))

        self.pg2.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac,
                             self.pg1.local_ip4, self.pg1.remote_hosts[7].ip4)

        #
        # An attached host route as yet unresolved out of pg2 for an
        # undiscovered host, an ARP requests begets a response.
        #
        att_unnum1 = VppIpRoute(
            self, self.pg1.remote_hosts[8].ip4, 32,
            [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)])
        att_unnum1.add_vpp_config()

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg1.remote_hosts[8].ip4))

        self.pg2.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac,
                             self.pg1.local_ip4, self.pg1.remote_hosts[8].ip4)

        #
        # Send an ARP request from one of the so-far unlearned remote hosts
        # with a VLAN0 tag
        #
        p = (
            Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac) /
            Dot1Q(vlan=0) / ARP(op="who-has",
                                hwsrc=self.pg1._remote_hosts[9].mac,
                                pdst=self.pg1.local_ip4,
                                psrc=self.pg1._remote_hosts[9].ip4))

        self.pg1.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg1.local_mac,
                             self.pg1._remote_hosts[9].mac, self.pg1.local_ip4,
                             self.pg1._remote_hosts[9].ip4)

        #
        # Add a hierachy of routes for a host in the sub-net.
        # Should still get an ARP resp since the cover is attached
        #
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg1.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg1.remote_hosts[10].ip4))

        r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30, [
            VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)
        ])
        r1.add_vpp_config()

        self.pg1.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1.remote_mac,
                             self.pg1.local_ip4, self.pg1.remote_hosts[10].ip4)

        r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32, [
            VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)
        ])
        r2.add_vpp_config()

        self.pg1.add_stream(p)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
        self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1.remote_mac,
                             self.pg1.local_ip4, self.pg1.remote_hosts[10].ip4)

        #
        # add an ARP entry that's not on the sub-net and so whose
        # adj-fib fails the refinement check. then send an ARP request
        # from that source
        #
        a1 = VppNeighbor(self, self.pg0.sw_if_index, self.pg0.remote_mac,
                         "100.100.100.50")
        a1.add_vpp_config()

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 psrc="100.100.100.50",
                 pdst=self.pg0.remote_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for from failed adj-fib")

        #
        # ERROR Cases
        #  1 - don't respond to ARP request for address not within the
        #      interface's sub-net
        #  1b - nor within the unnumbered subnet
        #  1c - nor within the subnet of a different interface
        #
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 pdst="10.10.10.3",
                 psrc=self.pg0.remote_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local destination")
        self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3"))

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 pdst="10.10.10.3",
                 psrc=self.pg1.remote_hosts[7].ip4))
        self.send_and_assert_no_replies(
            self.pg0, p, "ARP req for non-local destination - unnum")

        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 pdst=self.pg1.local_ip4,
                 psrc=self.pg1.remote_ip4))
        self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net")
        self.assertFalse(
            find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4))

        #
        #  2 - don't respond to ARP request from an address not within the
        #      interface's sub-net
        #   2b - to a prxied address
        #   2c - not within a differents interface's sub-net
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 psrc="10.10.10.3",
                 pdst=self.pg0.local_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local source")
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg2.remote_mac,
                 psrc="10.10.10.3",
                 pdst=self.pg0.local_ip4))
        self.send_and_assert_no_replies(
            self.pg0, p, "ARP req for non-local source - unnum")
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 psrc=self.pg1.remote_ip4,
                 pdst=self.pg0.local_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local source 2c")

        #
        #  3 - don't respond to ARP request from an address that belongs to
        #      the router
        #
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 psrc=self.pg0.local_ip4,
                 pdst=self.pg0.local_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local source")

        #
        #  4 - don't respond to ARP requests that has mac source different
        #      from ARP request HW source
        #
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc="00:00:00:DE:AD:BE",
                 psrc=self.pg0.remote_ip4,
                 pdst=self.pg0.local_ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local source")

        #
        #  5 - don't respond to ARP requests for address within the
        #      interface's sub-net but not the interface's address
        #
        self.pg0.generate_remote_hosts(2)
        p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
             ARP(op="who-has",
                 hwsrc=self.pg0.remote_mac,
                 psrc=self.pg0.remote_hosts[0].ip4,
                 pdst=self.pg0.remote_hosts[1].ip4))
        self.send_and_assert_no_replies(self.pg0, p,
                                        "ARP req for non-local destination")

        #
        # cleanup
        #
        dyn_arp.remove_vpp_config()
        static_arp.remove_vpp_config()
        self.pg2.unset_unnumbered(self.pg1.sw_if_index)

        # need this to flush the adj-fibs
        self.pg2.unset_unnumbered(self.pg1.sw_if_index)
        self.pg2.admin_down()
        self.pg1.admin_down()
Exemple #22
0
def main():
    """Send IP ICMP packet from one traffic generator interface to the other.

    :raises RuntimeError: If the received packet is not correct."""

    args = TrafficScriptArg(
        [
            u"tg_src_mac", u"tg_dst_mac", u"src_ip", u"dst_ip", u"dut_if1_mac",
            u"dut_if2_mac", u"src_rloc", u"dst_rloc"
        ],
        [u"ot_mode"]
    )

    tx_src_mac = args.get_arg(u"tg_src_mac")
    tx_dst_mac = args.get_arg(u"dut_if1_mac")
    rx_dst_mac = args.get_arg(u"tg_dst_mac")
    rx_src_mac = args.get_arg(u"dut_if2_mac")
    src_ip = args.get_arg(u"src_ip")
    dst_ip = args.get_arg(u"dst_ip")
    src_rloc = args.get_arg(u"src_rloc")
    dst_rloc = args.get_arg(u"dst_rloc")
    tx_if = args.get_arg(u"tx_if")
    rx_if = args.get_arg(u"rx_if")
    ot_mode = args.get_arg(u"ot_mode")

    rxq = RxQueue(rx_if)
    txq = TxQueue(tx_if)

    pkt_raw = Ether(src=tx_src_mac, dst=tx_dst_mac)

    if valid_ipv4(src_ip) and valid_ipv4(dst_ip):
        pkt_raw /= IP(src=src_ip, dst=dst_ip)
        pkt_raw /= ICMP()
        ip_format = IP
        lisp_layer = LispInnerIP
    elif valid_ipv6(src_ip) and valid_ipv6(dst_ip):
        pkt_raw /= IPv6(src=src_ip, dst=dst_ip)
        pkt_raw /= ICMPv6EchoRequest()
        ip_format = IPv6
        lisp_layer = LispInnerIPv6
    else:
        raise ValueError(u"IP not in correct format")

    bind_layers(UDP, LispHeader, dport=4341)
    bind_layers(LispHeader, lisp_layer)

    pkt_raw /= Raw()
    sent_packets = list()
    sent_packets.append(pkt_raw)
    txq.send(pkt_raw)

    if tx_if == rx_if:
        ether = rxq.recv(2, ignore=sent_packets)
    else:
        ether = rxq.recv(2)

    if ether is None:
        raise RuntimeError(u"ICMP echo Rx timeout")

    if rx_dst_mac == ether[Ether].dst and rx_src_mac == ether[Ether].src:
        print(u"MAC addresses match.")
    else:
        raise RuntimeError(f"Matching packet unsuccessful: {ether!r}")

    ip = ether.payload

    if ot_mode == u"6to4":
        if not isinstance(ip, IP):
            raise RuntimeError(f"Not an IP packet received {ip!r}")
    elif ot_mode == u"4to6":
        if not isinstance(ip, IPv6):
            raise RuntimeError(f"Not an IP packet received {ip!r}")
    elif not isinstance(ip, ip_format):
            raise RuntimeError(f"Not an IP packet received {ip!r}")

    lisp = ether.getlayer(lisp_layer)
    if not lisp:
        raise RuntimeError("Lisp layer not present or parsing failed.")

    # Compare data from packets
    if src_ip == lisp.src:
        print(u"Source IP matches source EID.")
    else:
        raise RuntimeError(
            f"Matching Src IP unsuccessful: {src_ip} != {lisp.src}"
        )

    if dst_ip == lisp.dst:
        print(u"Destination IP matches destination EID.")
    else:
        raise RuntimeError(
            f"Matching Dst IP unsuccessful: {dst_ip} != {lisp.dst}"
        )

    if src_rloc == ip.src:
        print(u"Source RLOC matches configuration.")
    else:
        raise RuntimeError(
            f"Matching Src RLOC unsuccessful: {src_rloc} != {ip.src}"
        )

    if dst_rloc == ip.dst:
        print(u"Destination RLOC matches configuration.")
    else:
        raise RuntimeError(
            f"Matching dst RLOC unsuccessful: {dst_rloc} != {ip.dst}"
        )

    sys.exit(0)
Exemple #23
0
 def frame_reply(self):
     """ Ethernet frame modeling a generic reply """
     return (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') /
             IP(src='4.3.2.1', dst='1.2.3.4') /
             UDP(sport=20000, dport=10000) / Raw('\xa5' * 100))
Exemple #24
0
    def test_l2_emulation(self):
        """ L2 Emulation """

        #
        # non distinct L3 packets, in the tag/non-tag combos
        #
        pkt_no_tag = (Ether(src=self.pg0.remote_mac,
                            dst=self.pg1.remote_mac) /
                      IP(src="2.2.2.2",
                         dst="1.1.1.1") /
                      UDP(sport=1234, dport=1234) /
                      Raw('\xa5' * 100))
        pkt_to_tag = (Ether(src=self.pg0.remote_mac,
                            dst=self.pg2.remote_mac) /
                      IP(src="2.2.2.2",
                         dst="1.1.1.2") /
                      UDP(sport=1234, dport=1234) /
                      Raw('\xa5' * 100))
        pkt_from_tag = (Ether(src=self.pg3.remote_mac,
                              dst=self.pg2.remote_mac) /
                        Dot1Q(vlan=93) /
                        IP(src="2.2.2.2",
                           dst="1.1.1.1") /
                        UDP(sport=1234, dport=1234) /
                        Raw('\xa5' * 100))
        pkt_from_to_tag = (Ether(src=self.pg3.remote_mac,
                                 dst=self.pg2.remote_mac) /
                           Dot1Q(vlan=93) /
                           IP(src="2.2.2.2",
                              dst="1.1.1.2") /
                           UDP(sport=1234, dport=1234) /
                           Raw('\xa5' * 100))
        pkt_bcast = (Ether(src=self.pg0.remote_mac,
                           dst="ff:ff:ff:ff:ff:ff") /
                     IP(src="2.2.2.2",
                        dst="255.255.255.255") /
                     UDP(sport=1234, dport=1234) /
                     Raw('\xa5' * 100))

        #
        # A couple of sub-interfaces for tags
        #
        sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92)
        sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93)
        sub_if_on_pg2.admin_up()
        sub_if_on_pg3.admin_up()

        #
        # Put all the interfaces into a new bridge domain
        #
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg0.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1)
        self.vapi.l2_interface_vlan_tag_rewrite(
            sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
            push_dot1q=92)
        self.vapi.l2_interface_vlan_tag_rewrite(
            sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
            push_dot1q=93)

        #
        # Disable UU flooding, learning and ARP termination. makes this test
        # easier as unicast packets are dropped if not extracted.
        #
        self.vapi.bridge_flags(bd_id=1, is_set=0,
                               flags=(1 << 0) | (1 << 3) | (1 << 4))

        #
        # Add a DVR route to steer traffic at L3
        #
        route_1 = VppIpRoute(self, "1.1.1.1", 32,
                             [VppRoutePath("0.0.0.0",
                                           self.pg1.sw_if_index,
                                           is_dvr=1)])
        route_2 = VppIpRoute(self, "1.1.1.2", 32,
                             [VppRoutePath("0.0.0.0",
                                           sub_if_on_pg2.sw_if_index,
                                           is_dvr=1)])
        route_1.add_vpp_config()
        route_2.add_vpp_config()

        #
        # packets are dropped because bridge does not flood unknown unicast
        #
        self.send_and_assert_no_replies(self.pg0, pkt_no_tag)

        #
        # Enable L3 extraction on pgs
        #
        self.vapi.l2_emulation(self.pg0.sw_if_index)
        self.vapi.l2_emulation(self.pg1.sw_if_index)
        self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index)
        self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index)

        #
        # now we expect the packet forward according to the DVR route
        #
        rx = self.send_and_expect(self.pg0, pkt_no_tag * 65, self.pg1)
        self.assert_same_mac_addr(pkt_no_tag, rx)
        self.assert_has_no_tag(rx)

        rx = self.send_and_expect(self.pg0, pkt_to_tag * 65, self.pg2)
        self.assert_same_mac_addr(pkt_to_tag, rx)
        self.assert_has_vlan_tag(92, rx)

        rx = self.send_and_expect(self.pg3, pkt_from_tag * 65, self.pg1)
        self.assert_same_mac_addr(pkt_from_tag, rx)
        self.assert_has_no_tag(rx)

        rx = self.send_and_expect(self.pg3, pkt_from_to_tag * 65, self.pg2)
        self.assert_same_mac_addr(pkt_from_tag, rx)
        self.assert_has_vlan_tag(92, rx)

        #
        # but broadcast packets are still flooded
        #
        self.send_and_expect(self.pg0, pkt_bcast * 33, self.pg2)

        #
        # cleanup
        #
        self.vapi.l2_emulation(self.pg0.sw_if_index,
                               enable=0)
        self.vapi.l2_emulation(self.pg1.sw_if_index,
                               enable=0)
        self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index,
                               enable=0)
        self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index,
                               enable=0)

        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0)

        route_1.remove_vpp_config()
        route_2.remove_vpp_config()
        sub_if_on_pg3.remove_vpp_config()
        sub_if_on_pg2.remove_vpp_config()
Exemple #25
0
    def test_fif4(self):
        """ Fragments in fragments (4o4) """

        # TODO this should be ideally in setUpClass, but then we hit a bug
        # with VppIpRoute incorrectly reporting it's present when it's not
        # so we need to manually remove the vpp config, thus we cannot have
        # it shared for multiple test cases
        self.tun_ip4 = "1.1.1.2"

        self.gre4 = VppGreInterface(self, self.src_if.local_ip4, self.tun_ip4)
        self.gre4.add_vpp_config()
        self.gre4.admin_up()
        self.gre4.config_ip4()

        self.vapi.ip_reassembly_enable_disable(
            sw_if_index=self.gre4.sw_if_index, enable_ip4=True)

        self.route4 = VppIpRoute(
            self, self.tun_ip4, 32,
            [VppRoutePath(self.src_if.remote_ip4, self.src_if.sw_if_index)])
        self.route4.add_vpp_config()

        self.reset_packet_infos()
        for i in range(test_packet_count):
            info = self.create_packet_info(self.src_if, self.dst_if)
            payload = self.info_to_payload(info)
            # Ethernet header here is only for size calculation, thus it
            # doesn't matter how it's initialized. This is to ensure that
            # reassembled packet is not > 9000 bytes, so that it's not dropped
            p = (Ether() / IP(
                id=i, src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
                 UDP(sport=1234, dport=5678) / Raw(payload))
            size = self.packet_sizes[(i // 2) % len(self.packet_sizes)]
            self.extend_packet(p, size, self.padding)
            info.data = p[IP]  # use only IP part, without ethernet header

        fragments = [
            x for _, p in self._packet_infos.iteritems()
            for x in fragment_rfc791(p.data, 400)
        ]

        encapped_fragments = \
            [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
             IP(src=self.tun_ip4, dst=self.src_if.local_ip4) /
                GRE() /
                p
                for p in fragments]

        fragmented_encapped_fragments = \
            [x for p in encapped_fragments
             for x in fragment_rfc791(p, 200)]

        self.src_if.add_stream(fragmented_encapped_fragments)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        self.src_if.assert_nothing_captured()
        packets = self.dst_if.get_capture(len(self._packet_infos))
        self.verify_capture(packets, IP)

        # TODO remove gre vpp config by hand until VppIpRoute gets fixed
        # so that it's query_vpp_config() works as it should
        self.gre4.remove_vpp_config()
        self.logger.debug(self.vapi.ppcli("show interface"))
Exemple #26
0
    def test_dvr(self):
        """ Distributed Virtual Router """

        #
        # A packet destined to an IP address that is L2 bridged via
        # a non-tag interface
        #
        ip_non_tag_bridged = "10.10.10.10"
        ip_tag_bridged = "10.10.10.11"
        any_src_addr = "1.1.1.1"

        pkt_no_tag = (Ether(src=self.pg0.remote_mac,
                            dst=self.loop0.local_mac) /
                      IP(src=any_src_addr,
                         dst=ip_non_tag_bridged) /
                      UDP(sport=1234, dport=1234) /
                      Raw('\xa5' * 100))
        pkt_tag = (Ether(src=self.pg0.remote_mac,
                         dst=self.loop0.local_mac) /
                   IP(src=any_src_addr,
                      dst=ip_tag_bridged) /
                   UDP(sport=1234, dport=1234) /
                   Raw('\xa5' * 100))

        #
        # Two sub-interfaces so we can test VLAN tag push/pop
        #
        sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92)
        sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93)
        sub_if_on_pg2.admin_up()
        sub_if_on_pg3.admin_up()

        #
        # Put all the interfaces into a new bridge domain
        #
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg0.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg1.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.loop0.sw_if_index, bd_id=1,
            port_type=L2_PORT_TYPE.BVI)

        self.vapi.l2_interface_vlan_tag_rewrite(
            sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
            push_dot1q=92)
        self.vapi.l2_interface_vlan_tag_rewrite(
            sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
            push_dot1q=93)

        #
        # Add routes to bridge the traffic via a tagged an nontagged interface
        #
        route_no_tag = VppIpRoute(
            self, ip_non_tag_bridged, 32,
            [VppRoutePath("0.0.0.0",
                          self.pg1.sw_if_index,
                          is_dvr=1)])
        route_no_tag.add_vpp_config()

        #
        # Inject the packet that arrives and leaves on a non-tagged interface
        # Since it's 'bridged' expect that the MAC headed is unchanged.
        #
        rx = self.send_and_expect(self.pg0, pkt_no_tag * 65, self.pg1)
        self.assert_same_mac_addr(pkt_no_tag, rx)
        self.assert_has_no_tag(rx)

        #
        # Add routes to bridge the traffic via a tagged interface
        #
        route_with_tag = VppIpRoute(
            self, ip_tag_bridged, 32,
            [VppRoutePath("0.0.0.0",
                          sub_if_on_pg3.sw_if_index,
                          is_dvr=1)])
        route_with_tag.add_vpp_config()

        #
        # Inject the packet that arrives non-tag and leaves on a tagged
        # interface
        #
        rx = self.send_and_expect(self.pg0, pkt_tag * 65, self.pg3)
        self.assert_same_mac_addr(pkt_tag, rx)
        self.assert_has_vlan_tag(93, rx)

        #
        # Tag to tag
        #
        pkt_tag_to_tag = (Ether(src=self.pg2.remote_mac,
                                dst=self.loop0.local_mac) /
                          Dot1Q(vlan=92) /
                          IP(src=any_src_addr,
                             dst=ip_tag_bridged) /
                          UDP(sport=1234, dport=1234) /
                          Raw('\xa5' * 100))

        rx = self.send_and_expect(self.pg2, pkt_tag_to_tag * 65, self.pg3)
        self.assert_same_mac_addr(pkt_tag_to_tag, rx)
        self.assert_has_vlan_tag(93, rx)

        #
        # Tag to non-Tag
        #
        pkt_tag_to_non_tag = (Ether(src=self.pg2.remote_mac,
                                    dst=self.loop0.local_mac) /
                              Dot1Q(vlan=92) /
                              IP(src=any_src_addr,
                                 dst=ip_non_tag_bridged) /
                              UDP(sport=1234, dport=1234) /
                              Raw('\xa5' * 100))

        rx = self.send_and_expect(self.pg2, pkt_tag_to_non_tag * 65, self.pg1)
        self.assert_same_mac_addr(pkt_tag_to_tag, rx)
        self.assert_has_no_tag(rx)

        #
        # Add an output L3 ACL that will block the traffic
        #
        rule_1 = ({'is_permit': 0,
                   'is_ipv6': 0,
                   'proto': 17,
                   'srcport_or_icmptype_first': 1234,
                   'srcport_or_icmptype_last': 1234,
                   'src_ip_prefix_len': 32,
                   'src_ip_addr': inet_pton(AF_INET, any_src_addr),
                   'dstport_or_icmpcode_first': 1234,
                   'dstport_or_icmpcode_last': 1234,
                   'dst_ip_prefix_len': 32,
                   'dst_ip_addr': inet_pton(AF_INET, ip_non_tag_bridged)})
        acl = self.vapi.acl_add_replace(acl_index=4294967295,
                                        r=[rule_1])

        #
        # Apply the ACL on the output interface
        #
        self.vapi.acl_interface_set_acl_list(self.pg1.sw_if_index,
                                             0,
                                             [acl.acl_index])

        #
        # Send packet's that should match the ACL and be dropped
        #
        rx = self.send_and_assert_no_replies(self.pg2, pkt_tag_to_non_tag * 65)

        #
        # cleanup
        #
        self.vapi.acl_interface_set_acl_list(self.pg1.sw_if_index,
                                             0, [])
        self.vapi.acl_del(acl.acl_index)

        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0)
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.loop0.sw_if_index, bd_id=1,
            port_type=L2_PORT_TYPE.BVI, enable=0)

        #
        # Do a FIB dump to make sure the paths are correctly reported as DVR
        #
        routes = self.vapi.ip_fib_dump()

        for r in routes:
            if (inet_pton(AF_INET, ip_tag_bridged) == r.address):
                self.assertEqual(r.path[0].sw_if_index,
                                 sub_if_on_pg3.sw_if_index)
                self.assertEqual(r.path[0].is_dvr, 1)
            if (inet_pton(AF_INET, ip_non_tag_bridged) == r.address):
                self.assertEqual(r.path[0].sw_if_index,
                                 self.pg1.sw_if_index)
                self.assertEqual(r.path[0].is_dvr, 1)

        #
        # the explicit route delete is require so it happens before
        # the sbu-interface delete. subinterface delete is required
        # because that object type does not use the object registry
        #
        route_no_tag.remove_vpp_config()
        route_with_tag.remove_vpp_config()
        sub_if_on_pg3.remove_vpp_config()
        sub_if_on_pg2.remove_vpp_config()
Exemple #27
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.
        #
        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,
                         type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
                         next_hop_id=udp_encap_0.id)
        ])
        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)
        ])
        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)
        ])
        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)
        ])
        route_4o6.add_vpp_config()
        route_6o6.add_vpp_config()
        route_6o4.add_vpp_config()
        route_4o4.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 * NUM_PKTS, 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'], NUM_PKTS)

        #
        # 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 * 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('\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('\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('\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)
Exemple #28
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,
                                            QOS_SOURCE.IP, 1)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          QOS_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) * 65))
        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) * 65))

        rx = self.send_and_expect(self.pg0, p_1 * 65, 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 * 65, 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,
                                            QOS_SOURCE.MPLS, 1)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_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) * 65))

        rx = self.send_and_expect(self.pg0, p_m1 * 65, 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) * 65))

        rx = self.send_and_expect(self.pg0, p_m2 * 65, 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,
                                            QOS_SOURCE.IP, 0)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index,
                                          QOS_SOURCE.MPLS, 1, 0)
        self.vapi.qos_record_enable_disable(self.pg0.sw_if_index,
                                            QOS_SOURCE.MPLS, 0)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP,
                                          1, 0)
        self.vapi.qos_egress_map_delete(1)
Exemple #29
0
    def test_punt_socket_traffic_single_port_single_socket(self):
        """ Punt socket traffic single port single socket"""

        port = self.ports[0]
        pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
        af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
        udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
        punt_l4 = {
            'type': pt_l4,
            'punt': {
                'l4': {
                    'af': af_ip6,
                    'protocol': udp_proto,
                    'port': port,
                }
            }
        }

        p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
             inet6.UDP(sport=9876, dport=port) / Raw('\xa5' * 100))

        pkts = p * self.nr_packets

        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), 0)

        #
        # expect ICMPv6 - destination unreachable for all packets
        #
        self.vapi.cli("clear trace")
        self.pg0.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        # FIXME - when punt socket deregister is implemented
        # rx = self.pg0.get_capture(self.nr_packets)
        # for p in rx:
        #     self.assertEqual(int(p[IPv6].nh), 58)                # ICMPv6
        #     self.assertEqual(int(p[ICMPv6DestUnreach].code),4)  # unreachable

        #
        # configure a punt socket
        #
        self.socket_client_create(b"%s/socket_%d" %
                                  (six.ensure_binary(self.tempdir), port))
        self.vapi.punt_socket_register(
            punt_l4, b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), 1)

        #
        # expect punt socket and no packets on pg0
        #
        self.vapi.cli("clear errors")
        self.vapi.cli("clear trace")
        self.pg0.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        self.pg0.get_capture(0)
        self.logger.info(self.vapi.cli("show trace"))
        rx = self.socket_client_close()
        self.verify_udp_pkts(rx, len(pkts), port)

        #
        # remove punt socket. expect ICMP - dest. unreachable for all packets
        #
        self.vapi.punt_socket_deregister(punt_l4)
        punts = self.vapi.punt_socket_dump(type=pt_l4)
        self.assertEqual(len(punts), 0)
        self.pg0.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
Exemple #30
0
    def test_qos_vlan(self):
        """QoS mark/record VLAN """

        #
        # QoS for all input values
        #
        output = [scapy.compat.chb(0)] * 256
        for i in range(0, 255):
            output[i] = scapy.compat.chb(255 - i)
        os = b''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(1, rows)

        sub_if = VppDot1QSubint(self, self.pg0, 11)

        sub_if.admin_up()
        sub_if.config_ip4()
        sub_if.resolve_arp()
        sub_if.config_ip6()
        sub_if.resolve_ndp()

        #
        # enable VLAN QoS recording/marking on the input Pg0 subinterface and
        #
        self.vapi.qos_record_enable_disable(sub_if.sw_if_index,
                                            QOS_SOURCE.VLAN, 1)
        self.vapi.qos_mark_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN,
                                          1, 1)

        #
        # IP marking/recording on pg1
        #
        self.vapi.qos_record_enable_disable(self.pg1.sw_if_index,
                                            QOS_SOURCE.IP, 1)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP,
                                          1, 1)

        #
        # a routes to/from sub-interface
        #
        route_10_0_0_1 = VppIpRoute(
            self, "10.0.0.1", 32,
            [VppRoutePath(sub_if.remote_ip4, sub_if.sw_if_index)])
        route_10_0_0_1.add_vpp_config()
        route_10_0_0_2 = VppIpRoute(
            self, "10.0.0.2", 32,
            [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)])
        route_10_0_0_2.add_vpp_config()
        route_2001_1 = VppIpRoute(
            self,
            "2001::1",
            128, [
                VppRoutePath(sub_if.remote_ip6,
                             sub_if.sw_if_index,
                             proto=DpoProto.DPO_PROTO_IP6)
            ],
            is_ip6=1)
        route_2001_1.add_vpp_config()
        route_2001_2 = VppIpRoute(
            self,
            "2001::2",
            128, [
                VppRoutePath(self.pg1.remote_ip6,
                             self.pg1.sw_if_index,
                             proto=DpoProto.DPO_PROTO_IP6)
            ],
            is_ip6=1)
        route_2001_2.add_vpp_config()

        p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                Dot1Q(vlan=11, prio=1) /
                IP(src="1.1.1.1", dst="10.0.0.2", tos=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))

        p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
                IP(src="1.1.1.1", dst="10.0.0.1", tos=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))

        rx = self.send_and_expect(self.pg1, p_v2 * 65, self.pg0)

        for p in rx:
            self.assertEqual(p[Dot1Q].prio, 6)

        rx = self.send_and_expect(self.pg0, p_v1 * 65, self.pg1)

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

        p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                Dot1Q(vlan=11, prio=2) /
                IPv6(src="2001::1", dst="2001::2", tc=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))

        p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
                IPv6(src="3001::1", dst="2001::1", tc=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))

        rx = self.send_and_expect(self.pg1, p_v2 * 65, self.pg0)

        for p in rx:
            self.assertEqual(p[Dot1Q].prio, 6)

        rx = self.send_and_expect(self.pg0, p_v1 * 65, self.pg1)

        for p in rx:
            self.assertEqual(p[IPv6].tc, 253)

        #
        # cleanup
        #
        sub_if.unconfig_ip4()
        sub_if.unconfig_ip6()

        self.vapi.qos_record_enable_disable(sub_if.sw_if_index,
                                            QOS_SOURCE.VLAN, 0)
        self.vapi.qos_mark_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN,
                                          1, 0)
        self.vapi.qos_record_enable_disable(self.pg1.sw_if_index,
                                            QOS_SOURCE.IP, 0)
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP,
                                          1, 0)
Exemple #31
0
    def test_traffic(self):
        """ Punt socket traffic """

        port = self.ports[0]
        pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
        punt_ex = {'type': pt_ex, 'punt': {'exception': {}}}

        #
        # we need an IPSec tunnels for this to work otherwise ESP gets dropped
        # due to unknown IP proto
        #
        VppIpsecTunInterface(
            self, self.pg0, 1000, 1000,
            (VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128
             ), "0123456701234567", "0123456701234567",
            (VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96),
            "0123456701234567", "0123456701234567").add_vpp_config()
        VppIpsecTunInterface(
            self,
            self.pg0,
            1001,
            1001,
            (VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128
             ),
            "0123456701234567",
            "0123456701234567",
            (VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96),
            "0123456701234567",
            "0123456701234567",
            udp_encap=True).add_vpp_config()

        #
        # we're dealing with IPSec tunnels punting for no-such-tunnel
        # adn SPI=0
        #
        cfgs = dict()
        cfgs['ipsec4-no-such-tunnel'] = {'spi': 99, 'udp': False}
        cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}

        #
        # find the VPP ID for these punt exception reasin
        #
        rs = self.vapi.punt_reason_dump()
        for key in cfgs:
            for r in rs:
                if r.reason.name == key:
                    cfgs[key]['id'] = r.reason.id
                    cfgs[key]['vpp'] = copy.deepcopy(
                        set_reason(punt_ex, cfgs[key]['id']))
                    break

        #
        # configure punt sockets
        #
        for cfg in cfgs.values():
            cfg['sock'] = self.socket_client_create(
                b"%s/socket_%d" % (six.ensure_binary(self.tempdir), cfg['id']))
            self.vapi.punt_socket_register(
                cfg['vpp'],
                b"%s/socket_%d" % (six.ensure_binary(self.tempdir), cfg['id']))

        #
        # create packet streams for 'no-such-tunnel' exception
        #
        for cfg in cfgs.values():
            pkt = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                   IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
            if (cfg['udp']):
                pkt = pkt / UDP(sport=666, dport=4500)
            pkt = (pkt / ESP(spi=cfg['spi'], seq=3) / Raw('\xa5' * 100))
            cfg['pkts'] = [pkt]

        #
        # send packets for each SPI we expect to be punted
        #
        for cfg in cfgs.values():
            self.send_and_assert_no_replies(self.pg0, cfg['pkts'])

        #
        # verify the punted packets arrived on the associated socket
        #
        for cfg in cfgs.values():
            rx = cfg['sock'].close()
            self.verify_esp_pkts(rx, len(cfg['pkts']), cfg['spi'], cfg['udp'])

        #
        # socket deregister
        #
        for cfg in cfgs.values():
            self.vapi.punt_socket_deregister(cfg['vpp'])
Exemple #32
0
    def test_qos_ip(self):
        """ QoS Mark/Record IP """

        #
        # for table 1 map the n=0xff possible values of input QoS mark,
        # n to 1-n
        #
        output = [scapy.compat.chb(0)] * 256
        for i in range(0, 255):
            output[i] = scapy.compat.chb(255 - i)
        os = b''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(1, rows)

        #
        # For table 2 (and up) use the value n for everything
        #
        output = [scapy.compat.chb(2)] * 256
        os = b''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(2, rows)

        output = [scapy.compat.chb(3)] * 256
        os = b''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(3, rows)

        output = [scapy.compat.chb(4)] * 256
        os = b''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]
        self.vapi.qos_egress_map_update(4, rows)
        self.vapi.qos_egress_map_update(5, rows)
        self.vapi.qos_egress_map_update(6, rows)
        self.vapi.qos_egress_map_update(7, rows)

        self.logger.info(self.vapi.cli("sh qos eg map"))

        #
        # Bind interface pgN to table n
        #
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP,
                                          1, 1)
        self.vapi.qos_mark_enable_disable(self.pg2.sw_if_index, QOS_SOURCE.IP,
                                          2, 1)
        self.vapi.qos_mark_enable_disable(self.pg3.sw_if_index, QOS_SOURCE.IP,
                                          3, 1)
        self.vapi.qos_mark_enable_disable(self.pg4.sw_if_index, QOS_SOURCE.IP,
                                          4, 1)

        #
        # packets ingress on Pg0
        #
        p_v4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, tos=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))
        p_v6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6, tc=1) /
                UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * 65))

        #
        # Since we have not yet enabled the recording of the input QoS
        # from the input iP header, the egress packet's ToS will be unchanged
        #
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 1)
        rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IPv6].tc, 1)

        #
        # Enable QoS recrding on IP input for pg0
        #
        self.vapi.qos_record_enable_disable(self.pg0.sw_if_index,
                                            QOS_SOURCE.IP, 1)

        #
        # send the same packets, this time expect the input TOS of 1
        # to be mapped to pg1's egress value of 254
        #
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 254)
        rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IPv6].tc, 254)

        #
        # different input ToS to test the mapping
        #
        p_v4[IP].tos = 127
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 128)
        p_v6[IPv6].tc = 127
        rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IPv6].tc, 128)

        p_v4[IP].tos = 254
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 1)
        p_v6[IPv6].tc = 254
        rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IPv6].tc, 1)

        #
        # send packets out the other interfaces to test the maps are
        # correctly applied
        #
        p_v4[IP].dst = self.pg2.remote_ip4
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg2)
        for p in rx:
            self.assertEqual(p[IP].tos, 2)

        p_v4[IP].dst = self.pg3.remote_ip4
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg3)
        for p in rx:
            self.assertEqual(p[IP].tos, 3)

        p_v6[IPv6].dst = self.pg3.remote_ip6
        rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg3)
        for p in rx:
            self.assertEqual(p[IPv6].tc, 3)

        #
        # remove the map on pg2 and pg3, now expect an unchanged IP tos
        #
        self.vapi.qos_mark_enable_disable(self.pg2.sw_if_index, QOS_SOURCE.IP,
                                          2, 0)
        self.vapi.qos_mark_enable_disable(self.pg3.sw_if_index, QOS_SOURCE.IP,
                                          3, 0)
        self.logger.info(self.vapi.cli("sh int feat pg2"))

        p_v4[IP].dst = self.pg2.remote_ip4
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg2)
        for p in rx:
            self.assertEqual(p[IP].tos, 254)

        p_v4[IP].dst = self.pg3.remote_ip4
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg3)
        for p in rx:
            self.assertEqual(p[IP].tos, 254)

        #
        # still mapping out of pg1
        #
        p_v4[IP].dst = self.pg1.remote_ip4
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 1)

        #
        # disable the input recording on pg0
        #
        self.vapi.qos_record_enable_disable(self.pg0.sw_if_index,
                                            QOS_SOURCE.IP, 0)

        #
        # back to an unchanged TOS value
        #
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 254)

        #
        # disable the egress map on pg1 and pg4
        #
        self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP,
                                          1, 0)
        self.vapi.qos_mark_enable_disable(self.pg4.sw_if_index, QOS_SOURCE.IP,
                                          4, 0)

        #
        # unchanged Tos on pg1
        #
        rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1)
        for p in rx:
            self.assertEqual(p[IP].tos, 254)

        #
        # clean-up the masp
        #
        self.vapi.qos_egress_map_delete(1)
        self.vapi.qos_egress_map_delete(4)
        self.vapi.qos_egress_map_delete(2)
        self.vapi.qos_egress_map_delete(3)
        self.vapi.qos_egress_map_delete(5)
        self.vapi.qos_egress_map_delete(6)
        self.vapi.qos_egress_map_delete(7)