Ejemplo n.º 1
0
class TestEtag(TestCase):
    supported_vf_driver = ['pci-stub', 'vfio-pci']

    def set_up_all(self):
        self.dut_ports = self.dut.get_ports(self.nic)
        self.verify(self.nic in ['sagepond', 'sageville'],
                    '802.1BR only support by sagepond and sageville')
        self.verify(len(self.dut_ports) >= 1, 'Insufficient ports')
        self.src_intf = self.tester.get_interface(
            self.tester.get_local_port(0))
        self.src_mac = self.tester.get_mac(self.tester.get_local_port(0))
        self.dst_mac = self.dut.get_mac_address(0)
        self.vm0 = None
        self.printFlag = self._enable_debug
        self.dut.send_expect('ls', '#')
        self.setup_vm_env_flag = 0
        self.preset_host_cmds = list()

    def set_up(self):
        pass

    def setup_vm_env(self, driver='default'):
        '''
        setup qemu virtual environment
        '''
        if self.setup_vm_env_flag == 1:
            return

        self.used_dut_port_0 = self.dut_ports[0]
        self.dut.generate_sriov_vfs_by_port(self.used_dut_port_0,
                                            2,
                                            driver=driver)
        self.sriov_vfs_port_0 = self.dut.ports_info[
            self.used_dut_port_0]['vfs_port']

        # set vf assign method and vf driver
        self.vf_driver = self.get_suite_cfg()['vf_driver']
        if self.vf_driver is None:
            self.vf_driver = 'pci-stub'
        self.verify(self.vf_driver in self.supported_vf_driver,
                    "Unspported vf driver")
        if self.vf_driver == 'pci-stub':
            self.vf_assign_method = 'pci-assign'
        else:
            self.vf_assign_method = 'vfio-pci'
            self.dut.send_expect('modprobe vfio-pci', '#')

        try:
            for port in self.sriov_vfs_port_0:
                port.bind_driver(self.vf_driver)

            time.sleep(1)
            vf0_prop = {'opt_host': self.sriov_vfs_port_0[0].pci}
            vf1_prop = {'opt_host': self.sriov_vfs_port_0[1].pci}

            # start testpmd without the two VFs on the host
            self.host_testpmd = PmdOutput(self.dut)
            eal_param = '-b %(vf0)s -b %(vf1)s' % {
                'vf0': self.sriov_vfs_port_0[0].pci,
                'vf1': self.sriov_vfs_port_0[1].pci
            }

            self.preset_host_testpmd(VM_CORES_MASK, eal_param)

            # set up VM0 ENV
            self.vm0 = QEMUKvm(self.dut, 'vm0', 'vf_etag')
            self.vm0.set_vm_device(driver=self.vf_assign_method, **vf0_prop)
            self.vm0.set_vm_device(driver=self.vf_assign_method, **vf1_prop)
            self.vm_dut_0 = self.vm0.start()
            if self.vm_dut_0 is None:
                raise Exception('Set up VM0 ENV failed!')

        except Exception as e:
            print e
            self.destroy_vm_env()
            raise Exception(e)

    def destroy_vm_env(self):
        #destroy testpmd in vm0
        if getattr(self, 'vm0_testpmd', None) and self.vm0_testpmd:
            self.vm0_testpmd.execute_cmd('stop')
            self.vm0_testpmd.execute_cmd('quit', '# ')
            self.vm0_testpmd = None

        #destroy vm0
        if getattr(self, 'vm0', None) and self.vm0:
            self.vm0_dut_ports = None
            self.vm0.stop()
            self.vm0 = None

        #destroy host testpmd
        if getattr(self, 'host_testpmd', None):
            self.host_testpmd.execute_cmd('quit', '# ')
            self.host_testpmd = None

        # reset used port's sriov
        if getattr(self, 'used_dut_port_0', None):
            self.dut.destroy_sriov_vfs_by_port(self.used_dut_port_0)
            port = self.dut.ports_info[self.used_dut_port_0]['port']
            port.bind_driver()
            self.used_dut_port_0 = None

        # bind used ports with default driver
        for port_id in self.dut_ports:
            port = self.dut.ports_info[port_id]['port']
            port.bind_driver()
        self.setup_vm_env_flag = 0

    def check_packet_transmission(self, pkt_types):
        time.sleep(1)
        for pkt_type in pkt_types.keys():
            intf = self.src_intf
            pkt = Packet(pkt_type=pkt_type)
            # set packet every layer's input parameters
            if 'layer_configs' in pkt_types[pkt_type].keys():
                pkt_configs = pkt_types[pkt_type]['layer_configs']
                if pkt_configs:
                    for layer in pkt_configs.keys():
                        pkt.config_layer(layer, pkt_configs[layer])
            pkt.send_pkt(tx_port=self.src_intf)

            # check vm testpmd packet received information
            if 'vm' in pkt_types[pkt_type].keys():
                out = self.vm0_testpmd.get_output(timeout=2)
                if self.printFlag:  # debug output
                    print out
                for pkt_attribute in pkt_types[pkt_type]['vm']:
                    if self.printFlag:  # debug output
                        print pkt_attribute
                    if pkt_attribute not in out:
                        print utils.RED('Fail to detect %s' % pkt_attribute)
                        if not self.printFlag:  # print out all info in debug mode
                            raise VerifyFailure('Failed to detect %s' %
                                                pkt_attribute)
                print utils.GREEN('VM detected %s successfully' % pkt_type)

            # check dut testpmd packet received information
            if 'dut' in pkt_types[pkt_type].keys():
                out = self.host_testpmd.get_output(timeout=2)
                if self.printFlag:  # debug output
                    print out
                for pkt_attribute in pkt_types[pkt_type]['dut']:
                    if self.printFlag:  # debug output
                        print pkt_attribute
                    if pkt_attribute not in out:
                        print utils.RED('Fail to detect %s' % pkt_attribute)
                        if not self.printFlag:  # print out all info in debug mode
                            raise VerifyFailure('Failed to detect %s' %
                                                pkt_attribute)
                print utils.GREEN('DUT detected %s successfully' % pkt_type)
            time.sleep(1)

    def preset_host_testpmd(self, core_mask, eal_param):
        if self.setup_vm_env_flag == 0:
            self.host_testpmd.start_testpmd(core_mask,
                                            param='--port-topology=loop',
                                            eal_param=eal_param)
            self.execute_host_testpmd_cmd(self.preset_host_cmds)
            self.preset_host_cmds = list()
            time.sleep(2)

    def execute_host_testpmd_cmd(self, cmds):
        if len(cmds) == 0:
            return
        for item in cmds:
            if len(item) == 2:
                self.host_testpmd.execute_cmd(item[0], int(item[1]))
            else:
                self.host_testpmd.execute_cmd(item[0])

        time.sleep(2)

    def preset_guest_testpmd(self):
        if self.setup_vm_env_flag == 0:
            self.vm0_testpmd = PmdOutput(self.vm_dut_0)
            self.vm0_testpmd.start_testpmd(VM_CORES_MASK,
                                           param='--port-topology=loop')
            time.sleep(1)
        elif self.vm0_testpmd:
            self.vm0_testpmd.quit()
            self.vm0_testpmd.start_testpmd(VM_CORES_MASK,
                                           param='--port-topology=loop')
            time.sleep(1)

    def execute_guest_testpmd_cmd(self, cmds):
        if len(cmds) == 0:
            return
        for item in cmds:
            if len(item) == 2:
                self.vm0_testpmd.execute_cmd(item[0], int(item[1]))
            else:
                self.vm0_testpmd.execute_cmd(item[0])

    def preset_test_enviroment(self):
        self.setup_vm_env(driver='igb_uio')
        self.preset_guest_testpmd()
        self.setup_vm_env_flag = 1
        time.sleep(2)

    def test_l2_tunnel_filter(self):
        '''
        Enable E-tag l2 tunnel support means enabling ability of parsing E-tag packet.
        This ability should be enabled before we enable filtering, forwarding,
        offloading for this specific type of tunnel.
        '''
        host_cmds = [['port config 0 l2-tunnel E-tag enable'],
                     ['set fwd rxonly'], ['set verbose 1'], ['start']]
        guest_cmds = [['set fwd rxonly'], ['set verbose 1'], ['start']]
        config_layers = {
            'ether': {
                'src': self.src_mac
            },
            'etag': {
                'ECIDbase': 1000
            }
        }
        pkt_types = {
            'ETAG_UDP': {
                'dut': ['type=0x893f'],
                'vm': ['type=0x893f'],
                'layer_configs': config_layers
            }
        }

        self.preset_test_enviroment()
        self.execute_host_testpmd_cmd(host_cmds)
        self.execute_guest_testpmd_cmd(guest_cmds)
        self.check_packet_transmission(pkt_types)

    def test_etag_filter(self):
        '''
        when E-tag packet forwarding and add E-tag on VF0
        '''
        test_types = ['etag_pf', 'etag_remove', 'etag_vf_0', 'etag_vf_1']
        host_cmds = [['port config 0 l2-tunnel E-tag enable'],
                     ['E-tag set forwarding on port 0']]
        self.preset_test_enviroment()
        self.execute_host_testpmd_cmd(host_cmds)
        for test_type in test_types:
            host_cmds = list()
            guest_cmds = [['set fwd rxonly'], ['set verbose 1'], ['start']]
            if test_type == 'etag_pf':
                # Same E-tag forwarding to PF0, Send 802.1BR packet with broadcast mac and
                # check packet only received on PF

                host_cmds = [[
                    'E-tag set filter add e-tag-id 1000 dst-pool 2 port 0'
                ], ['set fwd mac'], ['set verbose 1'], ['start']]
                # set packet type and its expecting result
                config_layers = {
                    'ether': {
                        'src': self.src_mac,
                        'dst': self.dst_mac
                    },
                    'etag': {
                        'ECIDbase': 1000
                    }
                }
                pkt_types = {
                    'ETAG_UDP': {
                        'dut': ['type=0x893f'],
                        'layer_configs': config_layers
                    }
                }
            elif test_type == 'etag_remove':
                # Remove E-tag, Send 802.1BR packet with broadcast mac and check packet not
                # received
                host_cmds = [['E-tag set filter del e-tag-id 1000 port 0'],
                             ['set fwd rxonly'], ['set verbose 1'], ['start']]
                config_layers = {
                    'ether': {
                        'src': self.src_mac
                    },
                    'etag': {
                        'ECIDbase': 1000
                    }
                }
                pkt_types = {
                    'ETAG_UDP': {
                        'vm': [''],
                        'dut': [''],
                        'layer_configs': config_layers
                    }
                }
            else:
                # Same E-tag forwarding to VF0, Send 802.1BR packet with broadcast mac and
                # check packet only received on VF0 or VF1
                host_cmds = [[
                    'E-tag set filter add e-tag-id 1000 dst-pool %d port 0' %
                    int(test_type[-1:])
                ], ['set fwd rxonly'], ['set verbose 1'], ['start']]
                config_layers = {
                    'ether': {
                        'src': self.src_mac
                    },
                    'etag': {
                        'ECIDbase': 1000
                    }
                }
                pkt_types = {
                    'ETAG_UDP': {
                        'vm': ['type=0x893f'],
                        'layer_configs': config_layers
                    }
                }

            self.execute_host_testpmd_cmd(host_cmds)
            self.execute_guest_testpmd_cmd(guest_cmds)
            self.check_packet_transmission(pkt_types)
        self.host_testpmd.execute_cmd('E-tag set forwarding off port 0')

    def test_etag_insertion(self):
        '''
        When E-tag insertion enable in VF0
        '''
        host_cmds = [['port config 0 l2-tunnel E-tag enable'],
                     ['E-tag set insertion on port-tag-id 1000 port 0 vf 0'],
                     ['set fwd mac'], ['set verbose 1'], ['start']]
        guest_cmds = [['set fwd mac'], ['set verbose 1'], ['start']]
        self.preset_test_enviroment()
        self.execute_host_testpmd_cmd(host_cmds)
        self.execute_guest_testpmd_cmd(guest_cmds)

        self.vm0_dut_ports = self.vm_dut_0.get_ports('any')
        config_layers = {'ether': {'src': self.src_mac}}
        pkt_types = {'IP_RAW': {'layer_configs': config_layers}}

        intf = self.src_intf
        inst = self.tester.tcpdump_sniff_packets(intf)

        self.check_packet_transmission(pkt_types)
        time.sleep(1)
        pkts = self.tester.load_tcpdump_sniff_packets(inst)
        self.host_testpmd.execute_cmd(
            'E-tag set insertion off port-tag-id 1000 port 0 vf 0')

        # load sniff pcap file, check received packet's content
        packetContentFile = "/tmp/packetContent.log"
        pcap_file = "/tmp/sniff_%s.pcap" % intf
        fp = open(packetContentFile, 'w')
        backup_out = sys.stdout
        sys.stdout = fp
        pkts = rdpcap(pcap_file)
        pkts.show()
        fp.close()
        sys.stdout = backup_out
        fp = open(packetContentFile, 'r')
        out = fp.read()
        fp.close()
        if self.printFlag:  # debug output
            print out
        self.verify("Dot1BR" in out,
                    "tester %s hasn't receiver etag packet" % intf)

    def test_etag_strip(self):
        '''
        When E-tag strip enable on PF
        '''
        host_cmds = [['port config 0 l2-tunnel E-tag enable'],
                     ['set fwd rxonly'], ['set verbose 1'], ['start']]
        guest_cmds = [['set fwd rxonly'], ['set verbose 1'], ['start']]
        config_layers = {
            'ether': {
                'src': self.src_mac
            },
            'etag': {
                'ECIDbase': 1000
            }
        }
        pkt_types_on = {
            'ETAG_UDP': {
                'vm': ['type=0x0800', 'type=0x893f'],
                'layer_configs': config_layers
            }
        }
        pkt_types_off = {
            'ETAG_UDP': {
                'vm': ['type=0x893f', 'type=0x893f'],
                'layer_configs': config_layers
            }
        }

        self.preset_test_enviroment()
        self.execute_host_testpmd_cmd(host_cmds)
        self.execute_guest_testpmd_cmd(guest_cmds)
        # Enable E-tag strip on PF, Send 802.1BR packet to VF and check forwarded packet without E-tag
        self.host_testpmd.execute_cmd('E-tag set stripping on port 0')
        self.check_packet_transmission(pkt_types_on)

        # Disable E-tag strip on PF, Send 802.1BR packet and check forwarded packet with E-tag
        self.host_testpmd.execute_cmd('E-tag set stripping off port 0')
        self.check_packet_transmission(pkt_types_off)

    def tear_down(self):
        pass

    def tear_down_all(self):
        if self.setup_vm_env_flag == 1:
            self.destroy_vm_env()

        if getattr(self, 'vm0', None):
            self.vm0.stop()

        for port_id in self.dut_ports:
            self.dut.destroy_sriov_vfs_by_port(port_id)

        self.tester.send_expect(
            "kill -9 $(ps aux | grep -i qemu | grep -v grep  | awk  {'print $2'})",
            '# ', 5)
