Пример #1
0
    def create_packet_header_IPv6_SRH_L2(self, srcaddr, sidlist, segleft,
                                         vlan=0):
        """Create packet header: L2 encapsulated in SRv6:
        IPv6 header with SRH, L2

        :param int srcaddr: IPv6 source address
        :param list sidlist: segment list of outer IPv6 SRH
        :param int segleft: segments-left field of outer IPv6 SRH
        :param vlan: L2 vlan; if vlan!=0 then add 802.1q header

        IPv6 source address is set to srcaddr
        IPv6 destination address is set to sidlist[segleft]
        """
        eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
        etype = 0x8137  # IPX
        if vlan:
            # add 802.1q layer
            eth /= Dot1Q(vlan=vlan, type=etype)
        else:
            eth.type = etype

        p = IPv6(src=srcaddr, dst=sidlist[segleft]) / \
            IPv6ExtHdrSegmentRouting(addresses=sidlist,
                                     segleft=segleft, nh=59) / \
            eth
        return p
Пример #2
0
    def create_stream(self, src_if=None, dst_if=None, packets=None,
                      size=None, ip_ver='v4'):
        """Create a packet stream to tickle the plugin

        :param VppInterface src_if: Source interface for packet stream
        :param VppInterface src_if: Dst interface for packet stream
        """
        if src_if is None:
            src_if = self.pg1
        if dst_if is None:
            dst_if = self.pg2
        self.pkts = []
        if packets is None:
            packets = random.randint(1, self.max_number_of_packets)
        pkt_size = size
        for p in range(0, packets):
            if size is None:
                pkt_size = random.choice(self.pg_if_packet_sizes)
            info = self.create_packet_info(src_if, dst_if)
            payload = self.info_to_payload(info)
            p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
            if ip_ver == 'v4':
                p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
            else:
                p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
            p /= UDP(sport=1234, dport=4321)
            p /= Raw(payload)
            info.data = p.copy()
            self.extend_packet(p, pkt_size)
            self.pkts.append(p)
Пример #3
0
    def test_from_frame(self):
        e = Ether(src='00:01:02:03:04:05', dst='AA:BB:CC:DD:EE:FF')
        e.add_payload("thisisapayload")
        frame = str(e)

        vx = VXLAN(frame=frame, vni=123)
        self.assertEqual(vx.vni, 123)
        self.assertEqual(str(vx),
            "\x08\x00\x00\x00\x00\x00\x7b\x00" + frame)
Пример #4
0
    def send_frame(self, frame_body):
        PACKET = Ether()
        PACKET.length = 64
        PACKET.dst = self.dst
        PACKET.src = self.getHwAddr(self.interface)
        if self.stag:
            # WARNING: September/2016: This should be 0x88a8, but the Intel 10G
            # hardware I am currently using does not support receiving a TPID of
            # 0x88a8. So, I send double CTAGs, and I usually set this to 0x8100.
            # (NOTE: The Intel hardware can send a TPID of 0x88a8)
            PACKET.type = 0x8100
            if self.ctag:
                PACKET/=Dot1Q(type=0x8100,vlan=int(self.stag))
                PACKET/=Dot1Q(type=self.etype,vlan=int(self.ctag))
            else:
                PACKET/=Dot1Q(type=self.etype,vlan=int(self.stag))
        else:
            if self.ctag:
                PACKET.type = 0x8100
                PACKET/=Dot1Q(type=self.etype,vlan=int(self.ctag))
            else:
                PACKET.type = self.etype
#            PACKET/=Dot1Q(type=self.etype, vlan=int(self.ctag))
        PACKET/=SlowProtocolsSubtype()/FlagsBytes()/OAMPDU()
        PACKET/=frame_body
        PACKET/=EndOfPDU()
        if (self.verbose == True):
            PACKET.show()
            print '###[ Frame Length %d (before padding) ]###' % len(PACKET)
        if (self.hexdump == True):
            print hexdump(PACKET)
        if (self.dryrun != True):
            sendp(PACKET, iface=self.interface, verbose=self.verbose)
            time.sleep(self.sleep)
        return PACKET
Пример #5
0
    def test_from_packet(self):
        e = Ether(src='00:01:02:03:04:05', dst='AA:BB:CC:DD:EE:FF')
        e.add_payload("thisisapayload")
        frame = str(e)

        packet = "\x08\x00\x00\x00\x00\x00\x7c\x00" + frame
        vx = VXLAN(packet=packet)
        self.assertEqual(vx.vni, 124)
        self.assertEqual(str(vx.frame), frame)
        self.assertEqual(str(vx), packet)
        self.assertEqual(vx.src_mac, "00:01:02:03:04:05")
        self.assertEqual(vx.dst_mac, "AA:BB:CC:DD:EE:FF")
Пример #6
0
    def create_packet_header_L2(self, vlan=0):
        """Create packet header: L2 header

        :param vlan: if vlan!=0 then add 802.1q header
        """
        # Note: the dst addr ('00:55:44:33:22:11') is used in
        # the compare function compare_rx_tx_packet_T_Encaps_L2
        # to detect presence of L2 in SRH payload
        p = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
        etype = 0x8137  # IPX
        if vlan:
            # add 802.1q layer
            p /= Dot1Q(vlan=vlan, type=etype)
        else:
            p.type = etype
        return p
Пример #7
0
    def create_stream(self, src_if, dst_if, packet_header, packet_sizes,
                      count):
        """Create SRv6 input packet stream for defined interface.

        :param VppInterface src_if: Interface to create packet stream for
        :param VppInterface dst_if: destination interface of packet stream
        :param packet_header: Layer3 scapy packet headers,
                L2 is added when not provided,
                Raw(payload) with packet_info is added
        :param list packet_sizes: packet stream pckt sizes,sequentially applied
               to packets in stream have
        :param int count: number of packets in packet stream
        :return: list of packets
        """
        self.logger.info("Creating packets")
        pkts = []
        for i in range(0, count-1):
            payload_info = self.create_packet_info(src_if, dst_if)
            self.logger.debug(
                "Creating packet with index %d" % (payload_info.index))
            payload = self.info_to_payload(payload_info)
            # add L2 header if not yet provided in packet_header
            if packet_header.getlayer(0).name == 'Ethernet':
                p = (packet_header /
                     Raw(payload))
            else:
                p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
                     packet_header /
                     Raw(payload))
            size = packet_sizes[i % len(packet_sizes)]
            self.logger.debug("Packet size %d" % (size))
            self.extend_packet(p, size)
            # we need to store the packet with the automatic fields computed
            # read back the dumped packet (with str())
            # to force computing these fields
            # probably other ways are possible
            p = Ether(scapy.compat.raw(p))
            payload_info.data = p.copy()
            self.logger.debug(ppp("Created packet:", p))
            pkts.append(p)
        self.logger.info("Done creating packets")
        return pkts
 def on_pkt_rx (self, pkt):
     scapy_pkt = Ether(pkt['binary'])
     if not 'ICMP' in scapy_pkt:
         return None
     
     #scapy_pkt.show2()    
     ip = scapy_pkt['IP']
     
     icmp = scapy_pkt['ICMP']
     
     dt = pkt['ts'] - self.start_ts
     
     if icmp.type == 0:
         # echo reply
         return self.port.ok('Reply from {0}: bytes={1}, time={2:.2f}ms, TTL={3}'.format(ip.src, len(pkt['binary']), dt * 1000, ip.ttl))
         
     # unreachable
     elif icmp.type == 3:
         return self.port.ok('Reply from {0}: Destination host unreachable'.format(icmp.src))
     else:
         scapy_pkt.show2()
         return self.port.err('unknown ICMP reply')
Пример #9
0
    def cpu_port_handler(self, packet, psock):
        eth = Ether(packet)
        if not self.running:
            raise Exception('stop')

        if not eth.haslayer(bgp.BGPUpdate):
            # Release the packet.
            psock.send(packet)
            return

        #log("Get BGP update packet: {}".format(eth.summary()), "yellow")

        update = eth[bgp.BGPUpdate]

        # Flag to determine whether this packet should be stopped.
        quarantine = False
        drop = False
        quarantine_key = None

        while True:
            # Check if this path_attr ends at a different AS compared to
            # known for this prefix, and if so, quarantine this BGP update packet.

            p = [
                path_attr for path_attr in update.path_attr
                if path_attr.type_code == AS_PATH
            ]
            if len(p) > 0:
                s = [
                    path.segment_value for path in p[0].attribute.segments
                    if path.segment_type == AS_SEQUENCE
                ]
                if len(s) > 0:
                    # Get the destination AS in each sequence. Assert that they are all the same.
                    dest = [seq[-1] for seq in s]
                    assert (all(d == dest[0] for d in dest))
                    if dest[0] in self.blocked_as:
                        log(
                            "Dropping packet announcing blocked AS {}.".format(
                                dest[0]), "red")
                        drop = True
                        break
                    if dest[0] != 0:
                        for dest_prefix in [
                                nlri.prefix for nlri in update.nlri
                        ]:
                            #print("Announcement for prefix {}:".format(dest_prefix))
                            #print(s)
                            if dest_prefix.split('.')[0] == 9:
                                continue  # TODO: this skips the internal network. Should be fixed with CIDR below.
                            if (dest[0], dest_prefix.split('.')[0]
                                ) in self.quarantined:
                                drop = True  # Ignore this packet that's advertising a quarantined route.
                            elif dest_prefix in self.routing_table and self.routing_table[
                                    dest_prefix] != dest[0]:
                                log(
                                    "Delay AS {} announcing prefix {}.".format(
                                        dest[0], dest_prefix), "red")

                                # Ideally, we should look through all of the updates and notify all the
                                # ASes being targeted in a single update. For now though, we only notify
                                # the first, and similarly unblock the AS when this is done.

                                # Hardcode the prefix to /8. This needs modification on the P4 side to support
                                # proper CIDR.
                                quarantine_key = (dest[0],
                                                  dest_prefix.split('.')[0])
                                if not quarantine_key in self.allowed:
                                    quarantine = True
                                break
                            else:
                                log("Route {}: {}".format(dest_prefix, s[0]))
                                self.routing_table[dest_prefix] = dest[0]

            if not update.haslayer(
                    bgp.BGPHeader) or not update[bgp.BGPHeader].haslayer(
                        bgp.BGPUpdate):
                break
            else:
                # next update
                update = update[bgp.BGPHeader][bgp.BGPUpdate]

        if drop:
            pass  # blackhole
        elif not quarantine:
            psock.send(packet)
        elif not quarantine_key in self.quarantined:
            self.quarantined[quarantine_key] = int(
                time.time()) + _QUARANTINE_EXPIRATION_SEC
            (gap, prefix) = quarantine_key
            self.add_slice(prefix, gap)
Пример #10
0
async def run_test(dut):

    tb = TB(dut)

    await tb.init()

    tb.log.info("test UDP RX packet")

    payload = bytes([x % 256 for x in range(256)])
    eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
    ip = IP(src='192.168.1.100', dst='192.168.1.128')
    udp = UDP(sport=5678, dport=1234)
    test_pkt = eth / ip / udp / payload

    test_frame = XgmiiFrame.from_payload(test_pkt.build())

    await tb.qsfp_0_0_source.send(test_frame)

    tb.log.info("receive ARP request")

    rx_frame = await tb.qsfp_0_0_sink.recv()

    rx_pkt = Ether(bytes(rx_frame.get_payload()))

    tb.log.info("RX packet: %s", repr(rx_pkt))

    assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff'
    assert rx_pkt.src == test_pkt.dst
    assert rx_pkt[ARP].hwtype == 1
    assert rx_pkt[ARP].ptype == 0x0800
    assert rx_pkt[ARP].hwlen == 6
    assert rx_pkt[ARP].plen == 4
    assert rx_pkt[ARP].op == 1
    assert rx_pkt[ARP].hwsrc == test_pkt.dst
    assert rx_pkt[ARP].psrc == test_pkt[IP].dst
    assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00'
    assert rx_pkt[ARP].pdst == test_pkt[IP].src

    tb.log.info("send ARP response")

    eth = Ether(src=test_pkt.src, dst=test_pkt.dst)
    arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2,
        hwsrc=test_pkt.src, psrc=test_pkt[IP].src,
        hwdst=test_pkt.dst, pdst=test_pkt[IP].dst)
    resp_pkt = eth / arp

    resp_frame = XgmiiFrame.from_payload(resp_pkt.build())

    await tb.qsfp_0_0_source.send(resp_frame)

    tb.log.info("receive UDP packet")

    rx_frame = await tb.qsfp_0_0_sink.recv()

    rx_pkt = Ether(bytes(rx_frame.get_payload()))

    tb.log.info("RX packet: %s", repr(rx_pkt))

    assert rx_pkt.dst == test_pkt.src
    assert rx_pkt.src == test_pkt.dst
    assert rx_pkt[IP].dst == test_pkt[IP].src
    assert rx_pkt[IP].src == test_pkt[IP].dst
    assert rx_pkt[UDP].dport == test_pkt[UDP].sport
    assert rx_pkt[UDP].sport == test_pkt[UDP].dport
    assert rx_pkt[UDP].payload == test_pkt[UDP].payload

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)
Пример #11
0
    def test_gbp(self):
        """ Group Based Policy """

        nat_table = VppIpTable(self, 20)
        nat_table.add_vpp_config()
        nat_table = VppIpTable(self, 20, is_ip6=True)
        nat_table.add_vpp_config()

        #
        # Bridge Domains
        #
        self.vapi.bridge_domain_add_del(1,
                                        flood=1,
                                        uu_flood=1,
                                        forward=1,
                                        learn=0,
                                        arp_term=1,
                                        is_add=1)
        self.vapi.bridge_domain_add_del(2,
                                        flood=1,
                                        uu_flood=1,
                                        forward=1,
                                        learn=0,
                                        arp_term=1,
                                        is_add=1)
        self.vapi.bridge_domain_add_del(20,
                                        flood=1,
                                        uu_flood=1,
                                        forward=1,
                                        learn=0,
                                        arp_term=1,
                                        is_add=1)

        #
        # 3 EPGs, 2 of which share a BD.
        # 2 NAT EPGs, one for floating-IP subnets, the other for internet
        #
        epgs = [
            VppGbpEndpointGroup(self, 220, 0, 1, self.pg4, self.loop0,
                                "10.0.0.128", "2001:10::128"),
            VppGbpEndpointGroup(self, 221, 0, 1, self.pg5, self.loop0,
                                "10.0.1.128", "2001:10:1::128"),
            VppGbpEndpointGroup(self, 222, 0, 2, self.pg6, self.loop1,
                                "10.0.2.128", "2001:10:2::128"),
            VppGbpEndpointGroup(self, 333, 20, 20, self.pg7, self.loop2,
                                "11.0.0.128", "3001::128"),
            VppGbpEndpointGroup(self, 444, 20, 20, self.pg8, self.loop2,
                                "11.0.0.129", "3001::129")
        ]
        recircs = [
            VppGbpRecirc(self, epgs[0], self.loop3),
            VppGbpRecirc(self, epgs[1], self.loop4),
            VppGbpRecirc(self, epgs[2], self.loop5),
            VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
            VppGbpRecirc(self, epgs[4], self.loop8, is_ext=True)
        ]

        epg_nat = epgs[3]
        recirc_nat = recircs[3]

        #
        # 4 end-points, 2 in the same subnet, 3 in the same BD
        #
        eps = [
            VppGbpEndpoint(self, self.pg0, epgs[0], recircs[0], "10.0.0.1",
                           "11.0.0.1", "2001:10::1", "3001::1"),
            VppGbpEndpoint(self, self.pg1, epgs[0], recircs[0], "10.0.0.2",
                           "11.0.0.2", "2001:10::2", "3001::2"),
            VppGbpEndpoint(self, self.pg2, epgs[1], recircs[1], "10.0.1.1",
                           "11.0.0.3", "2001:10:1::1", "3001::3"),
            VppGbpEndpoint(self, self.pg3, epgs[2], recircs[2], "10.0.2.1",
                           "11.0.0.4", "2001:10:2::1", "3001::4")
        ]

        #
        # Config related to each of the EPGs
        #
        for epg in epgs:
            # IP config on the BVI interfaces
            if epg != epgs[1] and epg != epgs[4]:
                epg.bvi.set_table_ip4(epg.rd)
                epg.bvi.set_table_ip6(epg.rd)

                # The BVIs are NAT inside interfaces
                self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
                                                          is_inside=1,
                                                          is_add=1)
                self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
                                                  is_inside=1,
                                                  is_add=1)

            self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
                                                   epg.bvi_ip4_n, 32)
            self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
                                                   epg.bvi_ip6_n,
                                                   128,
                                                   is_ipv6=True)

            # EPG uplink interfaces in the BD
            epg.uplink.set_table_ip4(epg.rd)
            epg.uplink.set_table_ip6(epg.rd)
            self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index,
                                                 epg.bd)

            # add the BD ARP termination entry for BVI IP
            self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
                                        mac=mactobinary(self.router_mac),
                                        ip=epg.bvi_ip4_n,
                                        is_ipv6=0,
                                        is_add=1)
            self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
                                        mac=mactobinary(self.router_mac),
                                        ip=epg.bvi_ip6_n,
                                        is_ipv6=1,
                                        is_add=1)

            # epg[1] shares the same BVI to epg[0]
            if epg != epgs[1] and epg != epgs[4]:
                # BVI in BD
                self.vapi.sw_interface_set_l2_bridge(
                    epg.bvi.sw_if_index, epg.bd, port_type=L2_PORT_TYPE.BVI)

                # BVI L2 FIB entry
                self.vapi.l2fib_add_del(self.router_mac,
                                        epg.bd,
                                        epg.bvi.sw_if_index,
                                        is_add=1,
                                        bvi_mac=1)

            # EPG in VPP
            epg.add_vpp_config()

        for recirc in recircs:
            # EPG's ingress recirculation interface maps to its RD
            recirc.recirc.set_table_ip4(recirc.epg.rd)
            recirc.recirc.set_table_ip6(recirc.epg.rd)

            # in the bridge to allow DVR. L2 emulation to punt to L3
            self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index,
                                                 recirc.epg.bd)
            self.vapi.sw_interface_set_l2_emulation(recirc.recirc.sw_if_index)

            self.vapi.nat44_interface_add_del_feature(
                recirc.recirc.sw_if_index, is_inside=0, is_add=1)
            self.vapi.nat66_add_del_interface(recirc.recirc.sw_if_index,
                                              is_inside=0,
                                              is_add=1)

            recirc.add_vpp_config()

        ep_routes = []
        ep_arps = []
        for ep in eps:
            self.pg_enable_capture(self.pg_interfaces)
            self.pg_start()
            #
            # routes to the endpoints. We need these since there are no
            # adj-fibs due to the fact the the BVI address has /32 and
            # the subnet is not attached.
            #
            for (ip, fip) in zip(ep.ips, ep.fips):
                r = VppIpRoute(self,
                               ip.address,
                               ip.length, [
                                   VppRoutePath(ip.address,
                                                ep.epg.bvi.sw_if_index,
                                                proto=ip.dpo_proto)
                               ],
                               is_ip6=ip.is_ip6)
                r.add_vpp_config()
                ep_routes.append(r)

                #
                # ARP entries for the endpoints
                #
                a = VppNeighbor(self,
                                ep.epg.bvi.sw_if_index,
                                ep.itf.remote_mac,
                                ip.address,
                                af=ip.af)
                a.add_vpp_config()
                ep_arps.append(a)

                # add the BD ARP termination entry
                self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd,
                                            mac=ep.bin_mac,
                                            ip=ip.bytes,
                                            is_ipv6=ip.is_ip6,
                                            is_add=1)

                # Add static mappings for each EP from the 10/8 to 11/8 network
                if ip.af == AF_INET:
                    self.vapi.nat44_add_del_static_mapping(ip.bytes,
                                                           fip.bytes,
                                                           vrf_id=0,
                                                           addr_only=1)
                else:
                    self.vapi.nat66_add_del_static_mapping(ip.bytes,
                                                           fip.bytes,
                                                           vrf_id=0)

            # add each EP itf to the its BD
            self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index, ep.epg.bd)

            # L2 FIB entry
            self.vapi.l2fib_add_del(ep.mac,
                                    ep.epg.bd,
                                    ep.itf.sw_if_index,
                                    is_add=1)

            # VPP EP create ...
            ep.add_vpp_config()

            self.logger.info(self.vapi.cli("sh gbp endpoint"))

            # ... results in a Gratuitous ARP/ND on the EPG's uplink
            rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)

            for ii, ip in enumerate(ep.ips):
                p = rx[ii]

                if ip.is_ip6:
                    self.assertTrue(p.haslayer(ICMPv6ND_NA))
                    self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
                else:
                    self.assertTrue(p.haslayer(ARP))
                    self.assertEqual(p[ARP].psrc, ip.address)
                    self.assertEqual(p[ARP].pdst, ip.address)

            # add the BD ARP termination entry for floating IP
            for fip in ep.fips:
                self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd,
                                            mac=ep.bin_mac,
                                            ip=fip.bytes,
                                            is_ipv6=fip.is_ip6,
                                            is_add=1)

                # floating IPs route via EPG recirc
                r = VppIpRoute(self,
                               fip.address,
                               fip.length, [
                                   VppRoutePath(fip.address,
                                                ep.recirc.recirc.sw_if_index,
                                                is_dvr=1,
                                                proto=fip.dpo_proto)
                               ],
                               table_id=20,
                               is_ip6=fip.is_ip6)
                r.add_vpp_config()
                ep_routes.append(r)

            # L2 FIB entries in the NAT EPG BD to bridge the packets from
            # the outside direct to the internal EPG
            self.vapi.l2fib_add_del(ep.mac,
                                    epg_nat.bd,
                                    ep.recirc.recirc.sw_if_index,
                                    is_add=1)

        #
        # ARP packets for unknown IP are flooded
        #
        pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
                   ARP(op="who-has",
                       hwdst="ff:ff:ff:ff:ff:ff",
                       hwsrc=self.pg0.remote_mac,
                       pdst=epgs[0].bvi_ip4,
                       psrc="10.0.0.88"))

        self.send_and_expect(self.pg0, [pkt_arp], self.pg0)

        #
        # ARP/ND packets get a response
        #
        pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
                   ARP(op="who-has",
                       hwdst="ff:ff:ff:ff:ff:ff",
                       hwsrc=self.pg0.remote_mac,
                       pdst=epgs[0].bvi_ip4,
                       psrc=eps[0].ip4.address))

        self.send_and_expect(self.pg0, [pkt_arp], self.pg0)

        nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
        d = inet_ntop(AF_INET6, nsma)
        pkt_nd = (Ether(dst=in6_getnsmac(nsma)) /
                  IPv6(dst=d, src=eps[0].ip6.address) /
                  ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
                  ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
        self.send_and_expect(self.pg0, [pkt_nd], self.pg0)

        #
        # broadcast packets are flooded
        #
        pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
                     IP(src=eps[0].ip4.address, dst="232.1.1.1") /
                     UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.vapi.cli("clear trace")
        self.pg0.add_stream(pkt_bcast)

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

        rxd = eps[1].itf.get_capture(1)
        self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
        rxd = epgs[0].uplink.get_capture(1)
        self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)

        #
        # packets to non-local L3 destinations dropped
        #
        pkt_intra_epg_220_ip4 = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IP(src=eps[0].ip4.address, dst="10.0.0.99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        pkt_inter_epg_222_ip4 = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IP(src=eps[0].ip4.address, dst="10.0.1.99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)

        pkt_inter_epg_222_ip6 = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IPv6(src=eps[0].ip6.address, dst="2001:10::99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)

        #
        # Add the subnet routes
        #
        s41 = VppGbpSubnet(self, 0, "10.0.0.0", 24)
        s42 = VppGbpSubnet(self, 0, "10.0.1.0", 24)
        s43 = VppGbpSubnet(self, 0, "10.0.2.0", 24)
        s41.add_vpp_config()
        s42.add_vpp_config()
        s43.add_vpp_config()
        s61 = VppGbpSubnet(self, 0, "2001:10::1", 64)
        s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64)
        s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64)
        s61.add_vpp_config()
        s62.add_vpp_config()
        s63.add_vpp_config()

        self.send_and_expect_bridged(self.pg0, pkt_intra_epg_220_ip4 * 65,
                                     self.pg4)
        self.send_and_expect_bridged(self.pg3, pkt_inter_epg_222_ip4 * 65,
                                     self.pg6)
        self.send_and_expect_bridged6(self.pg3, pkt_inter_epg_222_ip6 * 65,
                                      self.pg6)

        self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
        self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
        self.logger.info(self.vapi.cli("sh gbp endpoint"))
        self.logger.info(self.vapi.cli("sh gbp recirc"))
        self.logger.info(self.vapi.cli("sh int"))
        self.logger.info(self.vapi.cli("sh int addr"))
        self.logger.info(self.vapi.cli("sh int feat loop6"))
        self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
        self.logger.info(self.vapi.cli("sh int feat loop3"))

        #
        # Packet destined to unknown unicast is sent on the epg uplink ...
        #
        pkt_intra_epg_220_to_uplink = (
            Ether(src=self.pg0.remote_mac, dst="00:00:00:33:44:55") /
            IP(src=eps[0].ip4.address, dst="10.0.0.99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_bridged(self.pg0,
                                     pkt_intra_epg_220_to_uplink * 65,
                                     self.pg4)
        # ... and nowhere else
        self.pg1.get_capture(0, timeout=0.1)
        self.pg1.assert_nothing_captured(remark="Flood onto other VMS")

        pkt_intra_epg_221_to_uplink = (
            Ether(src=self.pg2.remote_mac, dst="00:00:00:33:44:66") /
            IP(src=eps[0].ip4.address, dst="10.0.0.99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_bridged(self.pg2,
                                     pkt_intra_epg_221_to_uplink * 65,
                                     self.pg5)

        #
        # Packets from the uplink are forwarded in the absence of a contract
        #
        pkt_intra_epg_220_from_uplink = (
            Ether(src="00:00:00:33:44:55", dst=self.pg0.remote_mac) /
            IP(src=eps[0].ip4.address, dst="10.0.0.99") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_bridged(self.pg4,
                                     pkt_intra_epg_220_from_uplink * 65,
                                     self.pg0)

        #
        # in the absence of policy, endpoints in the same EPG
        # can communicate
        #
        pkt_intra_epg = (
            Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) /
            IP(src=eps[0].ip4.address, dst=eps[1].ip4.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)

        #
        # in the abscense of policy, endpoints in the different EPG
        # cannot communicate
        #
        pkt_inter_epg_220_to_221 = (
            Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) /
            IP(src=eps[0].ip4.address, dst=eps[2].ip4.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        pkt_inter_epg_221_to_220 = (
            Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac) /
            IP(src=eps[2].ip4.address, dst=eps[0].ip4.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        pkt_inter_epg_220_to_222 = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IP(src=eps[0].ip4.address, dst=eps[3].ip4.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_221 * 65)
        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_222 * 65)

        #
        # A uni-directional contract from EPG 220 -> 221
        #
        acl = VppGbpAcl(self)
        rule = acl.create_rule(permit_deny=1, proto=17)
        rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
        acl_index = acl.add_vpp_config([rule, rule2])
        c1 = VppGbpContract(self, 220, 221, acl_index)
        c1.add_vpp_config()

        self.send_and_expect_bridged(self.pg0, pkt_inter_epg_220_to_221 * 65,
                                     self.pg2)
        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_222 * 65)

        #
        # contract for the return direction
        #
        c2 = VppGbpContract(self, 221, 220, acl_index)
        c2.add_vpp_config()

        self.send_and_expect_bridged(self.pg0, pkt_inter_epg_220_to_221 * 65,
                                     self.pg2)
        self.send_and_expect_bridged(self.pg2, pkt_inter_epg_221_to_220 * 65,
                                     self.pg0)

        #
        # check that inter group is still disabled for the groups
        # not in the contract.
        #
        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_222 * 65)

        #
        # A uni-directional contract from EPG 220 -> 222 'L3 routed'
        #
        c3 = VppGbpContract(self, 220, 222, acl_index)
        c3.add_vpp_config()

        self.logger.info(self.vapi.cli("sh gbp contract"))

        self.send_and_expect_routed(self.pg0, pkt_inter_epg_220_to_222 * 65,
                                    self.pg3, self.router_mac)

        #
        # remove both contracts, traffic stops in both directions
        #
        c2.remove_vpp_config()
        c1.remove_vpp_config()
        c3.remove_vpp_config()
        acl.remove_vpp_config()

        self.send_and_assert_no_replies(self.pg2,
                                        pkt_inter_epg_221_to_220 * 65)
        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_221 * 65)
        self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)

        #
        # EPs to the outside world
        #

        # in the EP's RD an external subnet via the NAT EPG's recirc
        se1 = VppGbpSubnet(self,
                           0,
                           "0.0.0.0",
                           0,
                           is_internal=False,
                           sw_if_index=recirc_nat.recirc.sw_if_index,
                           epg=epg_nat.epg)
        se1.add_vpp_config()
        se2 = VppGbpSubnet(self,
                           0,
                           "11.0.0.0",
                           8,
                           is_internal=False,
                           sw_if_index=recirc_nat.recirc.sw_if_index,
                           epg=epg_nat.epg)
        se2.add_vpp_config()
        se16 = VppGbpSubnet(self,
                            0,
                            "::",
                            0,
                            is_internal=False,
                            sw_if_index=recirc_nat.recirc.sw_if_index,
                            epg=epg_nat.epg)
        se16.add_vpp_config()
        # in the NAT RD an external subnet via the NAT EPG's uplink
        se3 = VppGbpSubnet(self,
                           20,
                           "0.0.0.0",
                           0,
                           is_internal=False,
                           sw_if_index=epg_nat.uplink.sw_if_index,
                           epg=epg_nat.epg)
        se36 = VppGbpSubnet(self,
                            20,
                            "::",
                            0,
                            is_internal=False,
                            sw_if_index=epg_nat.uplink.sw_if_index,
                            epg=epg_nat.epg)
        se4 = VppGbpSubnet(self,
                           20,
                           "11.0.0.0",
                           8,
                           is_internal=False,
                           sw_if_index=epg_nat.uplink.sw_if_index,
                           epg=epg_nat.epg)
        se3.add_vpp_config()
        se36.add_vpp_config()
        se4.add_vpp_config()

        self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
        self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
        self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
        self.logger.info(self.vapi.cli("sh ip6 fib %s" % eps[0].fip6))

        #
        # From an EP to an outside addess: IN2OUT
        #
        pkt_inter_epg_220_to_global = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IP(src=eps[0].ip4.address, dst="1.1.1.1") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        # no policy yet
        self.send_and_assert_no_replies(self.pg0,
                                        pkt_inter_epg_220_to_global * 65)

        acl2 = VppGbpAcl(self)
        rule = acl2.create_rule(permit_deny=1,
                                proto=17,
                                sport_from=1234,
                                sport_to=1234,
                                dport_from=1234,
                                dport_to=1234)
        rule2 = acl2.create_rule(is_ipv6=1,
                                 permit_deny=1,
                                 proto=17,
                                 sport_from=1234,
                                 sport_to=1234,
                                 dport_from=1234,
                                 dport_to=1234)

        acl_index2 = acl2.add_vpp_config([rule, rule2])
        c4 = VppGbpContract(self, 220, 333, acl_index2)
        c4.add_vpp_config()

        self.send_and_expect_natted(self.pg0, pkt_inter_epg_220_to_global * 65,
                                    self.pg7, eps[0].fip4.address)

        pkt_inter_epg_220_to_global = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IPv6(src=eps[0].ip6.address, dst="6001::1") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_natted6(self.pg0,
                                     pkt_inter_epg_220_to_global * 65,
                                     self.pg7, eps[0].fip6.address)

        #
        # From a global address to an EP: OUT2IN
        #
        pkt_inter_epg_220_from_global = (
            Ether(src=self.router_mac, dst=self.pg0.remote_mac) /
            IP(dst=eps[0].fip4.address, src="1.1.1.1") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_assert_no_replies(self.pg7,
                                        pkt_inter_epg_220_from_global * 65)

        c5 = VppGbpContract(self, 333, 220, acl_index2)
        c5.add_vpp_config()

        self.send_and_expect_unnatted(self.pg7,
                                      pkt_inter_epg_220_from_global * 65,
                                      eps[0].itf, eps[0].ip4.address)

        pkt_inter_epg_220_from_global = (
            Ether(src=self.router_mac, dst=self.pg0.remote_mac) /
            IPv6(dst=eps[0].fip6.address, src="6001::1") /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_unnatted6(self.pg7,
                                       pkt_inter_epg_220_from_global * 65,
                                       eps[0].itf, eps[0].ip6.address)

        #
        # From a local VM to another local VM using resp. public addresses:
        #  IN2OUT2IN
        #
        pkt_intra_epg_220_global = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IP(src=eps[0].ip4.address, dst=eps[1].fip4.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_double_natted(eps[0].itf,
                                           pkt_intra_epg_220_global * 65,
                                           eps[1].itf, eps[0].fip4.address,
                                           eps[1].ip4.address)

        pkt_intra_epg_220_global = (
            Ether(src=self.pg0.remote_mac, dst=self.router_mac) /
            IPv6(src=eps[0].ip6.address, dst=eps[1].fip6.address) /
            UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        self.send_and_expect_double_natted6(eps[0].itf,
                                            pkt_intra_epg_220_global * 65,
                                            eps[1].itf, eps[0].fip6.address,
                                            eps[1].ip6.address)

        #
        # cleanup
        #
        for ep in eps:
            # del static mappings for each EP from the 10/8 to 11/8 network
            self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
                                                   ep.fip4.bytes,
                                                   vrf_id=0,
                                                   addr_only=1,
                                                   is_add=0)
            self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
                                                   ep.fip6.bytes,
                                                   vrf_id=0,
                                                   is_add=0)

        for epg in epgs:
            # IP config on the BVI interfaces
            self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
                                                   epg.bvi_ip4_n,
                                                   32,
                                                   is_add=0)
            self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
                                                   epg.bvi_ip6_n,
                                                   128,
                                                   is_add=0,
                                                   is_ipv6=True)
            self.logger.info(self.vapi.cli("sh int addr"))

            epg.uplink.set_table_ip4(0)
            epg.uplink.set_table_ip6(0)

            if epg != epgs[0] and epg != epgs[3]:
                epg.bvi.set_table_ip4(0)
                epg.bvi.set_table_ip6(0)

                self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
                                                          is_inside=1,
                                                          is_add=0)
                self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
                                                  is_inside=1,
                                                  is_add=0)

        for recirc in recircs:
            recirc.recirc.set_table_ip4(0)
            recirc.recirc.set_table_ip6(0)

            self.vapi.nat44_interface_add_del_feature(
                recirc.recirc.sw_if_index, is_inside=0, is_add=0)
            self.vapi.nat66_add_del_interface(recirc.recirc.sw_if_index,
                                              is_inside=0,
                                              is_add=0)