Ejemplo n.º 2
0
class TestCloudFilter(TestCase):
    def set_up_all(self):
        """
        vxlan Prerequisites
        """
        # this feature only enable in FVL now
        self.verify(
            self.nic in [
                "fortville_eagle", "fortville_spirit",
                "fortville_spirit_single"
            ], "Cloud filter only supported by Fortville")
        # Based on h/w type, choose how many ports to use
        self.dut_ports = self.dut.get_ports()

        # Verify that enough ports are available
        self.verify(len(self.dut_ports) >= 1, "Insufficient ports for testing")

        # required setting test environment
        self.env_done = False
        self.vf_queues = 4

    def setup_vf_env(self):
        """
        Create testing environment with 2VFs generated from PF
        """
        if self.env_done:
            return

        # get PF interface name and opposite tester interface name
        self.pf_port = self.dut_ports[0]
        self.bind_nics_driver([self.pf_port], driver="i40e")
        self.pf_intf = self.dut.ports_info[self.pf_port]['intf']
        tester_port = self.tester.get_local_port(self.pf_port)
        self.tester_intf = self.tester.get_interface(tester_port)
        self.tester_mac = self.tester.get_mac(tester_port)
        pf_numa = self.dut.get_numa_id(self.pf_port)

        self.dut.generate_sriov_vfs_by_port(self.pf_port, 2, driver="default")

        # enable vxlan on PF
        self.dut.send_expect(
            "ip li add vxlan0 type vxlan id 1 group " +
            "239.1.1.1 local 127.0.0.1 dev %s" % self.pf_intf, "# ")
        self.dut.send_expect("ifconfig vxlan0 up", "# ")

        self.vf_port0 = self.dut.ports_info[self.pf_port]['vfs_port'][0]
        self.vf_port1 = self.dut.ports_info[self.pf_port]['vfs_port'][1]

        # bind one vf device to dpdk
        self.vf_port0.bind_driver(driver='igb_uio')
        self.vf_port1.bind_driver(driver='i40evf')
        self.vf_intf = self.vf_port1.intf_name

        # bind vf0 to igb_uio and start testpmd
        core_num = self.vf_queues + 1
        cores = "1S/%dC/1T" % core_num

        self.pmdout = PmdOutput(self.dut)
        self.pmdout.start_testpmd(
            cores,
            "--rxq=%d --txq=%d --portmask=0x1 --enable-rx-cksum" %
            (self.vf_queues, self.vf_queues),
            socket=pf_numa)

        # rxonly and verbose enabled
        self.pmdout.execute_cmd("set nbcore %d" % self.vf_queues)
        self.pmdout.execute_cmd("set fwd rxonly")
        self.pmdout.execute_cmd("set verbose 1")
        self.pmdout.execute_cmd("start")

        self.env_done = True

    def destroy_vf_env(self):

        if getattr(self, 'pmd_output', None):
            self.dut.kill_all()

        if getattr(self, 'pf_port', None):
            self.dut.destroy_sriov_vfs_by_port(self.pf_port)
            self.bind_nics_driver([self.pf_port], driver="igb_uio")

        self.env_done = False

    def bind_nics_driver(self, ports, driver=""):
        # modprobe vfio driver
        if driver == "vfio-pci":
            for port in ports:
                netdev = self.dut.ports_info[port]['port']
                driver = netdev.get_nic_driver()
                if driver != 'vfio-pci':
                    netdev.bind_driver(driver='vfio-pci')

        elif driver == "igb_uio":
            # igb_uio should insmod as default, no need to check
            for port in ports:
                netdev = self.dut.ports_info[port]['port']
                driver = netdev.get_nic_driver()
                if driver != 'igb_uio':
                    netdev.bind_driver(driver='igb_uio')
        else:
            for port in ports:
                netdev = self.dut.ports_info[port]['port']
                driver_now = netdev.get_nic_driver()
                if driver == "":
                    driver = netdev.default_driver
                if driver != driver_now:
                    netdev.bind_driver(driver=driver)

    def send_and_verify(self, cloud_cfg=None, dpdk=True):
        """
        Send packet match cloud filter rule and verify packet received
        """
        self.logger.info("Verifying vxlan %s filter" %
                         cloud_cfg.cf_rule['type'])
        if dpdk:
            cloud_cfg.transmit_packet()
            out = self.pmdout.get_output()
            print out
            queue = cloud_cfg.cf_rule['queue']
            self.verify("queue %d" % queue in out,
                        "Vxlan not received in queue %d" % queue)
            self.verify("VXLAN packet" in out, "Vxlan packet not detected")
            self.verify("Inner L4 type: TCP" in out,
                        "Vxlan inner L4 type not detected")
            if 'vni' in cloud_cfg.cf_rule.keys():
                vni = cloud_cfg.cf_rule['vni']
                self.verify("VNI = %d" % vni in out,
                            "Vxlan vni value not correct")
            if 'ivlan' in cloud_cfg.cf_rule.keys():
                self.verify("Inner L2 type: ETHER_VLAN" in out,
                            "Vxlan inner vlan not detected")
        else:
            # packet received on dut VF device
            tmp_file = '/tmp/cloud_filter_%s.pcap' % self.vf_intf
            sniff_cmd = ('tcpdump -w ' + tmp_file +
                         ' -i {0} 2>tcpdump_{0}.out &').format(self.vf_intf)
            rm_cmd = 'rm -f ' + tmp_file
            self.dut.send_expect(rm_cmd, '#', alt_session=True)
            self.dut.send_expect(sniff_cmd, '#', alt_session=True)
            # wait for interface promisc enable
            time.sleep(2)
            cloud_cfg.transmit_packet()
            self.dut.send_expect('killall tcpdump', '#', alt_session=True)
            # wait for pcap file saved
            time.sleep(2)
            # copy pcap to tester and then analyze
            self.dut.session.copy_file_from(tmp_file)
            pkts = load_pcapfile(filename="cloud_filter_%s.pcap" %
                                 self.vf_intf)
            self.verify(
                len(pkts) == 1, "%d packet recevied on kernel VF" % len(pkts))
            cap_pkt = pkts[0].pktgen.pkt
            try:
                dport = cap_pkt[UDP].dport
                self.verify(dport == CLOUD_PORT,
                            "Captured packet is not vxlan packet")
                inner_ip = cap_pkt[Vxlan][IP].dst
                self.verify(inner_ip == cloud_cfg.cf_rule['iip'],
                            "Inner ip not matched")
            except:
                print "Kernel VF captured packet not match rule"
                raise

        self.logger.info("Verified vxlan %s filter pass" %
                         cloud_cfg.cf_rule['type'])

    def test_cloud_filter(self):
        """
        Verify dpdk work with linux driver added cloud filter rule
        """
        # setting for cloud filter rule
        queue = self.vf_queues - 1
        vni = 1
        vlan = 1
        # add cloud filter rule
        rules = [
            {
                'type': 'iip',
                'iip': '192.168.1.1',
                'vf': 0,
                'queue': queue,
                'loc': 1
            },
            {
                'type': 'imac',
                'imac': '00:00:00:00:09:00',
                'vf': 0,
                'queue': queue,
                'loc': 1
            },
            {
                'type': 'omac+imac+vni',
                'omac': '00:00:00:00:10:00',
                'imac': '00:00:00:00:09:00',
                'vni': vni,
                'vf': 0,
                'queue': queue,
                'loc': 1
            },
            {
                'type': 'imac+ivlan+vni',
                'imac': '00:00:00:00:09:00',
                'ivlan': vlan,
                'vni': vni,
                'vf': 0,
                'queue': queue,
                'loc': 1
            },
            {
                'type': 'imac+ivlan',
                'imac': '00:00:00:00:09:00',
                'ivlan': vlan,
                'vf': 0,
                'queue': queue,
                'loc': 1
            },
        ]
        cf_cfg = CloudFilterConfig(self, self.pf_intf)
        for rule in rules:
            cf_cfg.config_rule(**rule)
            cf_cfg.ethtool_add()

            self.send_and_verify(cf_cfg)

            cf_cfg.ethtool_delete()

    def test_bifurcated_driver(self):
        """
        Verify bifurcated driver work with dpdk VF and kernel VF
        """
        rules = [{
            'type': 'iip',
            'iip': '192.168.1.1',
            'vf': 0,
            'queue': self.vf_queues - 1,
            'loc': 1
        }, {
            'type': 'iip',
            'iip': '192.168.2.1',
            'vf': 1,
            'queue': 0,
            'loc': 2
        }]

        dpdk_cfg = CloudFilterConfig(self, self.pf_intf)
        # fdir rule for dpdk VF
        dpdk_cfg.config_rule(**rules[0])
        dpdk_cfg.ethtool_add()
        self.send_and_verify(dpdk_cfg)
        # fdir rule for kernel VF
        kernel_cfg = CloudFilterConfig(self, self.pf_intf)
        kernel_cfg.config_rule(**rules[1])
        kernel_cfg.ethtool_add()
        self.send_and_verify(kernel_cfg, dpdk=False)

        pass

    def set_up(self):
        """
        Run before each test case.
        """
        self.setup_vf_env()
        pass

    def tear_down(self):
        """
        Run after each test case.
        """
        pass

    def tear_down_all(self):
        """
        Run after each test suite.
        """
        self.destroy_vf_env()
        pass