Пример #12
0
    def test_dhcp_proxy(self):
        """ DHCPv4 Proxy """

        #
        # Verify no response to DHCP request without DHCP config
        #
        p_disc_vrf0 = (
            Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
            IP(src="0.0.0.0", dst="255.255.255.255") /
            UDP(sport=DHCP4_CLIENT_PORT, dport=DHCP4_SERVER_PORT) /
            BOOTP(op=1) /
            DHCP(options=[('message-type', 'discover'), ('end')]))
        pkts_disc_vrf0 = [p_disc_vrf0]
        p_disc_vrf1 = (
            Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg3.remote_mac) /
            IP(src="0.0.0.0", dst="255.255.255.255") /
            UDP(sport=DHCP4_CLIENT_PORT, dport=DHCP4_SERVER_PORT) /
            BOOTP(op=1) /
            DHCP(options=[('message-type', 'discover'), ('end')]))
        pkts_disc_vrf1 = [p_disc_vrf0]

        self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                        "DHCP with no configuration")

        #
        # Enable DHCP proxy in VRF 0
        #
        server_addr = self.pg0.remote_ip4n
        src_addr = self.pg0.local_ip4n

        self.vapi.dhcp_proxy_config(server_addr, src_addr, rx_table_id=0)

        #
        # Discover packets from the client are dropped because there is no
        # IP address configured on the client facing interface
        #
        self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
                                        "Discover DHCP no relay address")

        #
        # Inject a response from the server
        #  dropped, because there is no IP addrees on the
        #  client interfce to fill in the option.
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
             UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
             BOOTP(op=1) / DHCP(options=[('message-type', 'offer'), ('end')]))
        pkts = [p]

        self.send_and_assert_no_replies(self.pg2, pkts,
                                        "Offer DHCP no relay address")

        #
        # configure an IP address on the client facing interface
        #
        self.pg2.config_ip4()

        #
        # Try again with a discover packet
        # Rx'd packet should be to the server address and from the configured
        # source address
        # UDP source ports are unchanged
        # we've no option 82 config so that should be absent
        #
        self.pg2.add_stream(pkts_disc_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)
        rx = rx[0]

        option_82 = self.verify_relayed_dhcp_discover(rx,
                                                      self.pg0,
                                                      src_intf=self.pg2)

        #
        # Create an DHCP offer reply from the server with a correctly formatted
        # option 82. i.e. send back what we just captured
        # The offer, sent mcast to the client, still has option 82.
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
             UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
             BOOTP(op=1) /
             DHCP(options=[('message-type', 'offer'),
                           ('relay_agent_Information', option_82), ('end')]))
        pkts = [p]

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

        rx = self.pg2.get_capture(1)
        rx = rx[0]

        self.verify_dhcp_offer(rx, self.pg2)

        #
        # Bogus Option 82:
        #
        # 1. not our IP address = not checked by VPP? so offer is replayed
        #    to client
        bad_ip = option_82[0:8] + chr(33) + option_82[9:]

        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
             UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
             BOOTP(op=1) /
             DHCP(options=[('message-type', 'offer'),
                           ('relay_agent_Information', bad_ip), ('end')]))
        pkts = [p]
        self.send_and_assert_no_replies(self.pg0, pkts,
                                        "DHCP offer option 82 bad address")

        # 2. Not a sw_if_index VPP knows
        bad_if_index = option_82[0:2] + chr(33) + option_82[3:]

        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
             UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
             BOOTP(op=1) /
             DHCP(options=[('message-type',
                            'offer'), ('relay_agent_Information',
                                       bad_if_index), ('end')]))
        pkts = [p]
        self.send_and_assert_no_replies(self.pg0, pkts,
                                        "DHCP offer option 82 bad if index")

        #
        # Send a DHCP request in VRF 1. should be dropped.
        #
        self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                        "DHCP with no configuration VRF 1")

        #
        # Delete the DHCP config in VRF 0
        # Should now drop requests.
        #
        self.vapi.dhcp_proxy_config(server_addr,
                                    src_addr,
                                    rx_table_id=0,
                                    is_add=0)

        self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
                                        "DHCP config removed VRF 0")
        self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                        "DHCP config removed VRF 1")

        #
        # Add DHCP config for VRF 1
        #
        server_addr = self.pg1.remote_ip4n
        src_addr = self.pg1.local_ip4n
        self.vapi.dhcp_proxy_config(server_addr,
                                    src_addr,
                                    rx_table_id=1,
                                    server_table_id=1)

        #
        # Confim DHCP requests ok in VRF 1.
        #  - dropped on IP config on client interface
        #
        self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                        "DHCP config removed VRF 1")

        #
        # configure an IP address on the client facing interface
        #
        self.pg3.config_ip4()

        self.pg3.add_stream(pkts_disc_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg3)

        #
        # Add VSS config
        #  table=1, fib=id=1, oui=4
        self.vapi.dhcp_proxy_set_vss(1, 1, 4)

        self.pg3.add_stream(pkts_disc_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_relayed_dhcp_discover(rx,
                                          self.pg1,
                                          src_intf=self.pg3,
                                          fib_id=1,
                                          oui=4)

        #
        # Add a second DHCP server in VRF 1
        #  expect clients messages to be relay to both configured servers
        #
        self.pg1.generate_remote_hosts(2)
        server_addr2 = socket.inet_pton(AF_INET, self.pg1.remote_hosts[1].ip4)

        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_add=1)

        #
        # We'll need an ARP entry for the server to send it packets
        #
        arp_entry = VppNeighbor(self, self.pg1.sw_if_index,
                                self.pg1.remote_hosts[1].mac,
                                self.pg1.remote_hosts[1].ip4)
        arp_entry.add_vpp_config()

        #
        # Send a discover from the client. expect two relayed messages
        # The frist packet is sent to the second server
        # We're not enforcing that here, it's just the way it is.
        #
        self.pg3.add_stream(pkts_disc_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(2)

        option_82 = self.verify_relayed_dhcp_discover(
            rx[0],
            self.pg1,
            src_intf=self.pg3,
            dst_mac=self.pg1.remote_hosts[1].mac,
            dst_ip=self.pg1.remote_hosts[1].ip4,
            fib_id=1,
            oui=4)
        self.verify_relayed_dhcp_discover(rx[1],
                                          self.pg1,
                                          src_intf=self.pg3,
                                          fib_id=1,
                                          oui=4)

        #
        # Send both packets back. Client gets both.
        #
        p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
              IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
              UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
              BOOTP(op=1) /
              DHCP(options=[('message-type', 'offer'),
                            ('relay_agent_Information', option_82), ('end')]))
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
              IP(src=self.pg1.remote_hosts[1].ip4, dst=self.pg1.local_ip4) /
              UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
              BOOTP(op=1) /
              DHCP(options=[('message-type', 'offer'),
                            ('relay_agent_Information', option_82), ('end')]))
        pkts = [p1, p2]

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

        rx = self.pg3.get_capture(2)

        self.verify_dhcp_offer(rx[0], self.pg3, fib_id=1, oui=4)
        self.verify_dhcp_offer(rx[1], self.pg3, fib_id=1, oui=4)

        #
        # Ensure offers from non-servers are dropeed
        #
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
              IP(src="8.8.8.8", dst=self.pg1.local_ip4) /
              UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
              BOOTP(op=1) /
              DHCP(options=[('message-type', 'offer'),
                            ('relay_agent_Information', option_82), ('end')]))
        self.send_and_assert_no_replies(self.pg1, p2,
                                        "DHCP offer from non-server")

        #
        # Ensure only the discover is sent to multiple servers
        #
        p_req_vrf1 = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg3.remote_mac) /
                      IP(src="0.0.0.0", dst="255.255.255.255") /
                      UDP(sport=DHCP4_CLIENT_PORT, dport=DHCP4_SERVER_PORT) /
                      BOOTP(op=1) /
                      DHCP(options=[('message-type', 'request'), ('end')]))

        self.pg3.add_stream(p_req_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        #
        # Remove the second DHCP server
        #
        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_add=0)

        #
        # Test we can still relay with the first
        #
        self.pg3.add_stream(pkts_disc_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_relayed_dhcp_discover(rx,
                                          self.pg1,
                                          src_intf=self.pg3,
                                          fib_id=1,
                                          oui=4)

        #
        # Remove the VSS config
        #  relayed DHCP has default vlaues in the option.
        #
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_add=0)

        self.pg3.add_stream(pkts_disc_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg3)

        #
        # remove DHCP config to cleanup
        #
        self.vapi.dhcp_proxy_config(server_addr,
                                    src_addr,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_add=0)

        self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
                                        "DHCP cleanup VRF 0")
        self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                        "DHCP cleanup VRF 1")
        self.pg2.unconfig_ip4()
        self.pg3.unconfig_ip4()
Пример #13
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 = [chr(0)] * 256
        for i in range(0, 255):
            output[i] = chr(255 - i)
        os = ''.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 = [chr(2)] * 256
        os = ''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(2, rows)

        output = [chr(3)] * 256
        os = ''.join(output)
        rows = [{
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }, {
            'outputs': os
        }]

        self.vapi.qos_egress_map_update(3, rows)

        output = [chr(4)] * 256
        os = ''.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(chr(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(chr(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)
Пример #14
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 = [chr(from_ext)] * 256
        os1 = ''.join(output)
        output = [chr(from_vlan)] * 256
        os2 = ''.join(output)
        output = [chr(from_mpls)] * 256
        os3 = ''.join(output)
        output = [chr(from_ip)] * 256
        os4 = ''.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(chr(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(chr(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(chr(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(chr(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)
Пример #15
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(b"\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(b"\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,
                             type=FibPathType.FIB_PATH_TYPE_DVR)
            ],
        )
        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 * NUM_PKTS, 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,
                    type=FibPathType.FIB_PATH_TYPE_DVR,
                )
            ],
        )
        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 * NUM_PKTS, 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(b"\xa5" * 100))

        rx = self.send_and_expect(self.pg2, pkt_tag_to_tag * NUM_PKTS,
                                  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(b"\xa5" * 100))

        rx = self.send_and_expect(self.pg2, pkt_tag_to_non_tag * NUM_PKTS,
                                  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 = AclRule(
            is_permit=0,
            proto=17,
            ports=1234,
            src_prefix=IPv4Network((any_src_addr, 32)),
            dst_prefix=IPv4Network((ip_non_tag_bridged, 32)),
        )
        acl = VppAcl(self, rules=[rule_1])
        acl.add_vpp_config()

        #
        # Apply the ACL on the output interface
        #
        acl_if1 = VppAclInterface(self,
                                  sw_if_index=self.pg1.sw_if_index,
                                  n_input=0,
                                  acls=[acl])
        acl_if1.add_vpp_config()

        #
        # 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 * NUM_PKTS)

        #
        # cleanup
        #
        acl_if1.remove_vpp_config()
        acl.remove_vpp_config()

        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_route_dump(0)

        for r in routes:
            if ip_tag_bridged == str(r.route.prefix.network_address):
                self.assertEqual(r.route.paths[0].sw_if_index,
                                 sub_if_on_pg3.sw_if_index)
                self.assertEqual(r.route.paths[0].type,
                                 FibPathType.FIB_PATH_TYPE_DVR)
            if ip_non_tag_bridged == str(r.route.prefix.network_address):
                self.assertEqual(r.route.paths[0].sw_if_index,
                                 self.pg1.sw_if_index)
                self.assertEqual(r.route.paths[0].type,
                                 FibPathType.FIB_PATH_TYPE_DVR)

        #
        # 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()
Пример #16
0
 def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=100):
     return [
         Ether(dst=self.omac) / IP(src="1.1.1.1", dst="1.1.1.2") /
         UDP(sport=1144, dport=2233) / Raw('X' * payload_size)
         for i in range(count)
     ]
Пример #17
0
    def test_svs4(self):
        """ Source VRF Select IP4 """

        #
        # packets destined out of the 3 non-default table interfaces
        #
        pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                   IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)),
                  (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                   IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)),
                  (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                   IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100))]
        pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                   IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)),
                  (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                   IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)),
                  (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                   IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
                   UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100))]

        #
        # before adding the SVS config all these packets are dropped when
        # ingressing on pg0 since pg0 is in the default table
        #
        for p in pkts_0:
            self.send_and_assert_no_replies(self.pg0, p * 1)

        #
        # Add table 1001 & 1002 into which we'll add the routes
        # determining the source VRF selection
        #
        table_ids = [101, 102]

        for table_id in table_ids:
            self.vapi.svs_table_add_del(
                VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_id)

            #
            # map X.0.0.0/8 to each SVS table for lookup in table X
            #
            for i in range(1, 4):
                self.vapi.svs_route_add_del(table_id, "%d.0.0.0/8" % i, i)

        #
        # Enable SVS on pg0/pg1 using table 1001/1002
        #
        self.vapi.svs_enable_disable(
            VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[0],
            self.pg0.sw_if_index)
        self.vapi.svs_enable_disable(
            VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[1],
            self.pg1.sw_if_index)

        #
        # now all the packets should be delivered out the respective interface
        #
        self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
        self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
        self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
        self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
        self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
        self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)

        #
        # check that if the SVS lookup does not match a route the packet
        # is forwarded using the interface's routing table
        #
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
             UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100))
        self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)

        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
             IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4) /
             UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100))
        self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)

        #
        # dump the SVS configs
        #
        ss = self.vapi.svs_dump()

        self.assertEqual(ss[0].table_id, table_ids[0])
        self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
        self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
        self.assertEqual(ss[1].table_id, table_ids[1])
        self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
        self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)

        #
        # cleanup
        #
        self.vapi.svs_enable_disable(
            VppEnum.vl_api_address_family_t.ADDRESS_IP4,
            table_ids[0],
            self.pg0.sw_if_index,
            is_enable=0)
        self.vapi.svs_enable_disable(
            VppEnum.vl_api_address_family_t.ADDRESS_IP4,
            table_ids[1],
            self.pg1.sw_if_index,
            is_enable=0)

        for table_id in table_ids:
            for i in range(1, 4):
                self.vapi.svs_route_add_del(table_id,
                                            "%d.0.0.0/8" % i,
                                            0,
                                            is_add=0)
            self.vapi.svs_table_add_del(
                VppEnum.vl_api_address_family_t.ADDRESS_IP4,
                table_id,
                is_add=0)
Пример #18
0
async def run_test(dut, idle_inserter=None, backpressure_inserter=None):

    tb = TB(dut)

    await tb.reset()

    tb.set_idle_generator(idle_inserter)
    tb.set_backpressure_generator(backpressure_inserter)

    local_mac = 'DA:D1:D2:D3:D4:D5'
    local_ip = '192.168.1.101'
    gateway_ip = '192.168.1.1'
    subnet_mask = '255.255.255.0'

    dut.local_mac.value = int.from_bytes(mac2str(local_mac), 'big')
    dut.local_ip.value = atol(local_ip)
    dut.gateway_ip.value = atol(gateway_ip)
    dut.subnet_mask.value = atol(subnet_mask)

    for k in range(10):
        await RisingEdge(dut.clk)

    tb.log.info("test ARP request")

    eth = Ether(src='5A:51:52:53:54:55', dst='FF:FF:FF:FF:FF:FF')
    arp = ARP(hwtype=1,
              ptype=0x0800,
              hwlen=6,
              plen=4,
              op=1,
              hwsrc='5A:51:52:53:54:55',
              psrc='192.168.1.100',
              hwdst='00:00:00:00:00:00',
              pdst='192.168.1.101')
    test_pkt = eth / arp

    await tb.send(test_pkt)

    rx_pkt = await tb.recv()

    tb.log.info("RX packet: %s", repr(rx_pkt))

    assert rx_pkt[Ether].dst.casefold() == test_pkt[Ether].src.casefold()
    assert rx_pkt[Ether].src.casefold() == local_mac.casefold()
    assert rx_pkt[Ether].type == test_pkt[Ether].type
    assert rx_pkt[ARP].hwtype == test_pkt[Ether].hwtype
    assert rx_pkt[ARP].ptype == test_pkt[Ether].ptype
    assert rx_pkt[ARP].hwlen == test_pkt[Ether].hwlen
    assert rx_pkt[ARP].plen == test_pkt[Ether].plen
    assert rx_pkt[ARP].op == 2
    assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold()
    assert rx_pkt[ARP].psrc == local_ip
    assert rx_pkt[ARP].hwdst.casefold() == test_pkt[ARP].hwsrc.casefold()
    assert rx_pkt[ARP].pdst == test_pkt[ARP].psrc

    tb.log.info("Cached read")

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.100')))

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert not resp.error
    assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big')

    tb.log.info("Uncached read, inside subnet")

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.102')))

    # wait for ARP request
    rx_pkt = await tb.recv()

    tb.log.info("RX packet: %s", repr(rx_pkt))

    assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold()
    assert rx_pkt[Ether].src.casefold() == local_mac.casefold()
    assert rx_pkt[Ether].type == 0x0806
    assert rx_pkt[ARP].hwtype == 0x0001
    assert rx_pkt[ARP].ptype == 0x0800
    assert rx_pkt[ARP].hwlen == 6
    assert rx_pkt[ARP].plen == 4
    assert rx_pkt[ARP].op == 1
    assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold()
    assert rx_pkt[ARP].psrc == local_ip
    assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold()
    assert rx_pkt[ARP].pdst == '192.168.1.102'

    # generate response
    eth = Ether(src='6A:61:62:63:64:65', dst=local_mac)
    arp = ARP(hwtype=1,
              ptype=0x0800,
              hwlen=6,
              plen=4,
              op=2,
              hwsrc='6A:61:62:63:64:65',
              psrc='192.168.1.102',
              hwdst=local_mac,
              pdst=local_ip)
    test_pkt = eth / arp

    await tb.send(test_pkt)

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert not resp.error
    assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big')

    tb.log.info("Uncached read, outside of subnet")

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('8.8.8.8')))

    # wait for ARP request
    rx_pkt = await tb.recv()

    tb.log.info("RX packet: %s", repr(rx_pkt))

    assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold()
    assert rx_pkt[Ether].src.casefold() == local_mac.casefold()
    assert rx_pkt[Ether].type == 0x0806
    assert rx_pkt[ARP].hwtype == 0x0001
    assert rx_pkt[ARP].ptype == 0x0800
    assert rx_pkt[ARP].hwlen == 6
    assert rx_pkt[ARP].plen == 4
    assert rx_pkt[ARP].op == 1
    assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold()
    assert rx_pkt[ARP].psrc == local_ip
    assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold()
    assert rx_pkt[ARP].pdst == gateway_ip

    # generate response
    eth = Ether(src='AA:BB:CC:DD:EE:FF', dst=local_mac)
    arp = ARP(hwtype=1,
              ptype=0x0800,
              hwlen=6,
              plen=4,
              op=2,
              hwsrc='AA:BB:CC:DD:EE:FF',
              psrc='192.168.1.1',
              hwdst=local_mac,
              pdst=local_ip)
    test_pkt = eth / arp

    await tb.send(test_pkt)

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert not resp.error
    assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big')

    tb.log.info("Uncached read, timeout")

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.103')))

    # wait for ARP request
    for k in range(4):
        rx_pkt = await tb.recv()

        tb.log.info("RX packet: %s", repr(rx_pkt))

        assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold()
        assert rx_pkt[Ether].src.casefold() == local_mac.casefold()
        assert rx_pkt[Ether].type == 0x0806
        assert rx_pkt[ARP].hwtype == 0x0001
        assert rx_pkt[ARP].ptype == 0x0800
        assert rx_pkt[ARP].hwlen == 6
        assert rx_pkt[ARP].plen == 4
        assert rx_pkt[ARP].op == 1
        assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold()
        assert rx_pkt[ARP].psrc == local_ip
        assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold()
        assert rx_pkt[ARP].pdst == '192.168.1.103'

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert resp.error

    tb.log.info("Broadcast")

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.255')))

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert not resp.error
    assert resp.mac == int.from_bytes(mac2str('FF:FF:FF:FF:FF:FF'), 'big')

    await tb.arp_req_source.send(ArpReqTransaction(ip=atol('255.255.255.255')))

    resp = await tb.arp_resp_sink.recv()

    tb.log.info("Read value: %s", resp)

    assert not resp.error
    assert resp.mac == int.from_bytes(mac2str('FF:FF:FF:FF:FF:FF'), 'big')

    assert tb.header_sink.empty()
    assert tb.payload_sink.empty()

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)
Пример #19
0
    def test_tra_anti_replay(self, count=1):
        """ ipsec v4 transport anti-reply test """
        p = self.params[socket.AF_INET]
        use_esn = p.vpp_tra_sa.use_esn

        # fire in a packet with seq number 1
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=1))
        recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)

        # now move the window over to 235
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=235))
        recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)

        # replayed packets are dropped
        self.send_and_assert_no_replies(self.tra_if, pkt * 3)
        self.assert_packet_counter_equal(
            '/err/%s/SA replayed packet' % self.tra4_decrypt_node_name, 3)

        # the window size is 64 packets
        # in window are still accepted
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=172))
        recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)

        # a packet that does not decrypt does not move the window forward
        bogus_sa = SecurityAssociation(self.encryption_type, p.vpp_tra_spi)
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               bogus_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                   dst=self.tra_if.local_ip4) / ICMP(),
                                seq_num=350))
        self.send_and_assert_no_replies(self.tra_if, pkt * 17)

        self.assert_packet_counter_equal(
            '/err/%s/Integrity check failed' % self.tra4_decrypt_node_name, 17)

        # which we can determine since this packet is still in the window
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=234))
        self.send_and_expect(self.tra_if, [pkt], self.tra_if)

        # out of window are dropped
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=17))
        self.send_and_assert_no_replies(self.tra_if, pkt * 17)

        if use_esn:
            # an out of window error with ESN looks like a high sequence
            # wrap. but since it isn't then the verify will fail.
            self.assert_packet_counter_equal(
                '/err/%s/Integrity check failed' % self.tra4_decrypt_node_name,
                34)

        else:
            self.assert_packet_counter_equal(
                '/err/%s/SA replayed packet' % self.tra4_decrypt_node_name, 20)

        # valid packet moves the window over to 236
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=236))
        rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
        decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])

        # move VPP's SA to just before the seq-number wrap
        self.vapi.cli("test ipsec sa %d seq 0xffffffff" % p.scapy_tra_sa_id)

        # then fire in a packet that VPP should drop because it causes the
        # seq number to wrap  unless we're using extended.
        pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
               p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                         dst=self.tra_if.local_ip4) / ICMP(),
                                      seq_num=237))

        if use_esn:
            rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
            # in order to decrpyt the high order number needs to wrap
            p.vpp_tra_sa.seq_num = 0x100000000
            decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])

            # send packets with high bits set
            p.scapy_tra_sa.seq_num = 0x100000005
            pkt = (
                Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) /
                p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
                                          dst=self.tra_if.local_ip4) / ICMP(),
                                       seq_num=0x100000005))
            rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
            # in order to decrpyt the high order number needs to wrap
            decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
        else:
            self.send_and_assert_no_replies(self.tra_if, [pkt])
            self.assert_packet_counter_equal(
                '/err/%s/sequence number cycled' % self.tra4_encrypt_node_name,
                1)

        # move the security-associations seq number on to the last we used
        self.vapi.cli("test ipsec sa %d seq 0x15f" % p.scapy_tra_sa_id)
        p.scapy_tra_sa.seq_num = 351
        p.vpp_tra_sa.seq_num = 351
Пример #20
0
 def gen_pkts(self, sw_intf, src, dst, count=1):
     return [
         Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
         IP(src=src, dst=dst) / ICMP() / self.payload for i in range(count)
     ]
Пример #21
0
 def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=54):
     return [
         Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
         IP(src=src, dst=dst) / ICMP() / Raw('X' * payload_size)
         for i in range(count)
     ]
Пример #22
0
    def test_static(self):
        """ 1:1 NAT66 test """
        flags = self.config_flags.NAT_IS_INSIDE
        self.vapi.nat66_add_del_interface(is_add=1,
                                          flags=flags,
                                          sw_if_index=self.pg0.sw_if_index)
        self.vapi.nat66_add_del_interface(is_add=1,
                                          sw_if_index=self.pg1.sw_if_index)
        self.vapi.nat66_add_del_static_mapping(
            local_ip_address=self.pg0.remote_ip6,
            external_ip_address=self.nat_addr,
            is_add=1)

        # in2out
        pkts = []
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / TCP())
        pkts.append(p)
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / UDP())
        pkts.append(p)
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
             ICMPv6EchoRequest())
        pkts.append(p)
        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / GRE() /
             IP() / TCP())
        pkts.append(p)
        self.pg0.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        capture = self.pg1.get_capture(len(pkts))

        for packet in capture:
            try:
                self.assertEqual(packet[IPv6].src, self.nat_addr)
                self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
                self.assert_packet_checksums_valid(packet)
            except:
                self.logger.error(ppp("Unexpected or invalid packet:", packet))
                raise

        # out2in
        pkts = []
        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
             IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / TCP())
        pkts.append(p)
        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
             IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / UDP())
        pkts.append(p)
        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
             IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
             ICMPv6EchoReply())
        pkts.append(p)
        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
             IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / GRE() / IP() /
             TCP())
        pkts.append(p)
        self.pg1.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        capture = self.pg0.get_capture(len(pkts))
        for packet in capture:
            try:
                self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
                self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
                self.assert_packet_checksums_valid(packet)
            except:
                self.logger.error(ppp("Unexpected or invalid packet:", packet))
                raise

        sm = self.vapi.nat66_static_mapping_dump()
        self.assertEqual(len(sm), 1)
        self.assertEqual(sm[0].total_pkts, 8)
Пример #23
0
async def run_test(dut,
                   payload_lengths=None,
                   payload_data=None,
                   idle_inserter=None,
                   backpressure_inserter=None):

    tb = TB(dut)

    await tb.reset()

    tb.set_idle_generator(idle_inserter)
    tb.set_backpressure_generator(backpressure_inserter)

    test_pkts = []
    test_frames = []

    ip_id = 1

    for payload in [payload_data(x) for x in payload_lengths()]:
        eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5')
        ip = IP(src='192.168.1.100', dst='192.168.1.101', id=ip_id)
        udp = UDP(sport=1234, dport=4321)
        test_pkt = eth / ip / udp / payload

        ip_id = (ip_id + 1) & 0xffff

        # don't compute checksum
        test_pkts.append(test_pkt.copy())
        test_frame = AxiStreamFrame(test_pkt.build())
        test_frames.append(test_frame)

        await tb.source.send(test_frame)
        await tb.cmd_source.send(
            CsumCmdTransaction(csum_enable=0,
                               csum_start=34,
                               csum_offset=40,
                               csum_init=0))

        # inline partial checksum
        test_pkts.append(test_pkt.copy())

        pkt = test_pkt.copy()
        partial_csum = scapy.utils.checksum(bytes(pkt[UDP]))
        pkt[UDP].chksum = partial_csum

        test_frame = AxiStreamFrame(pkt.build())
        test_frames.append(test_frame)

        await tb.source.send(test_frame)
        await tb.cmd_source.send(
            CsumCmdTransaction(csum_enable=1,
                               csum_start=34,
                               csum_offset=40,
                               csum_init=0))

        # partial checksum in command
        test_pkts.append(test_pkt.copy())

        pkt = test_pkt.copy()
        partial_csum = scapy.utils.checksum(bytes(pkt[UDP]))
        pkt[UDP].chksum = 0

        test_frame = AxiStreamFrame(pkt.build())
        test_frames.append(test_frame)

        await tb.source.send(test_frame)
        await tb.cmd_source.send(
            CsumCmdTransaction(csum_enable=1,
                               csum_start=34,
                               csum_offset=40,
                               csum_init=partial_csum))

    for test_pkt, test_frame in zip(test_pkts, test_frames):
        rx_frame = await tb.sink.recv()

        rx_pkt = Ether(bytes(rx_frame))

        tb.log.info("RX packet: %s", repr(rx_pkt))

        check_pkt = Ether(test_pkt.build())

        tb.log.info("RX packet UDP checksum: 0x%04x (expected 0x%04x)",
                    rx_pkt[UDP].chksum, check_pkt[UDP].chksum)

        assert check_pkt == rx_pkt

    assert tb.sink.empty()

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)
Пример #24
0
    ip_dst_count = Counter()
    ip_src_size = Counter()
    ip_dst_size = Counter()

    tcp_src_count = Counter()
    tcp_dst_count = Counter()
    tcp_src_size = Counter()
    tcp_dst_size = Counter()

    for block in rdr:
        # print(repr(block))

        if isinstance(block, EnhancedPacket):
            assert block.interface.link_type == 1  # must be ethernet!

            decoded = Ether(block.packet_data)
            # print(repr(Ether(block.packet_data))[:400] + '...')

            _pl1 = decoded.payload
            if isinstance(_pl1, IP):
                ip_src_count[_pl1.src] += 1
                ip_dst_count[_pl1.dst] += 1
                ip_src_size[_pl1.src] += block.packet_len
                ip_dst_size[_pl1.dst] += block.packet_len

                _pl2 = _pl1.payload
                if isinstance(_pl2, TCP):
                    _src = '{0}:{1}'.format(_pl1.dst, _pl2.dport)
                    _dst = '{0}:{1}'.format(_pl1.src, _pl2.sport)
                    tcp_src_count[_src] += 1
                    tcp_dst_count[_dst] += 1
Пример #25
0
    def create_stream(self, src_ip_if, dst_ip_if, reverse, packet_sizes,
                      is_ip6, expect_blocked, expect_established,
                      add_extension_header):
        pkts = []
        rules = []
        permit_rules = []
        permit_and_reflect_rules = []
        total_packet_count = 8
        for i in range(0, total_packet_count):
            modulo = (i // 2) % 2
            can_reflect_this_packet = (modulo == 0)
            is_permit = i % 2
            remote_dst_index = i % len(dst_ip_if.remote_hosts)
            remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index]
            if is_permit == 1:
                info = self.create_packet_info(src_ip_if, dst_ip_if)
                payload = self.info_to_payload(info)
            else:
                to_be_blocked = False
                if (expect_blocked and not expect_established):
                    to_be_blocked = True
                if (not can_reflect_this_packet):
                    to_be_blocked = True
                if to_be_blocked:
                    payload = "to be blocked"
                else:
                    info = self.create_packet_info(src_ip_if, dst_ip_if)
                    payload = self.info_to_payload(info)
            if reverse:
                dst_mac = 'de:ad:00:00:00:00'
                src_mac = remote_dst_host._mac
                dst_ip6 = src_ip_if.remote_ip6
                src_ip6 = remote_dst_host.ip6
                dst_ip4 = src_ip_if.remote_ip4
                src_ip4 = remote_dst_host.ip4
                dst_l4 = 1234 + i
                src_l4 = 4321 + i
            else:
                dst_mac = src_ip_if.local_mac
                src_mac = src_ip_if.remote_mac
                src_ip6 = src_ip_if.remote_ip6
                dst_ip6 = remote_dst_host.ip6
                src_ip4 = src_ip_if.remote_ip4
                dst_ip4 = remote_dst_host.ip4
                src_l4 = 1234 + i
                dst_l4 = 4321 + i

            # default ULP should be something we do not use in tests
            ulp_l4 = TCP(sport=src_l4, dport=dst_l4)
            # potentially a chain of protocols leading to ULP
            ulp = ulp_l4

            if can_reflect_this_packet:
                if is_ip6:
                    ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
                    if add_extension_header:
                        # prepend some extension headers
                        ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() /
                               IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4)
                        # uncomment below to test invalid ones
                        # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4
                    else:
                        ulp = ulp_l4
                    p = (Ether(dst=dst_mac, src=src_mac) /
                         IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload))
                else:
                    ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
                    # IPv4 does not allow extension headers,
                    # but we rather make it a first fragment
                    flags = 1 if add_extension_header else 0
                    ulp = ulp_l4
                    p = (Ether(dst=dst_mac, src=src_mac) /
                         IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) /
                         ulp / Raw(payload))
            elif modulo == 1:
                if is_ip6:
                    ulp_l4 = ICMPv6Unknown(type=128 + (i % 2), code=i % 2)
                    ulp = ulp_l4
                    p = (Ether(dst=dst_mac, src=src_mac) /
                         IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload))
                else:
                    ulp_l4 = ICMP(type=8 + (i % 2), code=i % 2)
                    ulp = ulp_l4
                    p = (Ether(dst=dst_mac, src=src_mac) /
                         IP(src=src_ip4, dst=dst_ip4) / ulp / Raw(payload))

            if i % 2 == 1:
                info.data = p.copy()
            size = packet_sizes[(i // 2) % len(packet_sizes)]
            self.extend_packet(p, size)
            pkts.append(p)

            rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET
            rule_prefix_len = 128 if p.haslayer(IPv6) else 32
            rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP

            if p.haslayer(UDP):
                rule_l4_sport = p[UDP].sport
                rule_l4_dport = p[UDP].dport
            else:
                if p.haslayer(ICMP):
                    rule_l4_sport = p[ICMP].type
                    rule_l4_dport = p[ICMP].code
                else:
                    rule_l4_sport = p[ICMPv6Unknown].type
                    rule_l4_dport = p[ICMPv6Unknown].code
            if p.haslayer(IPv6):
                rule_l4_proto = ulp_l4.overload_fields[IPv6]['nh']
            else:
                rule_l4_proto = p[IP].proto

            new_rule = {
                'is_permit': is_permit,
                'is_ipv6': p.haslayer(IPv6),
                'src_ip_addr': inet_pton(rule_family, p[rule_l3_layer].src),
                'src_ip_prefix_len': rule_prefix_len,
                'dst_ip_addr': inet_pton(rule_family, p[rule_l3_layer].dst),
                'dst_ip_prefix_len': rule_prefix_len,
                'srcport_or_icmptype_first': rule_l4_sport,
                'srcport_or_icmptype_last': rule_l4_sport,
                'dstport_or_icmpcode_first': rule_l4_dport,
                'dstport_or_icmpcode_last': rule_l4_dport,
                'proto': rule_l4_proto,
            }
            rules.append(new_rule)
            new_rule_permit = new_rule.copy()
            new_rule_permit['is_permit'] = 1
            permit_rules.append(new_rule_permit)

            new_rule_permit_and_reflect = new_rule.copy()
            if can_reflect_this_packet:
                new_rule_permit_and_reflect['is_permit'] = 2
            else:
                new_rule_permit_and_reflect['is_permit'] = is_permit
            permit_and_reflect_rules.append(new_rule_permit_and_reflect)

        return {
            'stream': pkts,
            'rules': rules,
            'permit_rules': permit_rules,
            'permit_and_reflect_rules': permit_and_reflect_rules
        }
Пример #26
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)
Пример #27
0
    def test_qos_vlan(self):
        """QoS mark/record VLAN """

        #
        # QoS for all input values
        #
        output = [chr(0)] * 256
        for i in range(0, 255):
            output[i] = chr(255 - i)
        os = ''.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(chr(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(chr(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(chr(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(chr(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)
Пример #28
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)

        #
        # 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
        #      the router
        #
        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")

        #
        # 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()
Пример #29
0
    def test_dhcp_client(self):
        """ DHCP Client"""

        hostname = 'universal-dp'

        self.pg_enable_capture(self.pg_interfaces)

        #
        # Configure DHCP client on PG2 and capture the discover sent
        #
        self.vapi.dhcp_client(self.pg2.sw_if_index, hostname)

        rx = self.pg2.get_capture(1)

        self.verify_orig_dhcp_discover(rx[0], self.pg2, hostname)

        #
        # Sned back on offer, expect the request
        #
        p_offer = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
                   IP(src=self.pg2.remote_ip4, dst="255.255.255.255") /
                   UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
                   BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
                   DHCP(options=[('message-type', 'offer'),
                                 ('server_id', self.pg2.remote_ip4), ('end')]))

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

        rx = self.pg2.get_capture(1)
        self.verify_orig_dhcp_request(rx[0], self.pg2, hostname,
                                      self.pg2.local_ip4)

        #
        # Send an acknowloedgement
        #
        p_ack = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
                 IP(src=self.pg2.remote_ip4, dst="255.255.255.255") /
                 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
                 BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
                 DHCP(options=[('message-type',
                                'ack'), ('subnet_mask', "255.255.255.0"),
                               ('router', self.pg2.remote_ip4),
                               ('server_id', self.pg2.remote_ip4),
                               ('lease_time', 43200), ('end')]))

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

        #
        # We'll get an ARP request for the router address
        #
        rx = self.pg2.get_capture(1)

        self.assertEqual(rx[0][ARP].pdst, self.pg2.remote_ip4)
        self.pg_enable_capture(self.pg_interfaces)

        #
        # At the end of this procedure there should be a connected route
        # in the FIB
        #
        self.assertTrue(find_route(self, self.pg2.local_ip4, 24))
        self.assertTrue(find_route(self, self.pg2.local_ip4, 32))

        # remove the left over ARP entry
        self.vapi.ip_neighbor_add_del(self.pg2.sw_if_index,
                                      mactobinary(self.pg2.remote_mac),
                                      self.pg2.remote_ip4,
                                      is_add=0)
        #
        # remove the DHCP config
        #
        self.vapi.dhcp_client(self.pg2.sw_if_index, hostname, is_add=0)

        #
        # and now the route should be gone
        #
        self.assertFalse(find_route(self, self.pg2.local_ip4, 32))
        self.assertFalse(find_route(self, self.pg2.local_ip4, 24))

        #
        # Start the procedure again. this time have VPP send the client-ID
        #
        self.pg2.admin_down()
        self.sleep(1)
        self.pg2.admin_up()
        self.vapi.dhcp_client(self.pg2.sw_if_index,
                              hostname,
                              client_id=self.pg2.local_mac)

        rx = self.pg2.get_capture(1)

        self.verify_orig_dhcp_discover(rx[0], self.pg2, hostname,
                                       self.pg2.local_mac)

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

        rx = self.pg2.get_capture(1)
        self.verify_orig_dhcp_request(rx[0], self.pg2, hostname,
                                      self.pg2.local_ip4)

        #
        # unicast the ack to the offered address
        #
        p_ack = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
                 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
                 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
                 BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
                 DHCP(options=[('message-type',
                                'ack'), ('subnet_mask', "255.255.255.0"),
                               ('router', self.pg2.remote_ip4),
                               ('server_id', self.pg2.remote_ip4),
                               ('lease_time', 43200), ('end')]))

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

        #
        # At the end of this procedure there should be a connected route
        # in the FIB
        #
        self.assertTrue(find_route(self, self.pg2.local_ip4, 32))
        self.assertTrue(find_route(self, self.pg2.local_ip4, 24))

        #
        # remove the DHCP config
        #
        self.vapi.dhcp_client(self.pg2.sw_if_index, hostname, is_add=0)

        self.assertFalse(find_route(self, self.pg2.local_ip4, 32))
        self.assertFalse(find_route(self, self.pg2.local_ip4, 24))
Пример #30
0
    def test_proxy_mirror_arp(self):
        """ Interface Mirror Proxy ARP """

        #
        # When VPP has an interface whose address is also applied to a TAP
        # interface on the host, then VPP's TAP interface will be unnumbered
        # to the 'real' interface and do proxy ARP from the host.
        # the curious aspect of this setup is that ARP requests from the host
        # will come from the VPP's own address.
        #
        self.pg0.generate_remote_hosts(2)

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

        #
        # Configure Proxy ARP for the subnet on PG0addresses on pg0
        #
        self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
                                    self.pg0._local_ip4n_bcast)

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

        #
        # Enable pg2 for proxy ARP
        #
        self.pg2.set_proxy_arp()

        #
        # Send the ARP request with an originating address that
        # is VPP's own address
        #
        self.pg2.add_stream(arp_req_from_me)
        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.pg0.remote_hosts[1].ip4,
                             self.pg0.local_ip4)

        #
        # validate we have not learned an ARP entry as a result of this
        #
        self.assertFalse(find_nbr(self,
                                  self.pg2.sw_if_index,
                                  self.pg0.local_ip4))

        #
        # cleanup
        #
        self.pg2.set_proxy_arp(0)
        self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
                                    self.pg0._local_ip4n_bcast,
                                    is_add=0)
Пример #31
0
    def test_dhcp6_proxy(self):
        """ DHCPv6 Proxy"""
        #
        # Verify no response to DHCP request without DHCP config
        #
        dhcp_solicit_dst = "ff02::1:2"
        dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg2.remote_mac)
        dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg3.remote_mac)
        server_addr_vrf0 = self.pg0.remote_ip6n
        src_addr_vrf0 = self.pg0.local_ip6n
        server_addr_vrf1 = self.pg1.remote_ip6n
        src_addr_vrf1 = self.pg1.local_ip6n

        dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst))
        p_solicit_vrf0 = (
            Ether(dst=dmac, src=self.pg2.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf0, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())
        p_solicit_vrf1 = (
            Ether(dst=dmac, src=self.pg3.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())

        self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # DHCPv6 config in VRF 0.
        # Packets still dropped because the client facing interface has no
        # IPv6 config
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1)

        self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # configure an IP address on the client facing interface
        #
        self.pg2.config_ip6()

        #
        # Now the DHCP requests are relayed to the server
        #
        self.pg2.add_stream(p_solicit_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg0, dhcp_solicit_src_vrf0,
                                  self.pg2.remote_mac)

        #
        # Exception cases for rejected relay responses
        #

        # 1 - not a relay reply
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 not a relay reply")

        # 2 - no relay message option
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP not a relay message")

        # 3 - no circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6OptRelayMsg(optlen=0) /
                      DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 no circuit ID")
        # 4 - wrong circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 wrong circuit ID")

        #
        # Send the relay response (the advertisement)
        #   - no peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

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

        rx = self.pg2.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg2, "::")

        #
        # Send the relay response (the advertisement)
        #   - with peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

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

        rx = self.pg2.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg2, dhcp_solicit_src_vrf0)

        #
        # Add all the config for VRF 1
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1)
        self.pg3.config_ip6()

        #
        # VRF 1 solicit
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # VRF 1 Advert
        #
        p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                      IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf1 = [p_adv_vrf1]

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

        rx = self.pg3.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1)

        #
        # Add VSS config
        #  table=1, fib=id=1, oui=4
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1)

        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0],
                                  self.pg1,
                                  dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac,
                                  fib_id=1,
                                  oui=4)

        #
        # Remove the VSS config
        #  relayed DHCP has default vlaues in the option.
        #
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1, is_add=0)

        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # Add a second DHCP server in VRF 1
        #  expect clients messages to be relay to both configured servers
        #
        self.pg1.generate_remote_hosts(2)
        server_addr2 = socket.inet_pton(AF_INET6, self.pg1.remote_hosts[1].ip6)

        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1)

        #
        # We'll need an ND entry for the server to send it packets
        #
        nd_entry = VppNeighbor(self,
                               self.pg1.sw_if_index,
                               self.pg1.remote_hosts[1].mac,
                               self.pg1.remote_hosts[1].ip6,
                               af=AF_INET6)
        nd_entry.add_vpp_config()

        #
        # Send a discover from the client. expect two relayed messages
        # The frist packet is sent to the second server
        # We're not enforcing that here, it's just the way it is.
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(2)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)
        self.verify_dhcp6_solicit(rx[1],
                                  self.pg1,
                                  dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac,
                                  dst_mac=self.pg1.remote_hosts[1].mac,
                                  dst_ip=self.pg1.remote_hosts[1].ip6)

        #
        # Send both packets back. Client gets both.
        #
        p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
              IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
              IPv6(dst=self.pg1.local_ip6, src=self.pg1._remote_hosts[1].ip6) /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))

        pkts = [p1, p2]

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

        rx = self.pg3.get_capture(2)

        self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1)
        self.verify_dhcp6_advert(rx[1], self.pg3, dhcp_solicit_src_vrf1)

        #
        # Ensure only solicit messages are duplicated
        #
        p_request_vrf1 = (
            Ether(dst=dmac, src=self.pg3.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Request())

        self.pg3.add_stream(p_request_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        #
        # Test we drop DHCP packets from addresses that are not configured as
        # DHCP servers
        #
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
              IPv6(dst=self.pg1.local_ip6, src="3001::1") /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))
        self.send_and_assert_no_replies(self.pg1, p2, "DHCP6 not from server")

        #
        # Remove the second DHCP server
        #
        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1,
                                    is_add=0)

        #
        # Test we can still relay with the first
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # Cleanup
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1,
                                    is_add=0)
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1,
                                    is_add=0)

        # duplicate delete
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1,
                                    is_add=0)
        self.pg2.unconfig_ip6()
        self.pg3.unconfig_ip6()
Пример #32
0
    def test_proxy_arp(self):
        """ Proxy ARP """

        self.pg1.generate_remote_hosts(2)

        #
        # Proxy ARP rewquest packets for each interface
        #
        arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
                             dst="ff:ff:ff:ff:ff:ff") /
                       ARP(op="who-has",
                           hwsrc=self.pg0.remote_mac,
                           pdst="10.10.10.3",
                           psrc=self.pg0.remote_ip4))
        arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
                                    dst="ff:ff:ff:ff:ff:ff") /
                              Dot1Q(vlan=0) /
                              ARP(op="who-has",
                                  hwsrc=self.pg0.remote_mac,
                                  pdst="10.10.10.3",
                                  psrc=self.pg0.remote_ip4))
        arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
                             dst="ff:ff:ff:ff:ff:ff") /
                       ARP(op="who-has",
                           hwsrc=self.pg1.remote_mac,
                           pdst="10.10.10.3",
                           psrc=self.pg1.remote_ip4))
        arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
                             dst="ff:ff:ff:ff:ff:ff") /
                       ARP(op="who-has",
                           hwsrc=self.pg2.remote_mac,
                           pdst="10.10.10.3",
                           psrc=self.pg1.remote_hosts[1].ip4))
        arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
                             dst="ff:ff:ff:ff:ff:ff") /
                       ARP(op="who-has",
                           hwsrc=self.pg3.remote_mac,
                           pdst="10.10.10.3",
                           psrc=self.pg3.remote_ip4))

        #
        # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
        #
        self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
                                    inet_pton(AF_INET, "10.10.10.124"))

        #
        # No responses are sent when the interfaces are not enabled for proxy
        # ARP
        #
        self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
                                        "ARP req from unconfigured interface")
        self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
                                        "ARP req from unconfigured interface")

        #
        # Make pg2 un-numbered to pg1
        #  still won't reply.
        #
        self.pg2.set_unnumbered(self.pg1.sw_if_index)

        self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
                                        "ARP req from unnumbered interface")

        #
        # Enable each interface to reply to proxy ARPs
        #
        for i in self.pg_interfaces:
            i.set_proxy_arp()

        #
        # Now each of the interfaces should reply to a request to a proxied
        # address
        #
        self.pg0.add_stream(arp_req_pg0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)
        self.verify_arp_resp(rx[0],
                             self.pg0.local_mac,
                             self.pg0.remote_mac,
                             "10.10.10.3",
                             self.pg0.remote_ip4)

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

        rx = self.pg0.get_capture(1)
        self.verify_arp_resp(rx[0],
                             self.pg0.local_mac,
                             self.pg0.remote_mac,
                             "10.10.10.3",
                             self.pg0.remote_ip4)

        self.pg1.add_stream(arp_req_pg1)
        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,
                             "10.10.10.3",
                             self.pg1.remote_ip4)

        self.pg2.add_stream(arp_req_pg2)
        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,
                             "10.10.10.3",
                             self.pg1.remote_hosts[1].ip4)

        #
        # A request for an address out of the configured range
        #
        arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
                                dst="ff:ff:ff:ff:ff:ff") /
                          ARP(op="who-has",
                              hwsrc=self.pg1.remote_mac,
                              pdst="10.10.10.125",
                              psrc=self.pg1.remote_ip4))
        self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
                                        "ARP req out of range HI")
        arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
                                 dst="ff:ff:ff:ff:ff:ff") /
                           ARP(op="who-has",
                               hwsrc=self.pg1.remote_mac,
                               pdst="10.10.10.1",
                               psrc=self.pg1.remote_ip4))
        self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
                                        "ARP req out of range Low")

        #
        # Request for an address in the proxy range but from an interface
        # in a different VRF
        #
        self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
                                        "ARP req from different VRF")

        #
        # Disable Each interface for proxy ARP
        #  - expect none to respond
        #
        for i in self.pg_interfaces:
            i.set_proxy_arp(0)

        self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
                                        "ARP req from disable")
        self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
                                        "ARP req from disable")
        self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
                                        "ARP req from disable")

        #
        # clean up on interface 2
        #
        self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Пример #33
0
    def _get_gw_mac_address_v4(self, ip: IPAddress, vlan: str = "") -> str:
        try:
            gw_ip = ipaddress.ip_address(ip.address)
            self.logger.debug(
                "sending arp via egress: %s",
                self.config.non_nat_arp_egress_port,
            )
            eth_mac_src = get_if_hwaddr(self.config.non_nat_arp_egress_port)
            psrc = "0.0.0.0"
            egress_port_ip = get_if_addr(self.config.non_nat_arp_egress_port)
            if egress_port_ip:
                psrc = egress_port_ip

            pkt = Ether(dst=ETHER_BROADCAST, src=eth_mac_src)
            if vlan.isdigit():
                pkt /= Dot1Q(vlan=int(vlan))
            pkt /= ARP(op="who-has", pdst=gw_ip, hwsrc=eth_mac_src, psrc=psrc)
            self.logger.debug("ARP Req pkt %s", pkt.show(dump=True))

            res = srp1(
                pkt,
                type=ETH_P_ALL,
                iface=self.config.non_nat_arp_egress_port,
                timeout=1,
                verbose=0,
                nofilter=1,
                promisc=0,
            )

            if res is not None:
                self.logger.debug("ARP Res pkt %s", res.show(dump=True))
                if str(res[ARP].psrc) != str(gw_ip):
                    self.logger.warning(
                        "Unexpected IP in ARP response. expected: %s pkt: %s",
                        str(gw_ip),
                        res.show(dump=True),
                    )
                    return ""
                if vlan.isdigit():
                    if Dot1Q in res and str(res[Dot1Q].vlan) == vlan:
                        mac = res[ARP].hwsrc
                    else:
                        self.logger.warning(
                            "Unexpected vlan in ARP response. expected: %s pkt: %s",
                            vlan,
                            res.show(dump=True),
                        )
                        return ""
                else:
                    mac = res[ARP].hwsrc
                return mac
            else:
                self.logger.debug("Got Null response")
                return ""

        except Scapy_Exception as ex:
            self.logger.warning("Error in probing Mac address: err %s", ex)
            return ""
        except ValueError:
            self.logger.warning(
                "Invalid GW Ip address: [%s] or vlan %s",
                str(ip),
                vlan,
            )
            return ""
Пример #34
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" % scapy.compat.raw(src_mac)

            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

                acl_rule = {
                    'is_permit': is_permit,
                    'is_ipv6': is_ip6,
                    'src_ip_addr': inet_pton(rule_family,
                                             packet[rule_l3_layer].src),
                    'src_ip_prefix_len': rule_prefix_len,
                    'dst_ip_addr': inet_pton(rule_family,
                                             packet[rule_l3_layer].dst),
                    'dst_ip_prefix_len': rule_prefix_len,
                    'srcport_or_icmptype_first': rule_l4_sport,
                    'srcport_or_icmptype_last': rule_l4_sport,
                    'dstport_or_icmpcode_first': rule_l4_dport,
                    'dstport_or_icmpcode_last': rule_l4_dport,
                    'proto': rule_l4_proto}
                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 = ({
                    'is_permit': is_permit,
                    'is_ipv6': is_ip6,
                    'src_ip_addr': ip_rule,
                    'src_ip_prefix_len': prefix_len,
                    'src_mac': binascii.unhexlify(mac_rule.replace(':', '')),
                    'src_mac_mask': binascii.unhexlify(
                        mac_mask.replace(':', ''))})
                macip_rules.append(macip_rule)

        # deny all other packets
        if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP):
            macip_rule = ({'is_permit': 0,
                           'is_ipv6': is_ip6,
                           'src_ip_addr': "",
                           'src_ip_prefix_len': 0,
                           'src_mac': "",
                           'src_mac_mask': ""})
            macip_rules.append(macip_rule)

        acl_rule = {'is_permit': 0,
                    'is_ipv6': is_ip6}
        acl_rules.append(acl_rule)
        return {'stream': packets,
                'macip_rules': macip_rules,
                'acl_rules': acl_rules}
Пример #35
0
 def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=100):
     return [
         Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
         IPv6(src=src, dst=dst) / UDP(sport=1166, dport=2233) /
         Raw(b'X' * payload_size) for i in range(count)
     ]
Пример #36
0
async def run_test_nic(dut):

    tb = TB(dut)

    await tb.init()

    tb.log.info("Init driver")
    await tb.driver.init_dev(tb.dev.functions[0].pcie_id)
    await tb.driver.interfaces[0].open()
    # await driver.interfaces[1].open()

    # enable queues
    tb.log.info("Enable queues")
    await tb.rc.mem_write_dword(tb.driver.interfaces[0].ports[0].hw_addr+mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001)
    for k in range(tb.driver.interfaces[0].tx_queue_count):
        await tb.rc.mem_write_dword(tb.driver.interfaces[0].ports[0].schedulers[0].hw_addr+4*k, 0x00000003)

    # wait for all writes to complete
    await tb.rc.mem_read(tb.driver.hw_addr, 4)
    tb.log.info("Init complete")

    tb.log.info("Send and receive single packet")

    data = bytearray([x % 256 for x in range(1024)])

    await tb.driver.interfaces[0].start_xmit(data, 0)

    pkt = await tb.qsfp0_mac.tx.recv()
    tb.log.info("Packet: %s", pkt)

    await tb.qsfp0_mac.rx.send(pkt)

    pkt = await tb.driver.interfaces[0].recv()

    tb.log.info("Packet: %s", pkt)
    assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff

    # await tb.driver.interfaces[1].start_xmit(data, 0)

    # pkt = await tb.qsfp1_mac.tx.recv()
    # tb.log.info("Packet: %s", pkt)

    # await tb.qsfp1_mac.rx.send(pkt)

    # pkt = await tb.driver.interfaces[1].recv()

    # tb.log.info("Packet: %s", pkt)
    # assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff

    tb.log.info("RX and TX checksum tests")

    payload = bytes([x % 256 for x in range(256)])
    eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5')
    ip = IP(src='192.168.1.100', dst='192.168.1.101')
    udp = UDP(sport=1, dport=2)
    test_pkt = eth / ip / udp / payload

    test_pkt2 = test_pkt.copy()
    test_pkt2[UDP].chksum = scapy.utils.checksum(bytes(test_pkt2[UDP]))

    await tb.driver.interfaces[0].start_xmit(test_pkt2.build(), 0, 34, 6)

    pkt = await tb.qsfp0_mac.tx.recv()
    tb.log.info("Packet: %s", pkt)

    await tb.qsfp0_mac.rx.send(pkt)

    pkt = await tb.driver.interfaces[0].recv()

    tb.log.info("Packet: %s", pkt)
    assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff
    assert Ether(pkt.data).build() == test_pkt.build()

    tb.log.info("Multiple small packets")

    count = 64

    pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]

    tb.loopback_enable = True

    for p in pkts:
        await tb.driver.interfaces[0].start_xmit(p, 0)

    for k in range(count):
        pkt = await tb.driver.interfaces[0].recv()

        tb.log.info("Packet: %s", pkt)
        assert pkt.data == pkts[k]
        assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff

    tb.loopback_enable = False

    tb.log.info("Multiple large packets")

    count = 64

    pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]

    tb.loopback_enable = True

    for p in pkts:
        await tb.driver.interfaces[0].start_xmit(p, 0)

    for k in range(count):
        pkt = await tb.driver.interfaces[0].recv()

        tb.log.info("Packet: %s", pkt)
        assert pkt.data == pkts[k]
        assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff

    tb.loopback_enable = False

    tb.log.info("Jumbo frames")

    count = 64

    pkts = [bytearray([(x+k) % 256 for x in range(9014)]) for k in range(count)]

    tb.loopback_enable = True

    for p in pkts:
        await tb.driver.interfaces[0].start_xmit(p, 0)

    for k in range(count):
        pkt = await tb.driver.interfaces[0].recv()

        tb.log.info("Packet: %s", pkt)
        assert pkt.data == pkts[k]
        assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff

    tb.loopback_enable = False

    await RisingEdge(dut.clk_250mhz)
    await RisingEdge(dut.clk_250mhz)
Пример #37
0
    def create_stream(self, src_if, packet_sizes, traffic_type=0, ipv6=0,
                      proto=-1, ports=0, fragments=False,
                      pkt_raw=True, etype=-1):
        """
        Create input packet stream for defined interface using hosts or
        deleted_hosts list.

        :param object src_if: Interface to create packet stream for.
        :param list packet_sizes: List of required packet sizes.
        :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
        :return: Stream of packets.
        """
        pkts = []
        if self.flows.__contains__(src_if):
            src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
            for dst_if in self.flows[src_if]:
                dst_hosts = self.hosts_by_pg_idx[dst_if.sw_if_index]
                n_int = len(dst_hosts) * len(src_hosts)
                for i in range(0, n_int):
                    dst_host = dst_hosts[i / len(src_hosts)]
                    src_host = src_hosts[i % len(src_hosts)]
                    pkt_info = self.create_packet_info(src_if, dst_if)
                    if ipv6 == 1:
                        pkt_info.ip = 1
                    elif ipv6 == 0:
                        pkt_info.ip = 0
                    else:
                        pkt_info.ip = random.choice([0, 1])
                    if proto == -1:
                        pkt_info.proto = random.choice(self.proto[self.IP])
                    else:
                        pkt_info.proto = proto
                    payload = self.info_to_payload(pkt_info)
                    p = Ether(dst=dst_host.mac, src=src_host.mac)
                    if etype > 0:
                        p = Ether(dst=dst_host.mac,
                                  src=src_host.mac,
                                  type=etype)
                    if pkt_info.ip:
                        p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
                        if fragments:
                            p /= IPv6ExtHdrFragment(offset=64, m=1)
                    else:
                        if fragments:
                            p /= IP(src=src_host.ip4, dst=dst_host.ip4,
                                    flags=1, frag=64)
                        else:
                            p /= IP(src=src_host.ip4, dst=dst_host.ip4)
                    if traffic_type == self.ICMP:
                        if pkt_info.ip:
                            p /= ICMPv6EchoRequest(type=self.icmp6_type,
                                                   code=self.icmp6_code)
                        else:
                            p /= ICMP(type=self.icmp4_type,
                                      code=self.icmp4_code)
                    else:
                        p /= self.create_upper_layer(i, pkt_info.proto, ports)
                    if pkt_raw:
                        p /= Raw(payload)
                        pkt_info.data = p.copy()
                    if pkt_raw:
                        size = random.choice(packet_sizes)
                        self.extend_packet(p, size)
                    pkts.append(p)
        return pkts
Пример #38
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()
Пример #39
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"))
Пример #40
0
async def run_test_offsets(dut,
                           payload_lengths=None,
                           payload_data=None,
                           idle_inserter=None,
                           backpressure_inserter=None):

    tb = TB(dut)

    await tb.reset()

    tb.set_idle_generator(idle_inserter)
    tb.set_backpressure_generator(backpressure_inserter)

    test_pkts = []
    test_frames = []
    check_frames = []

    ip_id = 1

    for payload in [payload_data(x) for x in payload_lengths()]:
        eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5')
        test_pkt = eth / payload

        ip_id = (ip_id + 1) & 0xffff

        for start in range(0, min(len(payload) + 14, 32)):
            offset = 0
            test_pkts.append(test_pkt.copy())
            test_frame = AxiStreamFrame(test_pkt.build())
            test_frames.append(test_frame)

            await tb.source.send(test_frame)
            await tb.cmd_source.send(
                CsumCmdTransaction(csum_enable=1,
                                   csum_start=start,
                                   csum_offset=offset,
                                   csum_init=0))

            csum = scapy.utils.checksum(bytes(test_pkt)[start:])

            check_frame = bytearray(test_frame.tdata)
            struct.pack_into('>H', check_frame, offset, csum)

            check_frames.append(check_frame)

        for offset in range(0, min(len(payload) + 14, 32) - 1):
            start = 0
            test_pkts.append(test_pkt.copy())
            test_frame = AxiStreamFrame(test_pkt.build())
            test_frames.append(test_frame)

            await tb.source.send(test_frame)
            await tb.cmd_source.send(
                CsumCmdTransaction(csum_enable=1,
                                   csum_start=start,
                                   csum_offset=offset,
                                   csum_init=0))

            csum = scapy.utils.checksum(bytes(test_pkt)[start:])

            check_frame = bytearray(test_frame.tdata)
            struct.pack_into('>H', check_frame, offset, csum)

            check_frames.append(check_frame)

    for test_pkt, test_frame, check_frame in zip(test_pkts, test_frames,
                                                 check_frames):
        rx_frame = await tb.sink.recv()

        rx_pkt = Ether(bytes(rx_frame))

        tb.log.info("RX packet: %s", repr(rx_pkt))

        assert rx_frame.tdata == check_frame

    assert tb.sink.empty()

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)