[dpdk-dev] [RFC PATCH 1/4] doc: fix file attributes
Signed-off-by: Thomas Monjalon --- doc/guides/prog_guide/i40e_ixgbe_igb_virt_func_drv.rst | 0 doc/guides/prog_guide/poll_mode_drv.rst| 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 doc/guides/prog_guide/i40e_ixgbe_igb_virt_func_drv.rst mode change 100755 => 100644 doc/guides/prog_guide/poll_mode_drv.rst diff --git a/doc/guides/prog_guide/i40e_ixgbe_igb_virt_func_drv.rst b/doc/guides/prog_guide/i40e_ixgbe_igb_virt_func_drv.rst old mode 100755 new mode 100644 diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst old mode 100755 new mode 100644 -- 2.2.2
[dpdk-dev] [RFC PATCH 2/4] doc: move Xen guide out of programmers guide
Xen is an environment comparable to Linux and FreeBSD which have their own guide. Signed-off-by: Thomas Monjalon --- MAINTAINERS | 2 +- doc/guides/index.rst| 1 + doc/guides/prog_guide/index.rst | 1 - doc/guides/{prog_guide => xen}/img/dpdk_xen_pkt_switch.png | Bin doc/guides/{prog_guide => xen}/img/grant_refs.png | Bin doc/guides/{prog_guide => xen}/img/grant_table.png | Bin .../index.rst} | 2 ++ 7 files changed, 4 insertions(+), 2 deletions(-) rename doc/guides/{prog_guide => xen}/img/dpdk_xen_pkt_switch.png (100%) rename doc/guides/{prog_guide => xen}/img/grant_refs.png (100%) rename doc/guides/{prog_guide => xen}/img/grant_table.png (100%) rename doc/guides/{prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst => xen/index.rst} (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 9a63714..1d9ddbc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -117,7 +117,7 @@ F: lib/librte_mempool/rte_dom0_mempool.c F: lib/librte_pmd_xenvirt/ F: app/test-pmd/mempool_* F: examples/vhost_xen/ -F: doc/guides/prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst +F: doc/guides/prog_guide/xen/index.rst FreeBSD EAL (with overlaps) F: lib/librte_eal/bsdapp/Makefile diff --git a/doc/guides/index.rst b/doc/guides/index.rst index c589a30..53f1be1 100644 --- a/doc/guides/index.rst +++ b/doc/guides/index.rst @@ -39,6 +39,7 @@ Contents: linux_gsg/index freebsd_gsg/index + xen/index prog_guide/index sample_app_ug/index testpmd_app_ug/index diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 8d86dd4..cdc7ea0 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -53,7 +53,6 @@ Programmer's Guide ivshmem_lib poll_mode_drv_emulated_virtio_nic poll_mode_drv_paravirtual_vmxnets_nic -intel_dpdk_xen_based_packet_switch_sol libpcap_ring_based_poll_mode_drv link_bonding_poll_mode_drv_lib timer_lib diff --git a/doc/guides/prog_guide/img/dpdk_xen_pkt_switch.png b/doc/guides/xen/img/dpdk_xen_pkt_switch.png similarity index 100% rename from doc/guides/prog_guide/img/dpdk_xen_pkt_switch.png rename to doc/guides/xen/img/dpdk_xen_pkt_switch.png diff --git a/doc/guides/prog_guide/img/grant_refs.png b/doc/guides/xen/img/grant_refs.png similarity index 100% rename from doc/guides/prog_guide/img/grant_refs.png rename to doc/guides/xen/img/grant_refs.png diff --git a/doc/guides/prog_guide/img/grant_table.png b/doc/guides/xen/img/grant_table.png similarity index 100% rename from doc/guides/prog_guide/img/grant_table.png rename to doc/guides/xen/img/grant_table.png diff --git a/doc/guides/prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst b/doc/guides/xen/index.rst similarity index 99% rename from doc/guides/prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst rename to doc/guides/xen/index.rst index 1f1e04f..70b7429 100644 --- a/doc/guides/prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst +++ b/doc/guides/xen/index.rst @@ -31,6 +31,8 @@ DPDK Xen Based Packet-Switching Solution +|today| + Introduction -- 2.2.2
[dpdk-dev] [RFC PATCH 3/4] doc: nics guide
Create nics guide by moving chapters about Intel NICS. Signed-off-by: Thomas Monjalon --- MAINTAINERS| 13 +- doc/guides/index.rst | 1 + .../driver_vm_emul_dev.rst => nics/e1000em.rst}| 0 doc/guides/{prog_guide => nics}/img/console.png| Bin .../{prog_guide => nics}/img/fast_pkt_proc.png | Bin .../{prog_guide => nics}/img/forward_stats.png | Bin .../{prog_guide => nics}/img/host_vm_comms.png | Bin .../img/host_vm_comms_qemu.png | Bin .../{prog_guide => nics}/img/inter_vm_comms.png| Bin .../{prog_guide => nics}/img/perf_benchmark.png| Bin .../{prog_guide => nics}/img/single_port_nic.png | Bin .../{prog_guide => nics}/img/vm_vm_comms.png | Bin .../{prog_guide => nics}/img/vmxnet3_int.png | Bin doc/guides/{prog_guide => nics}/img/vswitch_vm.png | Bin doc/guides/{ => nics}/index.rst| 28 ++-- .../intel_vf.rst} | 0 doc/guides/nics/ixgbe.rst | 184 + .../pcap_ring.rst} | 0 .../virtio.rst}| 0 .../vmxnet3.rst} | 0 doc/guides/prog_guide/index.rst| 17 -- doc/guides/prog_guide/poll_mode_drv.rst| 152 - 22 files changed, 209 insertions(+), 186 deletions(-) rename doc/guides/{prog_guide/driver_vm_emul_dev.rst => nics/e1000em.rst} (100%) rename doc/guides/{prog_guide => nics}/img/console.png (100%) rename doc/guides/{prog_guide => nics}/img/fast_pkt_proc.png (100%) rename doc/guides/{prog_guide => nics}/img/forward_stats.png (100%) rename doc/guides/{prog_guide => nics}/img/host_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/host_vm_comms_qemu.png (100%) rename doc/guides/{prog_guide => nics}/img/inter_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/perf_benchmark.png (100%) rename doc/guides/{prog_guide => nics}/img/single_port_nic.png (100%) rename doc/guides/{prog_guide => nics}/img/vm_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/vmxnet3_int.png (100%) rename doc/guides/{prog_guide => nics}/img/vswitch_vm.png (100%) copy doc/guides/{ => nics}/index.rst (88%) rename doc/guides/{prog_guide/i40e_ixgbe_igb_virt_func_drv.rst => nics/intel_vf.rst} (100%) create mode 100644 doc/guides/nics/ixgbe.rst rename doc/guides/{prog_guide/libpcap_ring_based_poll_mode_drv.rst => nics/pcap_ring.rst} (100%) rename doc/guides/{prog_guide/poll_mode_drv_emulated_virtio_nic.rst => nics/virtio.rst} (100%) rename doc/guides/{prog_guide/poll_mode_drv_paravirtual_vmxnets_nic.rst => nics/vmxnet3.rst} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 1d9ddbc..343e18f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -190,16 +190,21 @@ F: lib/librte_pmd_enic/ Intel e1000 F: lib/librte_pmd_e1000/ +F: doc/guides/nics/e1000em.rst +F: doc/guides/nics/intel_vf.rst Intel ixgbe F: lib/librte_pmd_ixgbe/ +F: doc/guides/nics/ixgbe.rst +F: doc/guides/nics/intel_vf.rst Intel i40e F: lib/librte_pmd_i40e/ +F: doc/guides/nics/intel_vf.rst RedHat virtio F: lib/librte_pmd_virtio/ -F: doc/guides/prog_guide/poll_mode_drv_emulated_virtio_nic.rst +F: doc/guides/nics/virtio.rst F: lib/librte_vhost/ F: doc/guides/prog_guide/vhost_lib.rst F: examples/vhost/ @@ -207,15 +212,15 @@ F: doc/guides/sample_app_ug/vhost.rst VMware vmxnet3 F: lib/librte_pmd_vmxnet3/ -F: doc/guides/prog_guide/poll_mode_drv_paravirtual_vmxnets_nic.rst +F: doc/guides/nics/vmxnet3.rst PCAP PMD F: lib/librte_pmd_pcap/ -F: doc/guides/prog_guide/libpcap_ring_based_poll_mode_drv.rst +F: doc/guides/nics/pcap_ring.rst Ring PMD F: lib/librte_pmd_ring/ -F: doc/guides/prog_guide/ring_lib.rst +F: doc/guides/nics/pcap_ring.rst F: app/test/test_pmd_ring.c diff --git a/doc/guides/index.rst b/doc/guides/index.rst index 53f1be1..44e8432 100644 --- a/doc/guides/index.rst +++ b/doc/guides/index.rst @@ -41,6 +41,7 @@ Contents: freebsd_gsg/index xen/index prog_guide/index + nics/index sample_app_ug/index testpmd_app_ug/index rel_notes/index diff --git a/doc/guides/prog_guide/driver_vm_emul_dev.rst b/doc/guides/nics/e1000em.rst similarity index 100% rename from doc/guides/prog_guide/driver_vm_emul_dev.rst rename to doc/guides/nics/e1000em.rst diff --git a/doc/guides/prog_guide/img/console.png b/doc/guides/nics/img/console.png similarity index 100% rename from doc/guides/prog_guide/img/console.png rename to doc/guides/nics/img/console.png diff --git a/doc/guides/prog_guide/img/fast_pkt_proc.png b/doc/guides/nics/img/fast_pkt_proc.png similarity index 100% rename from doc/guides/prog_guide/img/fast_pkt_proc.png rename to doc/guides/nics/img/fast_pkt_proc.png diff --git a/doc/guides/prog_guide/img/forward_stats.png b/doc/guides/nics/img/forward_stats.png similarity index 100% rename from do
[dpdk-dev] [RFC PATCH 4/4] doc: remove copyright footer
In order to be more vendor neutral, copyright should not be printed in the footer of every documentation pages. It should help to have documentation from other vendors. Copyright is still written in the source files. Sphinx notice is also removed to make the footer empty in the current theme. Signed-off-by: Thomas Monjalon --- doc/guides/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/guides/conf.py b/doc/guides/conf.py index 385af03..9d9f5c8 100644 --- a/doc/guides/conf.py +++ b/doc/guides/conf.py @@ -32,7 +32,8 @@ import subprocess project = 'DPDK' -copyright = '2014, Intel' +html_show_copyright = False +html_show_sphinx = False version = subprocess.check_output(["make","-sRrC","../../", "showversion"]) -- 2.2.2
[dpdk-dev] [PATCH v6 00/13] Port Hotplug Framework
This patch series adds a dynamic port hotplug framework to DPDK. With the patches, DPDK apps can attach or detach ports at runtime. The basic concept of the port hotplug is like followings. - DPDK apps must have responsibility to manage ports. DPDK apps only know which ports are attached or detached at the moment. The port hotplug framework is implemented to allow DPDK apps to manage ports. For example, when DPDK apps call port attach function, attached port number will be returned. Also DPDK apps can detach port by port number. - Kernel support is needed for attaching or detaching physical device ports. To attach a new physical device port, the device will be recognized by userspace directly I/O framework in kernel at first. Then DPDK apps can call the port hotplug functions to attach ports. For detaching, steps are vice versa. - Before detach ports, ports must be stopped and closed. DPDK application must call rte_eth_dev_stop() and rte_eth_dev_close() before detaching ports. These function will call finalization codes of PMDs. But so far, no PMD frees all resources allocated by initialization. It means PMDs are needed to be fixed to support the port hotplug. 'RTE_PCI_DRV_DETACHABLE' is a new flag indicating a PMD supports detaching. Without this flag, detaching will be failed. - Mustn't affect legacy DPDK apps. No DPDK EAL behavior is changed, if the port hotplug functions are't called. So all legacy DPDK apps can still work without modifications. And a few limitations. - The port hotplug functions are not thread safe. DPDK apps should handle it. - Only support Linux and igb_uio so far. BSD and VFIO is not supported. I will send VFIO patches at least, but I don't have a plan to submit BSD patch so far. Here is port hotplug APIs. --- /** * Attach a new device. * * @param devargs * A pointer to a strings array describing the new device * to be attached. The strings should be a pci address like * ':01:00.0' or virtual device name like 'eth_pcap0'. * @param port_id * A pointer to a port identifier actually attached. * @return * 0 on success and port_id is filled, negative on error */ int rte_eal_dev_attach(const char *devargs, uint8_t *port_id); /** * Detach a device. * * @param port_id * The port identifier of the device to detach. * @param addr * A pointer to a device name actually detached. * @return * 0 on success and devname is filled, negative on error */ int rte_eal_dev_detach(uint8_t port_id, char *devname); --- This patch series are for DPDK EAL. To use port hotplug function by DPDK apps, each PMD should be fixed to support 'RTE_PCI_DRV_DETACHABLE' flag. Please check a patch for pcap PMD. Also please check testpmd patch. It will show you how to fix your legacy applications to support port hotplug feature. PATCH v6 changes - Fix rte_eth_dev_uninit() to handle a return value of uninit function of PMD. To do this, below changes also be applied. - Fix a paramter of rte_eth_dev_free(). - Use rte_eth_dev structure as the paramter of rte_eth_dev_free(). PATCH v5 changes - Add runtime check passthrough driver type, like vfio-pci, igb_uio and uio_pci_generic. This was done by Qiu, Michael. Thanks a lot. - Change function names like below. - rte_eal_dev_find_and_invoke() to rte_eal_vdev_find_and_invoke(). - rte_eal_dev_invoke() to rte_eal_vdev_invoke(). - Add code to handle a return value of rte_eal_devargs_remove(). - Fix pci address format in rte_eal_dev_detach(). - Remove RTE_EAL_INVOKE_TYPE_UNKNOWN, because it's unused. - Change function definition of rte_eal_devargs_remove(). - Fix pci_unmap_device() to check pt_driver. - Fix return value of below functions. - rte_eth_dev_get_changed_port(). - rte_eth_dev_get_port_by_addr(). - Change paramters of rte_eth_dev_validate_port() to cleanup code. - Fix pci_scan_one to handle pt_driver correctly. (Thanks to Qiu, Michael for above sugesstions) PATCH v4 changes - Merge patches to review easier. - Fix indent of 'if' statement. - Fix calculation method of eal_compare_pci_addr(). - Fix header file declaration. - Add header file to determine if hotplug can be enabled. (Thanks to Qiu, Michael) - Use braces with 'for' loop. - Add paramerter checking. - Fix sanity check code - Fix comments of rte_eth_dev_type. - Change function names. (Thanks to Iremonger, Bernard) PATCH v3 changes: - Fix enum definition used in rte_ethdev.c. (Thanks to Zhang, Helin) PATCH v2 changes: - Replace rte_eal_dev_attach_pdev(), rte_eal_dev_detach_pdev, rte_eal_dev_attach_vdev() and rte_eal_dev_detach_vdev() to rte_eal_dev_attach() and rte_eal_dev_detach(). - Add parameter values checking. - Refashion a few functions. (Thanks to Iremonger, Bernard) PATCH v1 Changes: - Fix error checking
[dpdk-dev] [PATCH v6 01/13] eal_pci: Add flag to hold kernel driver type
From: Michael Qiu Currently, dpdk has no ability to know which type of driver( vfio-pci/igb_uio/uio_pci_generic) the device used. It only can check whether vfio is enabled or not staticly. It really useful to have the flag, becasue different type need to handle differently in runtime. For example, pci memory map, pot hotplug, and so on. This patch add a flag field for pci device to solve above issue. Signed-off-by: Michael Qiu Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 8 + lib/librte_eal/linuxapp/eal/eal_pci.c | 53 +++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 66ed793..7b48b55 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -139,6 +139,13 @@ struct rte_pci_addr { struct rte_devargs; +enum rte_pt_driver { + RTE_PT_UNKNOWN = 0, + RTE_PT_IGB_UIO = 1, + RTE_PT_VFIO = 2, + RTE_PT_UIO_GENERIC = 3, +}; + /** * A structure describing a PCI device. */ @@ -152,6 +159,7 @@ struct rte_pci_device { uint16_t max_vfs; /**< sriov enable if not zero */ int numa_node; /**< NUMA node connection */ struct rte_devargs *devargs;/**< Device user arguments */ + enum rte_pt_driver pt_driver; /**< Driver of passthrough */ }; /** Any PCI device identifier (vendor, device, ...) */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index b5f5410..bd3f77d 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -97,6 +97,35 @@ error: return -1; } +static int +pci_get_kernel_driver_by_path(const char *filename, char *dri_name) +{ + int count; + char path[PATH_MAX]; + char *name; + + if (!filename || !dri_name) + return -1; + + count = readlink(filename, path, PATH_MAX); + if (count >= PATH_MAX) + return -1; + + /* For device does not have a driver */ + if (count < 0) + return 1; + + path[count] = '\0'; + + name = strrchr(path, '/'); + if (name) { + strncpy(dri_name, name + 1, strlen(name + 1) + 1); + return 0; + } + + return -1; +} + void * pci_find_max_end_va(void) { @@ -222,11 +251,12 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, char filename[PATH_MAX]; unsigned long tmp; struct rte_pci_device *dev; + char driver[PATH_MAX]; + int ret; dev = malloc(sizeof(*dev)); - if (dev == NULL) { + if (dev == NULL) return -1; - } memset(dev, 0, sizeof(*dev)); dev->addr.domain = domain; @@ -298,6 +328,25 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, return -1; } + /* parse driver */ + snprintf(filename, sizeof(filename), "%s/driver", dirname); + ret = pci_get_kernel_driver_by_path(filename, driver); + if (!ret) { + if (!strcmp(driver, "vfio-pci")) + dev->pt_driver = RTE_PT_VFIO; + else if (!strcmp(driver, "igb_uio")) + dev->pt_driver = RTE_PT_IGB_UIO; + else if (!strcmp(driver, "uio_pci_generic")) + dev->pt_driver = RTE_PT_UIO_GENERIC; + else + dev->pt_driver = RTE_PT_UNKNOWN; + } else if (ret < 0) { + RTE_LOG(ERR, EAL, "Fail to get kernel driver\n"); + free(dev); + return -1; + } else + dev->pt_driver = RTE_PT_UNKNOWN; + /* device is valid, add in list (sorted) */ if (TAILQ_EMPTY(&pci_device_list)) { TAILQ_INSERT_TAIL(&pci_device_list, dev, next); -- 1.9.1
[dpdk-dev] [PATCH v6 02/13] eal_pci: pci memory map work with driver type
From: Michael Qiu With the driver type flag in struct rte_pci_dev, we do not need to always map uio devices with vfio related function when vfio enabled. Signed-off-by: Michael Qiu Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/linuxapp/eal/eal_pci.c | 30 +- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index bd3f77d..c0ca5a5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -549,25 +549,29 @@ pci_config_space_set(struct rte_pci_device *dev) static int pci_map_device(struct rte_pci_device *dev) { - int ret, mapped = 0; + int ret = -1; /* try mapping the NIC resources using VFIO if it exists */ + switch (dev->pt_driver) { + case RTE_PT_VFIO: #ifdef VFIO_PRESENT - if (pci_vfio_is_enabled()) { - ret = pci_vfio_map_resource(dev); - if (ret == 0) - mapped = 1; - else if (ret < 0) - return ret; - } + if (pci_vfio_is_enabled()) + ret = pci_vfio_map_resource(dev); #endif - /* map resources for devices that use igb_uio */ - if (!mapped) { + break; + case RTE_PT_IGB_UIO: + case RTE_PT_UIO_GENERIC: + /* map resources for devices that use uio */ ret = pci_uio_map_resource(dev); - if (ret != 0) - return ret; + break; + default: + RTE_LOG(DEBUG, EAL, " Not managed by known pt driver," + " skipped\n"); + ret = 1; + break; } - return 0; + + return ret; } /* -- 1.9.1
[dpdk-dev] [PATCH v6 03/13] eal/pci, ethdev: Remove assumption that port will not be detached
To remove assumption, do like followings. This patch adds "RTE_PCI_DRV_DETACHABLE" to drv_flags of rte_pci_driver structure. The flags indicates the driver can detach devices at runtime. Also remove assumption that port will not be detached. To remove the assumption. - Add 'attached' member to rte_eth_dev structure. This member is used for indicating the port is attached, or not. - Add rte_eth_dev_allocate_new_port(). This function is used for allocating new port. v5: - Change paramters of rte_eth_dev_validate_port() to cleanup code. v4: - Use braces with 'for' loop. - Fix indent of 'if' statement. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 2 + lib/librte_ether/rte_ethdev.c | 454 +--- lib/librte_ether/rte_ethdev.h | 5 + 3 files changed, 186 insertions(+), 275 deletions(-) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 7b48b55..7f2d699 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -207,6 +207,8 @@ struct rte_pci_driver { #define RTE_PCI_DRV_FORCE_UNBIND 0x0004 /** Device driver supports link state interrupt */ #define RTE_PCI_DRV_INTR_LSC 0x0008 +/** Device driver supports detaching capability */ +#define RTE_PCI_DRV_DETACHABLE 0x0010 /**< Internal use only - Macro used by pci addr parsing functions **/ #define GET_PCIADDR_FIELD(in, fd, lim, dlm) \ diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index ea3a1fb..d70854f 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -175,6 +175,16 @@ enum { STAT_QMAP_RX }; +enum { + DEV_INVALID = 0, + DEV_VALID, +}; + +enum { + DEV_DISCONNECTED = 0, + DEV_CONNECTED +}; + static inline void rte_eth_dev_data_alloc(void) { @@ -201,19 +211,34 @@ rte_eth_dev_allocated(const char *name) { unsigned i; - for (i = 0; i < nb_ports; i++) { - if (strcmp(rte_eth_devices[i].data->name, name) == 0) + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if ((rte_eth_devices[i].attached == DEV_CONNECTED) && + strcmp(rte_eth_devices[i].data->name, name) == 0) return &rte_eth_devices[i]; } return NULL; } +static uint8_t +rte_eth_dev_allocate_new_port(void) +{ + unsigned i; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if (rte_eth_devices[i].attached == DEV_DISCONNECTED) + return i; + } + return RTE_MAX_ETHPORTS; +} + struct rte_eth_dev * rte_eth_dev_allocate(const char *name) { + uint8_t port_id; struct rte_eth_dev *eth_dev; - if (nb_ports == RTE_MAX_ETHPORTS) { + port_id = rte_eth_dev_allocate_new_port(); + if (port_id == RTE_MAX_ETHPORTS) { PMD_DEBUG_TRACE("Reached maximum number of Ethernet ports\n"); return NULL; } @@ -226,10 +251,12 @@ rte_eth_dev_allocate(const char *name) return NULL; } - eth_dev = &rte_eth_devices[nb_ports]; - eth_dev->data = &rte_eth_dev_data[nb_ports]; + eth_dev = &rte_eth_devices[port_id]; + eth_dev->data = &rte_eth_dev_data[port_id]; snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); - eth_dev->data->port_id = nb_ports++; + eth_dev->data->port_id = port_id; + eth_dev->attached = DEV_CONNECTED; + nb_ports++; return eth_dev; } @@ -283,6 +310,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, (unsigned) pci_dev->id.device_id); if (rte_eal_process_type() == RTE_PROC_PRIMARY) rte_free(eth_dev->data->dev_private); + eth_dev->attached = DEV_DISCONNECTED; nb_ports--; return diag; } @@ -308,10 +336,28 @@ rte_eth_driver_register(struct eth_driver *eth_drv) rte_eal_pci_register(ð_drv->pci_drv); } +enum { + NONE_TRACE = 0, + TRACE +}; + +static int +rte_eth_dev_validate_port(uint8_t port_id, int trace) +{ + if (port_id >= RTE_MAX_ETHPORTS || + rte_eth_devices[port_id].attached != DEV_CONNECTED) { + if (trace) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + } + return DEV_INVALID; + } else + return DEV_VALID; +} + int rte_eth_dev_socket_id(uint8_t port_id) { - if (port_id >= nb_ports) + if (rte_eth_dev_validate_port(port_id, NONE_TRACE) == DEV_INVALID) return -1; return rte_eth_devices[port_id].pci_dev->numa_node; } @@ -369,10 +415,8 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id) * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); - if (port_id >= nb_ports) { - PMD_DEBUG_TRACE("Invalid por
[dpdk-dev] [PATCH v6 04/13] eal/pci: Consolidate pci address comparison APIs
This patch replaces pci_addr_comparison() and memcmp() of pci addresses by eal_compare_pci_addr(). v5: - Fix pci_scan_one to handle pt_driver correctly. v4: - Fix calculation method of eal_compare_pci_addr(). - Add parameter checking. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/bsdapp/eal/eal_pci.c | 25 --- lib/librte_eal/common/eal_common_pci.c| 2 +- lib/librte_eal/common/include/rte_pci.h | 34 +++ lib/librte_eal/linuxapp/eal/eal_pci.c | 25 --- lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c index 74ecce7..c844d58 100644 --- a/lib/librte_eal/bsdapp/eal/eal_pci.c +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c @@ -270,20 +270,6 @@ pci_uio_map_resource(struct rte_pci_device *dev) return (0); } -/* Compare two PCI device addresses. */ -static int -pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) -{ - uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function; - uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function; - - if (dev_addr > dev_addr2) - return 1; - else - return 0; -} - - /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(int dev_pci_fd, struct pci_conf *conf) @@ -356,13 +342,20 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf) } else { struct rte_pci_device *dev2 = NULL; + int ret; TAILQ_FOREACH(dev2, &pci_device_list, next) { - if (pci_addr_comparison(&dev->addr, &dev2->addr)) + ret = eal_compare_pci_addr(&dev->addr, &dev2->addr); + if (ret > 0) continue; - else { + else if (ret < 0) { TAILQ_INSERT_BEFORE(dev2, dev, next); return 0; + } else { /* already registered */ + /* update pt_driver */ + dev2->pt_driver = dev->pt_driver; + free(dev); + return 0; } } TAILQ_INSERT_TAIL(&pci_device_list, dev, next); diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index f3c7f71..a89f5c3 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -93,7 +93,7 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI && devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) continue; - if (!memcmp(&dev->addr, &devargs->pci.addr, sizeof(dev->addr))) + if (!eal_compare_pci_addr(&dev->addr, &devargs->pci.addr)) return devargs; } return NULL; diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 7f2d699..4814cd7 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -269,6 +269,40 @@ eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr) } #undef GET_PCIADDR_FIELD +/* Compare two PCI device addresses. */ +/** + * Utility function to compare two PCI device addresses. + * + * @param addr + * The PCI Bus-Device-Function address to compare + * @param addr2 + * The PCI Bus-Device-Function address to compare + * @return + * 0 on equal PCI address. + * Positive on addr is greater than addr2. + * Negative on addr is less than addr2, or error. + */ +static inline int +eal_compare_pci_addr(struct rte_pci_addr *addr, struct rte_pci_addr *addr2) +{ + uint64_t dev_addr, dev_addr2; + + if ((addr == NULL) || (addr2 == NULL)) + return -1; + + dev_addr = (addr->domain << 24) | (addr->bus << 16) | + (addr->devid << 8) | addr->function; + dev_addr2 = (addr2->domain << 24) | (addr2->bus << 16) | + (addr2->devid << 8) | addr2->function; + + if (dev_addr > dev_addr2) + return 1; + else if (dev_addr < dev_addr2) + return -1; + else + return 0; +} + /** * Probe the PCI bus for registered drivers. * diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index c0ca5a5..d847102 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -229,20 +229,6 @@ error: return -1; } -/* Compa
[dpdk-dev] [PATCH v6 05/13] ethdev: Add rte_eth_dev_free to free specified device
This patch adds rte_eth_dev_free(). The function is used for changing a attached status of the device that has specified name. v6: - Use rte_eth_dev structure as the paramter of rte_eth_dev_free(). v4: - Add paramerter checking. Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 11 +++ lib/librte_ether/rte_ethdev.h | 14 ++ 2 files changed, 25 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index d70854f..b58bab3 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -260,6 +260,17 @@ rte_eth_dev_allocate(const char *name) return eth_dev; } +int +rte_eth_dev_free(struct rte_eth_dev *eth_dev) +{ + if (eth_dev == NULL) + return -EINVAL; + + eth_dev->attached = 0; + nb_ports--; + return 0; +} + static int rte_eth_dev_init(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index ca101f5..fbe7ac1 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1627,6 +1627,20 @@ extern uint8_t rte_eth_dev_count(void); */ struct rte_eth_dev *rte_eth_dev_allocate(const char *name); +/** + * Function for internal use by dummy drivers primarily, e.g. ring-based + * driver. + * Free the specified ethdev. + * + * @param eth_dev + * The *eth_dev* pointer is the address of the *rte_eth_dev* structure + * associated with the matching device and which have been [automatically] + * allocated in the *rte_eth_devices* array. + * @return + * - 0 on success, negative on error + */ +int rte_eth_dev_free(struct rte_eth_dev *eth_dev); + struct eth_driver; /** * @internal -- 1.9.1
[dpdk-dev] [PATCH v6 06/13] eal, ethdev: Add a function and function pointers to close ether device
The patch adds function pointer to rte_pci_driver and eth_driver structure. These function pointers are used when ports are detached. Also the patch adds rte_eth_dev_uninit(). So far, it's not called by anywhere, but it will be called when port hotplug function is implemented. v6: - Fix rte_eth_dev_uninit() to handle a return value of uninit function of PMD. v4: - Add paramerter checking. - Change function names. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/include/rte_pci.h | 7 + lib/librte_ether/rte_ethdev.c | 47 + lib/librte_ether/rte_ethdev.h | 24 + 3 files changed, 78 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 4814cd7..87ca4cf 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -189,12 +189,19 @@ struct rte_pci_driver; typedef int (pci_devinit_t)(struct rte_pci_driver *, struct rte_pci_device *); /** + * Uninitialisation function for the driver called during hotplugging. + */ +typedef int (pci_devuninit_t)( + struct rte_pci_driver *, struct rte_pci_device *); + +/** * A structure describing a PCI driver. */ struct rte_pci_driver { TAILQ_ENTRY(rte_pci_driver) next; /**< Next in list. */ const char *name; /**< Driver name. */ pci_devinit_t *devinit; /**< Device init. function. */ + pci_devuninit_t *devuninit; /**< Device uninit function. */ struct rte_pci_id *id_table;/**< ID table, NULL terminated. */ uint32_t drv_flags; /**< Flags contolling handling of device. */ }; diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index b58bab3..7bed901 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -326,6 +326,52 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, return diag; } +static int +rte_eth_dev_uninit(struct rte_pci_driver *pci_drv, +struct rte_pci_device *pci_dev) +{ + struct eth_driver *eth_drv; + struct rte_eth_dev *eth_dev; + char ethdev_name[RTE_ETH_NAME_MAX_LEN]; + int ret; + + if ((pci_drv == NULL) || (pci_dev == NULL)) + return -EINVAL; + + /* Create unique Ethernet device name using PCI address */ + snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%d:%d.%d", + pci_dev->addr.bus, pci_dev->addr.devid, + pci_dev->addr.function); + + eth_dev = rte_eth_dev_allocated(ethdev_name); + if (eth_dev == NULL) + return -ENODEV; + + eth_drv = (struct eth_driver *)pci_drv; + + /* Invoke PMD device uninit function */ + if (*eth_drv->eth_dev_uninit) { + ret = (*eth_drv->eth_dev_uninit)(eth_drv, eth_dev); + if (ret) + return ret; + } + + /* free ether device */ + rte_eth_dev_free(eth_dev); + + /* init user callbacks */ + TAILQ_INIT(&(eth_dev->callbacks)); + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(eth_dev->data->dev_private); + + eth_dev->pci_dev = NULL; + eth_dev->driver = NULL; + eth_dev->data = NULL; + + return 0; +} + /** * Register an Ethernet [Poll Mode] driver. * @@ -344,6 +390,7 @@ void rte_eth_driver_register(struct eth_driver *eth_drv) { eth_drv->pci_drv.devinit = rte_eth_dev_init; + eth_drv->pci_drv.devuninit = rte_eth_dev_uninit; rte_eal_pci_register(ð_drv->pci_drv); } diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index fbe7ac1..91d9e86 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1678,6 +1678,27 @@ typedef int (*eth_dev_init_t)(struct eth_driver *eth_drv, /** * @internal + * Finalization function of an Ethernet driver invoked for each matching + * Ethernet PCI device detected during the PCI closing phase. + * + * @param eth_drv + * The pointer to the [matching] Ethernet driver structure supplied by + * the PMD when it registered itself. + * @param eth_dev + * The *eth_dev* pointer is the address of the *rte_eth_dev* structure + * associated with the matching device and which have been [automatically] + * allocated in the *rte_eth_devices* array. + * @return + * - 0: Success, the device is properly finalized by the driver. + *In particular, the driver MUST free the *dev_ops* pointer + *of the *eth_dev* structure. + * - <0: Error code of the device initialization failure. + */ +typedef int (*eth_dev_uninit_t)(struct eth_driver *eth_drv, + struct rte_eth_dev *eth_dev); + +/** + * @internal * The structure associated with a PMD Ethernet driver. * * Each Ethernet driver acts as a PCI driver and is represen
[dpdk-dev] [PATCH v6 07/13] ethdev: Add functions that will be used by port hotplug functions
The patch adds following functions. - rte_eth_dev_save() The function is used for saving current rte_eth_dev structures. - rte_eth_dev_get_changed_port() The function receives the rte_eth_dev structures, then compare these with current values to know which port is actually attached or detached. - rte_eth_dev_get_addr_by_port() The function returns a pci address of a ethdev specified by port identifier. - rte_eth_dev_get_port_by_addr() The function returns a port identifier of a ethdev specified by pci address. - rte_eth_dev_get_name_by_port() The function returns a unique identifier name of a ethdev specified by port identifier. - Add rte_eth_dev_check_detachable() The function returns whether a PMD supports detach function. Also the patch changes scope of rte_eth_dev_allocated() to global. This function will be called by virtual PMDs to support port hotplug. So change scope of the function to global. v5: - Fix return value of below functions. rte_eth_dev_get_changed_port(). rte_eth_dev_get_port_by_addr(). v4: - Add paramerter checking. v3: - Fix if-condition bug while comparing pci addresses. - Add error checking codes. Reported-by: Mark Enright Signed-off-by: Tetsuya Mukawa --- lib/librte_ether/rte_ethdev.c | 98 ++- lib/librte_ether/rte_ethdev.h | 80 +++ 2 files changed, 177 insertions(+), 1 deletion(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 7bed901..5aded10 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -206,7 +206,7 @@ rte_eth_dev_data_alloc(void) RTE_MAX_ETHPORTS * sizeof(*rte_eth_dev_data)); } -static struct rte_eth_dev * +struct rte_eth_dev * rte_eth_dev_allocated(const char *name) { unsigned i; @@ -426,6 +426,102 @@ rte_eth_dev_count(void) return (nb_ports); } +void +rte_eth_dev_save(struct rte_eth_dev *devs) +{ + if (devs == NULL) + return; + + /* save current rte_eth_devices */ + memcpy(devs, rte_eth_devices, + sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS); +} + +int +rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) +{ + if ((devs == NULL) || (port_id == NULL)) + return -EINVAL; + + /* check which port was attached or detached */ + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) { + if (rte_eth_devices[*port_id].attached ^ devs->attached) + return 0; + } + return -ENODEV; +} + +int +rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) +{ + if (rte_eth_dev_validate_port(port_id, TRACE) == DEV_INVALID) + return -EINVAL; + + if (addr == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + *addr = rte_eth_devices[port_id].pci_dev->addr; + return 0; +} + +int +rte_eth_dev_get_port_by_addr(struct rte_pci_addr *addr, uint8_t *port_id) +{ + struct rte_pci_addr *tmp; + + if ((addr == NULL) || (port_id == NULL)) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++) { + if (!rte_eth_devices[*port_id].attached) + continue; + if (!rte_eth_devices[*port_id].pci_dev) + continue; + tmp = &rte_eth_devices[*port_id].pci_dev->addr; + if (eal_compare_pci_addr(tmp, addr) == 0) + return 0; + } + return -ENODEV; +} + +int +rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) +{ + char *tmp; + + if (rte_eth_dev_validate_port(port_id, TRACE) == DEV_INVALID) + return -EINVAL; + + if (name == NULL) { + PMD_DEBUG_TRACE("Null pointer is specified\n"); + return -EINVAL; + } + + /* shouldn't check 'rte_eth_devices[i].data', +* because it might be overwritten by VDEV PMD */ + tmp = rte_eth_dev_data[port_id].name; + strncpy(name, tmp, strlen(tmp) + 1); + return 0; +} + +int +rte_eth_dev_check_detachable(uint8_t port_id) +{ + uint32_t drv_flags; + + if (port_id >= RTE_MAX_ETHPORTS) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags; + return !(drv_flags & RTE_PCI_DRV_DETACHABLE); +} + static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 91d9e86..9919968 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1616,6 +1616,86 @@ extern struct
[dpdk-dev] [PATCH v6 08/13] eal/linux/pci: Add functions for unmapping igb_uio resources
The patch adds functions for unmapping igb_uio resources. The patch is only for Linux and igb_uio environment. VFIO and BSD are not supported. v5: - Fix pci_unmap_device() to check pt_driver. v4: - Add paramerter checking. - Add header file to determine if hotplug can be enabled. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/Makefile | 1 + lib/librte_eal/common/include/rte_dev_hotplug.h | 44 + lib/librte_eal/linuxapp/eal/eal_pci.c | 44 + lib/librte_eal/linuxapp/eal/eal_pci_init.h | 8 +++ lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 65 + 5 files changed, 162 insertions(+) create mode 100644 lib/librte_eal/common/include/rte_dev_hotplug.h diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile index 52c1a5f..db7cc93 100644 --- a/lib/librte_eal/common/Makefile +++ b/lib/librte_eal/common/Makefile @@ -41,6 +41,7 @@ INC += rte_eal_memconfig.h rte_malloc_heap.h INC += rte_hexdump.h rte_devargs.h rte_dev.h INC += rte_common_vect.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h +INC += rte_dev_hotplug.h ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y) INC += rte_warnings.h diff --git a/lib/librte_eal/common/include/rte_dev_hotplug.h b/lib/librte_eal/common/include/rte_dev_hotplug.h new file mode 100644 index 000..b333e0f --- /dev/null +++ b/lib/librte_eal/common/include/rte_dev_hotplug.h @@ -0,0 +1,44 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2015 IGEL Co.,LTd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of IGEL Co.,Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_DEV_HOTPLUG_H_ +#define _RTE_DEV_HOTPLUG_H_ + +/* + * determine if hotplug can be enabled on the system + */ +#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP) +#define ENABLE_HOTPLUG +#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */ + +#endif /* _RTE_DEV_HOTPLUG_H_ */ diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index d847102..c3b7917 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -166,6 +166,25 @@ pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size) return mapaddr; } +#ifdef ENABLE_HOTPLUG +/* unmap a particular resource */ +void +pci_unmap_resource(void *requested_addr, size_t size) +{ + if (requested_addr == NULL) + return; + + /* Unmap the PCI memory resource of device */ + if (munmap(requested_addr, size)) { + RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n", + __func__, requested_addr, (unsigned long)size, + strerror(errno)); + } else + RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", + requested_addr); +} +#endif /* ENABLE_HOTPLUG */ + /* parse the "resource" sysfs file */ #define IORESOURCE_MEM 0x0200 @@ -567,6 +586,31 @@ pci_map_device(struct rte_pci_device *dev) return ret; } +#ifdef ENABLE_HOTPLUG +static void +pci_unmap_device(struct rte_pci_device *dev) +{ + if (dev == NULL) + return; + + /* try unmapping the NIC resources using VFIO if it exists */ + switch (dev->pt_driver) { + case RTE_PT_VFIO: + RTE_LOG(ERR, EAL, "Hotplug doesn't support vfio yet\n"); + break; + case RTE_P
[dpdk-dev] [PATCH v6 09/13] eal/pci: Add a function to remove the entry of devargs list
The function removes the specified devargs entry from devargs_list. Also the patch adds sanity checking to rte_eal_devargs_add(). v5: - Change function definition of rte_eal_devargs_remove(). v4: - Fix sanity check code. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_devargs.c | 60 + lib/librte_eal/common/include/rte_devargs.h | 21 ++ 2 files changed, 81 insertions(+) diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c index 4c7d11a..5b1ac8e 100644 --- a/lib/librte_eal/common/eal_common_devargs.c +++ b/lib/librte_eal/common/eal_common_devargs.c @@ -44,6 +44,35 @@ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); + +/* find a entry specified by pci address or device name */ +static struct rte_devargs * +rte_eal_devargs_find(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return NULL; + + TAILQ_FOREACH(devargs, &devargs_list, next) { + switch (devtype) { + case RTE_DEVTYPE_WHITELISTED_PCI: + case RTE_DEVTYPE_BLACKLISTED_PCI: + if (eal_compare_pci_addr(&devargs->pci.addr, args) == 0) + goto found; + break; + case RTE_DEVTYPE_VIRTUAL: + if (memcmp(&devargs->virtual.drv_name, args, + strlen((char *)args)) == 0) + goto found; + break; + } + } + return NULL; +found: + return devargs; +} + /* store a whitelist parameter for later parsing */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) @@ -87,6 +116,12 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) free(devargs); return -1; } + /* make sure there is no same entry */ + if (rte_eal_devargs_find(devtype, &devargs->pci.addr)) { + RTE_LOG(ERR, EAL, + "device already registered: <%s>\n", buf); + return -1; + } break; case RTE_DEVTYPE_VIRTUAL: /* save driver name */ @@ -98,6 +133,12 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) free(devargs); return -1; } + /* make sure there is no same entry */ + if (rte_eal_devargs_find(devtype, &devargs->virtual.drv_name)) { + RTE_LOG(ERR, EAL, + "device already registered: <%s>\n", buf); + return -1; + } break; } @@ -105,6 +146,25 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) return 0; } +/* remove it from the devargs_list */ +int +rte_eal_devargs_remove(enum rte_devtype devtype, void *args) +{ + struct rte_devargs *devargs; + + if (args == NULL) + return -EINVAL; + + devargs = rte_eal_devargs_find(devtype, args); + if (devargs == NULL) { + RTE_LOG(ERR, EAL, "device not found\n"); + return -ENODEV; + } + + TAILQ_REMOVE(&devargs_list, devargs, next); + return 0; +} + /* count the number of devices of a specified type */ unsigned int rte_eal_devargs_type_count(enum rte_devtype devtype) diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h index 9f9c98f..b5ad4b3 100644 --- a/lib/librte_eal/common/include/rte_devargs.h +++ b/lib/librte_eal/common/include/rte_devargs.h @@ -123,6 +123,27 @@ extern struct rte_devargs_list devargs_list; int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str); /** + * Remove a device from the user device list + * + * For PCI devices, the format of arguments string is "PCI_ADDR". It shouldn't + * involves parameters for the device. Example: "08:00.1". + * + * For virtual devices, the format of arguments string is "DRIVER_NAME*". It + * shouldn't involves parameters for the device. Example: "eth_ring". The + * validity of the driver name is not checked by this function, it is done + * when closing the drivers. + * + * @param devtype + * The type of the device. + * @param name + * The name of the device. + * + * @return + * - 0 on success, negative on error + */ +int rte_eal_devargs_remove(enum rte_devtype devtype, void *args); + +/** * Count the number of user devices of a specified type * * @param devtype -- 1.9.1
[dpdk-dev] [PATCH v6 10/13] eal/pci: Cleanup pci driver initialization code
- Add rte_eal_pci_close_one_dirver() The function is used for closing the specified driver and device. - Add pci_invoke_all_drivers() The function is based on pci_probe_all_drivers. But it can not only probe but also close drivers. - Add pci_close_all_drivers() The function tries to find a driver for the specified device, and then close the driver. - Add rte_eal_pci_probe_one() and rte_eal_pci_close_one() The functions are used for probe and close a device. First the function tries to find a device that has the specfied PCI address. Then, probe or close the device. v5: - Remove RTE_EAL_INVOKE_TYPE_UNKNOWN, because it's unused. v4: - Fix paramerter checking. - Fix indent of 'if' statement. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_pci.c | 90 + lib/librte_eal/common/eal_private.h | 24 + lib/librte_eal/common/include/rte_pci.h | 33 lib/librte_eal/linuxapp/eal/eal_pci.c | 69 + 4 files changed, 206 insertions(+), 10 deletions(-) diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c index a89f5c3..7c9b8c5 100644 --- a/lib/librte_eal/common/eal_common_pci.c +++ b/lib/librte_eal/common/eal_common_pci.c @@ -99,19 +99,27 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) return NULL; } -/* - * If vendor/device ID match, call the devinit() function of all - * registered driver for the given device. Return -1 if initialization - * failed, return 1 if no driver is found for this device. - */ static int -pci_probe_all_drivers(struct rte_pci_device *dev) +pci_invoke_all_drivers(struct rte_pci_device *dev, + enum rte_eal_invoke_type type) { struct rte_pci_driver *dr = NULL; - int rc; + int rc = 0; + + if ((dev == NULL) || (type >= RTE_EAL_INVOKE_TYPE_MAX)) + return -1; TAILQ_FOREACH(dr, &pci_driver_list, next) { - rc = rte_eal_pci_probe_one_driver(dr, dev); + switch (type) { + case RTE_EAL_INVOKE_TYPE_PROBE: + rc = rte_eal_pci_probe_one_driver(dr, dev); + break; + case RTE_EAL_INVOKE_TYPE_CLOSE: + rc = rte_eal_pci_close_one_driver(dr, dev); + break; + default: + return -1; + } if (rc < 0) /* negative value is an error */ return -1; @@ -123,6 +131,66 @@ pci_probe_all_drivers(struct rte_pci_device *dev) return 1; } +#ifdef ENABLE_HOTPLUG +static int +rte_eal_pci_invoke_one(struct rte_pci_addr *addr, + enum rte_eal_invoke_type type) +{ + struct rte_pci_device *dev = NULL; + int ret = 0; + + if ((addr == NULL) || (type >= RTE_EAL_INVOKE_TYPE_MAX)) + return -1; + + TAILQ_FOREACH(dev, &pci_device_list, next) { + if (eal_compare_pci_addr(&dev->addr, addr)) + continue; + + ret = pci_invoke_all_drivers(dev, type); + if (ret < 0) + goto invoke_err_return; + + if (type == RTE_EAL_INVOKE_TYPE_CLOSE) + goto remove_dev; + + return 0; + } + + return -1; + +invoke_err_return: + RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT + " cannot be used\n", dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + return -1; + +remove_dev: + TAILQ_REMOVE(&pci_device_list, dev, next); + return 0; +} + + +/* + * Find the pci device specified by pci address, then invoke probe function of + * the driver of the devive. + */ +int +rte_eal_pci_probe_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, RTE_EAL_INVOKE_TYPE_PROBE); +} + +/* + * Find the pci device specified by pci address, then invoke close function of + * the driver of the devive. + */ +int +rte_eal_pci_close_one(struct rte_pci_addr *addr) +{ + return rte_eal_pci_invoke_one(addr, RTE_EAL_INVOKE_TYPE_CLOSE); +} +#endif /* ENABLE_HOTPLUG */ + /* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table @@ -148,10 +216,12 @@ rte_eal_pci_probe(void) /* probe all or only whitelisted devices */ if (probe_all) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, + RTE_EAL_INVOKE_TYPE_PROBE); else if (devargs != NULL && devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) - ret = pci_probe_all_drivers(dev); + ret = pci_invoke_all_drivers(dev, +
[dpdk-dev] [PATCH v6 11/13] ethdev: Add one dev_type paramerter to rte_eth_dev_allocate
This new parameter is needed to keep device type like physical or virtual. Port detaching processes are different between physical and virtual. This paramerter lets detaching function know a device type of the port. v4: - Fix comments of rte_eth_dev_type. Signed-off-by: Tetsuya Mukawa --- app/test/virtual_pmd.c | 2 +- lib/librte_ether/rte_ethdev.c| 14 -- lib/librte_ether/rte_ethdev.h| 25 - lib/librte_pmd_af_packet/rte_eth_af_packet.c | 2 +- lib/librte_pmd_bond/rte_eth_bond_api.c | 2 +- lib/librte_pmd_pcap/rte_eth_pcap.c | 2 +- lib/librte_pmd_ring/rte_eth_ring.c | 2 +- lib/librte_pmd_xenvirt/rte_eth_xenvirt.c | 2 +- 8 files changed, 42 insertions(+), 9 deletions(-) diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c index 9fac95d..8d3a5ff 100644 --- a/app/test/virtual_pmd.c +++ b/app/test/virtual_pmd.c @@ -556,7 +556,7 @@ virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, goto err; /* reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(name); + eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PHYSICAL); if (eth_dev == NULL) goto err; diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 5aded10..b54b9ab 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -232,7 +232,7 @@ rte_eth_dev_allocate_new_port(void) } struct rte_eth_dev * -rte_eth_dev_allocate(const char *name) +rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type) { uint8_t port_id; struct rte_eth_dev *eth_dev; @@ -256,6 +256,7 @@ rte_eth_dev_allocate(const char *name) snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); eth_dev->data->port_id = port_id; eth_dev->attached = DEV_CONNECTED; + eth_dev->dev_type = type; nb_ports++; return eth_dev; } @@ -267,6 +268,7 @@ rte_eth_dev_free(struct rte_eth_dev *eth_dev) return -EINVAL; eth_dev->attached = 0; + eth_dev->dev_type = RTE_ETH_DEV_UNKNOWN; nb_ports--; return 0; } @@ -287,7 +289,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv, snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%d:%d.%d", pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); - eth_dev = rte_eth_dev_allocate(ethdev_name); + eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PHYSICAL); if (eth_dev == NULL) return -ENOMEM; @@ -426,6 +428,14 @@ rte_eth_dev_count(void) return (nb_ports); } +enum rte_eth_dev_type +rte_eth_dev_get_device_type(uint8_t port_id) +{ + if (rte_eth_dev_validate_port(port_id, NONE_TRACE) == DEV_INVALID) + return -1; + return rte_eth_devices[port_id].dev_type; +} + void rte_eth_dev_save(struct rte_eth_dev *devs) { diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 9919968..00a6218 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1522,6 +1522,17 @@ struct eth_dev_ops { }; /** + * The eth device type + */ +enum rte_eth_dev_type { + RTE_ETH_DEV_UNKNOWN,/**< unknown device type */ + RTE_ETH_DEV_PHYSICAL, + /**< Physical function and Virtual function devices of NIC */ + RTE_ETH_DEV_VIRTUAL,/**< non hardware device */ + RTE_ETH_DEV_MAX /**< max value of this enum */ +}; + +/** * @internal * The generic data structure associated with each ethernet device. * @@ -1540,6 +1551,7 @@ struct rte_eth_dev { struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */ struct rte_eth_dev_cb_list callbacks; /**< User application callbacks */ uint8_t attached; /**< Flag indicating the port is attached */ + enum rte_eth_dev_type dev_type; /**< Flag indicating the device type */ }; struct rte_eth_dev_sriov { @@ -1617,6 +1629,15 @@ extern uint8_t rte_eth_dev_count(void); /** * Function for internal use by port hotplug functions. + * Get the device type to know whether the device is physical or virtual. + * @param port_id The pointer to the port id + * @return + * - Device type. + */ +extern enum rte_eth_dev_type rte_eth_dev_get_device_type(uint8_t port_id); + +/** + * Function for internal use by port hotplug functions. * Copies current ethdev structures to the specified pointer. * * @param devsThe pointer to the ethdev structures @@ -1702,10 +1723,12 @@ extern struct rte_eth_dev *rte_eth_dev_allocated(const char *name); * to that slot for the driver to use. * * @param nameUnique identifier name for each Ethernet device + * @param typeDevice type of this Ethernet device * @return * - Slot in the rte_dev_devices array for a new device; */ -struct rte_eth_dev
[dpdk-dev] [PATCH v6 12/13] eal/pci: Add rte_eal_dev_attach/detach() functions
These functions are used for attaching or detaching a port. When rte_eal_dev_attach() is called, the function tries to realize the device name as pci address. If this is done successfully, rte_eal_dev_attach() will attach physical device port. If not, attaches virtual devive port. When rte_eal_dev_detach() is called, the function gets the device type of this port to know whether the port is came from physical or virtual. And then specific detaching function will be called. v5: - Change function names like below. rte_eal_dev_find_and_invoke() to rte_eal_vdev_find_and_invoke(). rte_eal_dev_invoke() to rte_eal_vdev_invoke(). - Add code to handle a return value of rte_eal_devargs_remove(). - Fix pci address format in rte_eal_dev_detach(). v4: - Fix comment. - Add error checking. - Fix indent of 'if' statement. - Change function name. Signed-off-by: Tetsuya Mukawa --- lib/librte_eal/common/eal_common_dev.c | 274 lib/librte_eal/common/eal_private.h | 11 ++ lib/librte_eal/common/include/rte_dev.h | 33 lib/librte_eal/linuxapp/eal/Makefile| 1 + lib/librte_eal/linuxapp/eal/eal_pci.c | 6 +- 5 files changed, 322 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c index eae5656..e3a3f54 100644 --- a/lib/librte_eal/common/eal_common_dev.c +++ b/lib/librte_eal/common/eal_common_dev.c @@ -32,10 +32,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include +#include #include #include #include @@ -107,3 +110,274 @@ rte_eal_dev_init(void) } return 0; } + +/* So far, DPDK hotplug function only supports linux */ +#ifdef ENABLE_HOTPLUG +static void +rte_eal_vdev_invoke(struct rte_driver *driver, + struct rte_devargs *devargs, enum rte_eal_invoke_type type) +{ + if ((driver == NULL) || (devargs == NULL)) + return; + + switch (type) { + case RTE_EAL_INVOKE_TYPE_PROBE: + driver->init(devargs->virtual.drv_name, devargs->args); + break; + case RTE_EAL_INVOKE_TYPE_CLOSE: + driver->uninit(devargs->virtual.drv_name, devargs->args); + break; + default: + break; + } +} + +static int +rte_eal_vdev_find_and_invoke(const char *name, int type) +{ + struct rte_devargs *devargs; + struct rte_driver *driver; + + if (name == NULL) + return -EINVAL; + + /* call the init function for each virtual device */ + TAILQ_FOREACH(devargs, &devargs_list, next) { + + if (devargs->type != RTE_DEVTYPE_VIRTUAL) + continue; + + if (strncmp(name, devargs->virtual.drv_name, strlen(name))) + continue; + + TAILQ_FOREACH(driver, &dev_driver_list, next) { + if (driver->type != PMD_VDEV) + continue; + + /* search a driver prefix in virtual device name */ + if (!strncmp(driver->name, devargs->virtual.drv_name, + strlen(driver->name))) { + rte_eal_vdev_invoke(driver, devargs, type); + break; + } + } + + if (driver == NULL) { + RTE_LOG(WARNING, EAL, "no driver found for %s\n", + devargs->virtual.drv_name); + } + return 0; + } + return 1; +} + +/* attach the new physical device, then store port_id of the device */ +static int +rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) +{ + uint8_t new_port_id; + struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; + + if ((addr == NULL) || (port_id == NULL)) + goto err; + + /* save current port status */ + rte_eth_dev_save(devs); + /* re-construct pci_device_list */ + if (rte_eal_pci_scan()) + goto err; + /* invoke probe func of the driver can handle the new device */ + if (rte_eal_pci_probe_one(addr)) + goto err; + /* get port_id enabled by above procedures */ + if (rte_eth_dev_get_changed_port(devs, &new_port_id)) + goto err; + + *port_id = new_port_id; + return 0; +err: + RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n"); + return -1; +} + +/* detach the new physical device, then store pci_addr of the device */ +static int +rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) +{ + struct rte_pci_addr freed_addr; + struct rte_pci_addr vp; + + if (addr == NULL) + goto err; + + /* check whether the driver supports detach feature, or not */ + if (rte_eth_dev_check_detachable(port_id)) +
[dpdk-dev] [PATCH v6 13/13] eal: Enable port hotplug framework in Linux
The patch enables CONFIG_RTE_LIBRTE_EAL_HOTPLUG in Linux configuration. Signed-off-by: Tetsuya Mukawa --- config/common_linuxapp | 5 + 1 file changed, 5 insertions(+) diff --git a/config/common_linuxapp b/config/common_linuxapp index 2f9643b..27d05be 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -114,6 +114,11 @@ CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE=0 CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y # +# Compile Environment Abstraction Layer to support hotplug +# +CONFIG_RTE_LIBRTE_EAL_HOTPLUG=y + +# # Compile Environment Abstraction Layer to support Vmware TSC map # CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y -- 1.9.1
[dpdk-dev] [PATCH v6] librte_pmd_pcap: Add port hotplug support
This patch adds finalization code to free resources allocated by the PMD. v6: - Fix a paramter of rte_eth_dev_free(). v4: - Change function name. Signed-off-by: Tetsuya Mukawa --- lib/librte_pmd_pcap/rte_eth_pcap.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c index af7fae8..5f88efd 100644 --- a/lib/librte_pmd_pcap/rte_eth_pcap.c +++ b/lib/librte_pmd_pcap/rte_eth_pcap.c @@ -498,6 +498,13 @@ static struct eth_dev_ops ops = { .stats_reset = eth_stats_reset, }; +static struct eth_driver rte_pcap_pmd = { + .pci_drv = { + .name = "rte_pcap_pmd", + .drv_flags = RTE_PCI_DRV_DETACHABLE, + }, +}; + /* * Function handler that opens the pcap file for reading a stores a * reference of it for use it later on. @@ -713,6 +720,10 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, if (*eth_dev == NULL) goto error; + /* check length of device name */ + if ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name)) + goto error; + /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver @@ -739,10 +750,13 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = ð_addr; + strncpy(data->name, + (*eth_dev)->data->name, strlen((*eth_dev)->data->name)); (*eth_dev)->data = data; (*eth_dev)->dev_ops = &ops; (*eth_dev)->pci_dev = pci_dev; + (*eth_dev)->driver = &rte_pcap_pmd; return 0; @@ -927,10 +941,36 @@ rte_pmd_pcap_devinit(const char *name, const char *params) } +static int +rte_pmd_pcap_devuninit(const char *name, const char *params __rte_unused) +{ + struct rte_eth_dev *eth_dev = NULL; + + RTE_LOG(INFO, PMD, "Closing pcap ethdev on numa socket %u\n", + rte_socket_id()); + + if (name == NULL) + return -1; + + /* reserve an ethdev entry */ + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) + return -1; + + rte_free(eth_dev->data->dev_private); + rte_free(eth_dev->data); + rte_free(eth_dev->pci_dev); + + rte_eth_dev_free(eth_dev); + + return 0; +} + static struct rte_driver pmd_pcap_drv = { .name = "eth_pcap", .type = PMD_VDEV, .init = rte_pmd_pcap_devinit, + .uninit = rte_pmd_pcap_devuninit, }; PMD_REGISTER_DRIVER(pmd_pcap_drv); -- 1.9.1
[dpdk-dev] [PATCH v6] testpmd: Add port hotplug support
The patch introduces following commands. - port attach [ident] - port detach [port_id] - attach: attaching a port - detach: detaching a port - ident: pci address of physical device. Or device name and paramerters of virtual device. (ex. :02:00.0, eth_pcap0,iface=eth0) - port_id: port identifier v5: - Add testpmd documentation. (Thanks to Iremonger, Bernard) v4: - Fix strings of command help. Signed-off-by: Tetsuya Mukawa --- app/test-pmd/cmdline.c | 133 +++ app/test-pmd/config.c | 116 +--- app/test-pmd/parameters.c | 22 ++- app/test-pmd/testpmd.c | 199 +--- app/test-pmd/testpmd.h | 18 ++- doc/guides/testpmd_app_ug/testpmd_funcs.rst | 57 6 files changed, 415 insertions(+), 130 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 4beb404..2f813d8 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -572,6 +572,12 @@ static void cmd_help_long_parsed(void *parsed_result, "port close (port_id|all)\n" "Close all ports or port_id.\n\n" + "port attach (ident)\n" + "Attach physical or virtual dev by pci address or virtual device name\n\n" + + "port detach (port_id)\n" + "Detach physical or virtual dev by port_id\n\n" + "port config (port_id|all)" " speed (10|100|1000|1|4|auto)" " duplex (half|full|auto)\n" @@ -848,6 +854,89 @@ cmdline_parse_inst_t cmd_operate_specific_port = { }, }; +/* *** attach a specificied port *** */ +struct cmd_operate_attach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + cmdline_fixed_string_t identifier; +}; + +static void cmd_operate_attach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_attach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "attach")) + attach_port(res->identifier); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_attach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_attach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + keyword, "attach"); +cmdline_parse_token_string_t cmd_operate_attach_port_identifier = + TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, + identifier, NULL); + +cmdline_parse_inst_t cmd_operate_attach_port = { + .f = cmd_operate_attach_port_parsed, + .data = NULL, + .help_str = "port attach identifier, " + "identifier: pci address or virtual dev name", + .tokens = { + (void *)&cmd_operate_attach_port_port, + (void *)&cmd_operate_attach_port_keyword, + (void *)&cmd_operate_attach_port_identifier, + NULL, + }, +}; + +/* *** detach a specificied port *** */ +struct cmd_operate_detach_port_result { + cmdline_fixed_string_t port; + cmdline_fixed_string_t keyword; + uint8_t port_id; +}; + +static void cmd_operate_detach_port_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_operate_detach_port_result *res = parsed_result; + + if (!strcmp(res->keyword, "detach")) + detach_port(res->port_id); + else + printf("Unknown parameter\n"); +} + +cmdline_parse_token_string_t cmd_operate_detach_port_port = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + port, "port"); +cmdline_parse_token_string_t cmd_operate_detach_port_keyword = + TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, + keyword, "detach"); +cmdline_parse_token_num_t cmd_operate_detach_port_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_operate_detach_port = { + .f = cmd_operate_detach_port_parsed, + .data = NULL, + .help_str = "port detach port_id", + .tokens = { + (void *)&cmd_operate_detach_port_port, + (void *)&cmd_operate_detach_port_keyword, + (void *)&cmd_operate_detach_port_port_id, + NULL, + }, +}; + /* *** configure speed for all
[dpdk-dev] [PATCH 05/12] lib/librte_vhost: copy host_memory_map from virtio-net.c to a new file virtio-net-cdev.c
On 2015/02/01 0:16, Xie, Huawei wrote: >>> + * map it to our address space. >>> + */ >>> +static int >>> +host_memory_map(struct virtio_net *dev, struct virtio_memory *mem, >>> + pid_t pid, uint64_t addr) >>> +{ >> Hi Xie, >> >> This patch only copy host_memory_map() to a new file. >> And actually the original function is removed at below patch. >> - "[PATCH 07/12] lib/librte_vhost: split set_memory_table into two parts" >> >> Is it difficult to remove and copy the function in this patch? > The purpose of splitting into several patches is to be reviewer friendly. > You could easily check the changes between each commit. OK, Thanks. Tetsuya >> Thanks, >> Tetsuya >>
[dpdk-dev] [PATCH] vhost: notify guest to fill buffer when there is no buffer
Hi,xie & xu I found that the new code had try to notify guest after send each packet after 2bbb811. So this bug not exist now. static inline uint32_t __attribute__((always_inline)) virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, struct rte_mbuf **pkts, uint32_t count) { ... ... for (pkt_idx = 0; pkt_idx < count; pkt_idx++) { ... ... /* Kick the guest if necessary. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->kickfd, 1); } return count; } thank you very much! On 2015/1/30 16:20, Xu, Qian Q wrote: > Haifeng > Could you give more information so that we can reproduce your issue? Thanks. > 1. What's your dpdk package, based on which branch, with Huawei's > vhost-user's patches? > 2. What's your step and command to launch vhost sample? > 3. What is mz? Your internal tool? I can't yum install mz or download mz > tool. > 4. As to your test scenario, I understand it in this way: virtio1 in VM1, > virtio2 in VM2, then let virtio1 send packages to virtio2, the problem is > that after 3 hours, virtio2 can't receive packets, but virtio1 is still > sending packets, am I right? So mz is like a packet generator to send > packets, right? > > > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Linhaifeng > Sent: Thursday, January 29, 2015 9:51 PM > To: Xie, Huawei; dev at dpdk.org > Subject: Re: [dpdk-dev] [PATCH] vhost: notify guest to fill buffer when there > is no buffer > > > > On 2015/1/29 21:00, Xie, Huawei wrote: >> >> >>> -Original Message- >>> From: Linhaifeng [mailto:haifeng.lin at huawei.com] >>> Sent: Thursday, January 29, 2015 8:39 PM >>> To: Xie, Huawei; dev at dpdk.org >>> Subject: Re: [dpdk-dev] [PATCH] vhost: notify guest to fill buffer >>> when there is no buffer >>> >>> >>> >>> On 2015/1/29 18:39, Xie, Huawei wrote: >>> > - if (count == 0) > + /* If there is no buffers we should notify guest to fill. > + * This is need when guest use virtio_net driver(not pmd). > + */ > + if (count == 0) { > + if (!(vq->avail->flags & > VRING_AVAIL_F_NO_INTERRUPT)) > + eventfd_write((int)vq->kickfd, 1); > return 0; > + } Haifeng: Is it the root cause and is it protocol required? Could you give a detailed description for that scenario? >>> >>> I use mz to send data from one VM1 to VM2.The two VM use virtio-net driver. >>> VM1 execute follow script: >>> for((i=0;i<9;i++)); >>> do >>> mz eth0 -t udp -A 1.1.1.1 -B 1.1.1.2 -a 00:00:00:00:00:01 -b >>> 00:00:00:00:00:02 -c >>> 1000 -p 512 >>> sleep 4 >>> done >>> >>> VM2 execute follow command to watch: >>> watch -d ifconfig >>> >>> After many hours VM2 stop to receive data. >>> >>> Could you test it ? >> >> >> We could try next week after I send the whole patch. >> How many hours? Is it reproducible at your side? I inject packets through >> packet generator to guest for more than ten hours, haven't met issues. > > About three hours. > What kind of driver you used in guest?virtio-net-pmd or virtio-net? > > >> As I said in another mail sent to you, could you dump the status of vring >> if you still have the spot? > > How to dump the status of vring in guest? > >> Could you please also reply to that mail? >> > > Which mail? > > >> For the patch, if we have no root cause, I prefer not to apply it, so that >> we don't send more interrupts than needed to guest to affect performance. > > I found that if we add this notify the performance is better(growth of > 100kpps when use 64byte UDP packets) > >> People could temporarily apply this patch as a work around. >> >> Or anyone >> > > OK.I'm also not sure about this bug.I think i should do something to found > the real reason. > >> >>> -- >>> Regards, >>> Haifeng >> >> >> > -- Regards, Haifeng
[dpdk-dev] Does virtio-net PMD require specific QEMU virtio-net parameters?
Hi, I cannot invoke virtio-net PMD at least on Ubuntu12 and Ubuntu14 QEMU guest. This behavior might be seen on other users environment also, so I report it. . Here is error log. $ ./testpmd -c f -n 1 -- -i snip Configuring Port0 (socket0) Fail to configuring port 0 tx queues. EAL: Error - exiting with code: 1 Cause: Start ports failed $ As a result of bisect, it seems this behavior is caused by following patch. 61b16f0f167a331e65f0729b3554ded0440b545b virtio: check for transmit checksum config error After revert the patch, I haven't seen the error. My question is that after applying this patch, should I specify some specific parameters for QEMU virtio-net device? Here is my parameters of virtio-net. -device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:c6:a7:44,bus=pci.0,addr=0x5 \ -netdev tap,id=hostnet1 Also could someone reproduce the same issue? My host is ubuntu14, and I am using QEMU I've got using apt-get. Thanks, Tetsuya
[dpdk-dev] [PATCH 1/7] rte_sched: make RED optional at runtime
From: Stephen Hemminger Want to be able to build with RTE_SCHED_RED enabled but allow disabling RED on a per-queue basis at runtime. RED is disabled unless min/max thresholds set. Signed-off-by: Stephen Hemmminger --- lib/librte_sched/rte_sched.c | 9 + 1 file changed, 9 insertions(+) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 95dee27..6928c98 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -636,6 +636,12 @@ rte_sched_port_config(struct rte_sched_port_params *params) uint32_t j; for (j = 0; j < e_RTE_METER_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | +params->red_params[i][j].max_th) == 0) { + continue; + } + if (rte_red_config_init(&port->red_config[i][j], params->red_params[i][j].wq_log2, params->red_params[i][j].min_th, @@ -1069,6 +1075,9 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 color = rte_sched_port_pkt_read_color(pkt); red_cfg = &port->red_config[tc_index][color]; + if ( (red_cfg->min_th | red_cfg->max_th) == 0) + return 0; + qe = port->queue_extra + qindex; red = &qe->red; -- 2.1.4
[dpdk-dev] [PATCH 2/7] rte_sched: use reserved field to allow more VLAN's
From: Stephen Hemminger The QoS subport is limited to 8 bits in original code. But customers demanded ability to support full number of VLAN's (4096) therefore use reserved field of mbuf for this field instead of packing inside other classify portions. Signed-off-by: Stephen Hemminger --- lib/librte_mbuf/rte_mbuf.h | 2 +- lib/librte_sched/rte_sched.h | 31 --- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index 16059c6..b6b08f4 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -242,7 +242,7 @@ struct rte_mbuf { uint16_t data_len;/**< Amount of data in segment buffer. */ uint32_t pkt_len; /**< Total pkt len: sum of all segments. */ uint16_t vlan_tci;/**< VLAN Tag Control Identifier (CPU order) */ - uint16_t reserved; + uint16_t subport; /**< SCHED Subport ID */ union { uint32_t rss; /**< RSS hash result if RSS enabled */ struct { diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index e6bba22..0688422 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -195,15 +195,18 @@ struct rte_sched_port_params { #endif }; -/** Path through the scheduler hierarchy used by the scheduler enqueue operation to -identify the destination queue for the current packet. Stored in the field hash.sched -of struct rte_mbuf of each packet, typically written by the classification stage and read by -scheduler enqueue.*/ +/* + * Path through the scheduler hierarchy used by the scheduler enqueue + * operation to identify the destination queue for the current + * packet. Stored in the field pkt.hash.sched of struct rte_mbuf of + * each packet, typically written by the classification stage and read + * by scheduler enqueue. + */ struct rte_sched_port_hierarchy { uint32_t queue:2;/**< Queue ID (0 .. 3) */ uint32_t traffic_class:2;/**< Traffic class ID (0 .. 3)*/ uint32_t pipe:20;/**< Pipe ID */ - uint32_t subport:6; /**< Subport ID */ + uint32_t extra:6;/**< currently unused */ uint32_t color:2;/**< Color */ }; @@ -350,12 +353,15 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, */ static inline void rte_sched_port_pkt_write(struct rte_mbuf *pkt, - uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue, enum rte_meter_color color) +uint32_t subport, uint32_t pipe, +uint32_t traffic_class, +uint32_t queue, enum rte_meter_color color) { - struct rte_sched_port_hierarchy *sched = (struct rte_sched_port_hierarchy *) &pkt->hash.sched; + struct rte_sched_port_hierarchy *sched + = (struct rte_sched_port_hierarchy *) &pkt->hash.sched; + pkt->subport = subport; sched->color = (uint32_t) color; - sched->subport = subport; sched->pipe = pipe; sched->traffic_class = traffic_class; sched->queue = queue; @@ -379,11 +385,14 @@ rte_sched_port_pkt_write(struct rte_mbuf *pkt, * */ static inline void -rte_sched_port_pkt_read_tree_path(struct rte_mbuf *pkt, uint32_t *subport, uint32_t *pipe, uint32_t *traffic_class, uint32_t *queue) +rte_sched_port_pkt_read_tree_path(struct rte_mbuf *pkt, uint32_t *subport, + uint32_t *pipe, uint32_t *traffic_class, + uint32_t *queue) { - struct rte_sched_port_hierarchy *sched = (struct rte_sched_port_hierarchy *) &pkt->hash.sched; + struct rte_sched_port_hierarchy *sched + = (struct rte_sched_port_hierarchy *) &pkt->hash.sched; - *subport = sched->subport; + *subport = pkt->subport; *pipe = sched->pipe; *traffic_class = sched->traffic_class; *queue = sched->queue; -- 2.1.4
[dpdk-dev] [PATCH 3/7] rte_sched: keep track of RED drops
From: Stephen Hemminger Add new statistic to keep track of drops due to RED. Signed-off-by: Stephen Hemminger --- lib/librte_sched/rte_sched.c | 28 +++- lib/librte_sched/rte_sched.h | 6 ++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6928c98..8cb8bf1 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1028,7 +1028,9 @@ rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex } static inline void -rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, + uint32_t qindex, + struct rte_mbuf *pkt, uint32_t red) { struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = (qindex >> 2) & 0x3; @@ -1036,6 +1038,9 @@ rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, uint32_ s->stats.n_pkts_tc_dropped[tc_index] += 1; s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; +#ifdef RTE_SCHED_RED + s->stats.n_pkts_red_dropped[tc_index] += red; +#endif } static inline void @@ -1049,13 +1054,18 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, } static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, + uint32_t qindex, + struct rte_mbuf *pkt, uint32_t red) { struct rte_sched_queue_extra *qe = port->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; qe->stats.n_bytes_dropped += pkt_len; +#ifdef RTE_SCHED_RED + qe->stats.n_pkts_red_dropped += red; +#endif } #endif /* RTE_SCHED_COLLECT_STATS */ @@ -1206,12 +1216,20 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, struct qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || (qlen >= qsize))) { + if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen))) { +#ifdef RTE_SCHED_COLLECT_STATS + rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, 1); + rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, 1); +#endif rte_pktmbuf_free(pkt); + } + + if (qlen >= qsize) { #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt); + rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, 0); + rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, 0); #endif + rte_pktmbuf_free(pkt); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 0688422..d5a1d5b 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -140,6 +140,9 @@ struct rte_sched_subport_stats { subport for each traffic class*/ uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of bytes dropped by the current subport for each traffic class due to subport queues being full or congested */ +#ifdef RTE_SCHED_RED + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of packets dropped by red */ +#endif }; /** Pipe configuration parameters. The period and credits_per_period parameters are measured @@ -168,6 +171,9 @@ struct rte_sched_queue_stats { /* Packets */ uint32_t n_pkts; /**< Number of packets successfully written to current queue */ uint32_t n_pkts_dropped; /**< Number of packets dropped due to current queue being full or congested */ +#ifdef RTE_SCHED_RED + uint32_t n_pkts_red_dropped; +#endif /* Bytes */ uint32_t n_bytes;/**< Number of bytes successfully written to current queue */ -- 2.1.4
[dpdk-dev] [PATCH 4/7] rte_sched: don't clear statistics when read
From: Stephen Hemminger Make rte_sched statistics API work like the ethernet statistics API. Don't auto-clear statistics. Signed-off-by: Stephen Hemminger --- lib/librte_sched/rte_sched.c | 30 ++ lib/librte_sched/rte_sched.h | 29 + 2 files changed, 59 insertions(+) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 8cb8bf1..d891e50 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -935,6 +935,21 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, } int +rte_sched_subport_stats_reset(struct rte_sched_port *port, + uint32_t subport_id) +{ + struct rte_sched_subport *s; + + /* Check user parameters */ + if (port == NULL || subport_id >= port->n_subports_per_port) + return -1; + + s = port->subport + subport_id; + memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats)); + return 0; +} + +int rte_sched_queue_read_stats(struct rte_sched_port *port, uint32_t queue_id, struct rte_sched_queue_stats *stats, @@ -963,6 +978,21 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, return 0; } +int +rte_sched_queue_stats_reset(struct rte_sched_port *port, + uint32_t queue_id) +{ + struct rte_sched_queue_extra *qe; + + /* Check user parameters */ + if (port == NULL || queue_id >= rte_sched_port_queues_per_port(port)) + return -1; + + qe = port->queue_extra + queue_id; + memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats)); + return 0; +} + static inline uint32_t rte_sched_port_qindex(struct rte_sched_port *port, uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue) { diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index d5a1d5b..64b4dd6 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -316,6 +316,21 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, struct rte_sched_subport_stats *stats, uint32_t *tc_ov); + +/** + * Hierarchical scheduler subport statistics reset + * + * @param port + * Handle to port scheduler instance + * @param subport_id + * Subport ID + * @return + * 0 upon success, error code otherwise + */ +int +rte_sched_subport_stats_reset(struct rte_sched_port *port, + uint32_t subport_id); + /** * Hierarchical scheduler queue statistics read * @@ -337,6 +352,20 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen); +/** + * Hierarchical scheduler queue statistics reset + * + * @param port + * Handle to port scheduler instance + * @param queue_id + * Queue ID within port scheduler + * @return + * 0 upon success, error code otherwise + */ +int +rte_sched_queue_stats_reset(struct rte_sched_port *port, + uint32_t queue_id); + /* * Run-time * -- 2.1.4
[dpdk-dev] [PATCH 5/7] rte_sched: don't put tabs in log messages
From: Stephen Hemminger syslog does not like tabs in log messages; tab gets translated to #011 Signed-off-by: Stephen Hemminger --- lib/librte_sched/rte_sched.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d891e50..55fbc14 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -495,10 +495,10 @@ rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) struct rte_sched_pipe_profile *p = port->pipe_profiles + i; RTE_LOG(INFO, SCHED, "Low level config for pipe profile %u:\n" - "\tToken bucket: period = %u, credits per period = %u, size = %u\n" - "\tTraffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" - "\tTraffic class 3 oversubscription: weight = %hhu\n" - "\tWRR cost: [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu]\n", + "Token bucket: period = %u, credits per period = %u, size = %u\n" + "Traffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" + "Traffic class 3 oversubscription: weight = %hhu\n" + "WRR cost: [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu]\n", i, /* Token bucket */ @@ -716,9 +716,9 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) struct rte_sched_subport *s = port->subport + i; RTE_LOG(INFO, SCHED, "Low level config for subport %u:\n" - "\tToken bucket: period = %u, credits per period = %u, size = %u\n" - "\tTraffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" - "\tTraffic class 3 oversubscription: wm min = %u, wm max = %u\n", + "Token bucket: period = %u, credits per period = %u, size = %u\n" + "Traffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" + "Traffic class 3 oversubscription: wm min = %u, wm max = %u\n", i, /* Token bucket */ -- 2.1.4
[dpdk-dev] [PATCH 6/7] rte_sched: eliminate floating point in calculating byte clock
From: Stephen Hemminger The old code was doing a floating point divide for each rte_dequeue() which is very expensive. Change to using fixed point scaled math instead. This improved performance from 5Gbit/sec to 10 Gbit/sec Signed-off-by: Stephen Hemminger --- lib/librte_sched/rte_sched.c | 14 ++ 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 55fbc14..3023457 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -102,6 +102,9 @@ #define RTE_SCHED_BMP_POS_INVALID UINT32_MAX +/* For cycles_per_byte calculation */ +#define RTE_SCHED_TIME_SHIFT 20 + struct rte_sched_subport { /* Token bucket (TB) */ uint64_t tb_time; /* time of last update */ @@ -239,7 +242,7 @@ struct rte_sched_port { uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ uint64_t time_cpu_bytes; /* Current CPU time measured in bytes */ uint64_t time;/* Current NIC TX time measured in bytes */ - double cycles_per_byte; /* CPU cycles per byte */ + uint32_t cycles_per_byte; /* CPU cycles per byte (scaled) */ /* Scheduling loop detection */ uint32_t pipe_loop; @@ -657,7 +660,9 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->time_cpu_cycles = rte_get_tsc_cycles(); port->time_cpu_bytes = 0; port->time = 0; - port->cycles_per_byte = ((double) rte_get_tsc_hz()) / ((double) params->rate); + + port->cycles_per_byte = (rte_get_tsc_hz() << RTE_SCHED_TIME_SHIFT) + / params->rate; /* Scheduling loop detection */ port->pipe_loop = RTE_SCHED_PIPE_INVALID; @@ -2156,11 +2161,12 @@ rte_sched_port_time_resync(struct rte_sched_port *port) { uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; - double bytes_diff = ((double) cycles_diff) / port->cycles_per_byte; + uint64_t bytes_diff = (cycles_diff << RTE_SCHED_TIME_SHIFT) + / port->cycles_per_byte; /* Advance port time */ port->time_cpu_cycles = cycles; - port->time_cpu_bytes += (uint64_t) bytes_diff; + port->time_cpu_bytes += bytes_diff; if (port->time < port->time_cpu_bytes) { port->time = port->time_cpu_bytes; } -- 2.1.4
[dpdk-dev] [PATCH 7/7] rte_sched: rearrange data structures
From: Stephen Hemminger Rearrange internal data structures to eliminate holes. Signed-off-by: Stephen Hemminger --- lib/librte_sched/rte_sched.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 3023457..7de1395 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -198,6 +198,8 @@ struct rte_sched_grinder { enum grinder_state state; uint32_t productive; uint32_t pindex; + uint32_t qpos; + struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_pipe_profile *pipe_params; @@ -212,11 +214,10 @@ struct rte_sched_grinder { uint32_t tc_index; struct rte_sched_queue *queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; struct rte_mbuf **qbase[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + struct rte_mbuf *pkt; uint32_t qindex[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint16_t qsize; uint32_t qmask; - uint32_t qpos; - struct rte_mbuf *pkt; + uint16_t qsize; /* WRR */ uint16_t wrr_tokens[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; @@ -234,9 +235,7 @@ struct rte_sched_port { uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t pipe_tc3_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][e_RTE_METER_COLORS]; -#endif + uint32_t busy_grinders; /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -247,16 +246,15 @@ struct rte_sched_port { /* Scheduling loop detection */ uint32_t pipe_loop; uint32_t pipe_exhaustion; + uint32_t n_pkts_out; /* Bitmap */ struct rte_bitmap *bmp; + struct rte_mbuf **pkts_out; uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; /* Grinders */ struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; - struct rte_mbuf **pkts_out; - uint32_t n_pkts_out; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -270,6 +268,9 @@ struct rte_sched_port { struct rte_sched_pipe_profile *pipe_profiles; uint8_t *bmp_array; struct rte_mbuf **queue_array; +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][e_RTE_METER_COLORS]; +#endif uint8_t memory[0] __rte_cache_aligned; } __rte_cache_aligned; -- 2.1.4
[dpdk-dev] [PATCH v1] librte_vhost: Add an abstraction to hide vhost-user and cuse devices.
This patch should be put on "lib/librte_vhost: vhost-user support" patch series written by Xie, Huawei. There are 2 type of vhost devices. One is cuse, the other is vhost-user. So far, one of them we can use. To use the other, DPDK is needed to be recompiled. The patch introduces rte_vhost_dev_type parameter. Using type parameter, the DPDK application can use both vhost devices without recompile. The type parameter should be specified when following vhost APIs are called. - int rte_vhost_driver_register(); - int rte_vhost_driver_session_start(); Signed-off-by: Tetsuya Mukawa --- examples/vhost/main.c| 4 +- lib/librte_vhost/Makefile| 4 +- lib/librte_vhost/rte_virtio_net.h| 15 +- lib/librte_vhost/vhost-net.c | 74 lib/librte_vhost/vhost_cuse/vhost-net-cdev.c | 5 +- lib/librte_vhost/vhost_cuse/vhost-net-cdev.h | 42 lib/librte_vhost/vhost_user/vhost-net-user.c | 4 +- lib/librte_vhost/vhost_user/vhost-net-user.h | 7 +++ 8 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 lib/librte_vhost/vhost-net.c create mode 100644 lib/librte_vhost/vhost_cuse/vhost-net-cdev.h diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 04f0118..545df72 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -3040,14 +3040,14 @@ main(int argc, char *argv[]) rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF); /* Register CUSE device to handle IOCTLs. */ - ret = rte_vhost_driver_register((char *)&dev_basename); + ret = rte_vhost_driver_register((char *)&dev_basename, VHOST_DEV_CUSE); if (ret != 0) rte_exit(EXIT_FAILURE,"CUSE device setup failure.\n"); rte_vhost_driver_callback_register(&virtio_net_device_ops); /* Start CUSE session. */ - rte_vhost_driver_session_start(); + rte_vhost_driver_session_start(VHOST_DEV_CUSE); return 0; } diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile index 22319b8..cc95415 100644 --- a/lib/librte_vhost/Makefile +++ b/lib/librte_vhost/Makefile @@ -39,8 +39,8 @@ CFLAGS += -I vhost_cuse -lfuse CFLAGS += -I vhost_user LDFLAGS += -lfuse # all source are stored in SRCS-y -SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := virtio-net.c vhost_rxtx.c -#SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c vhost_cuse/eventfd_copy.c +SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := virtio-net.c vhost-net.c vhost_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c vhost_cuse/eventfd_copy.c SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_user/vhost-net-user.c vhost_user/virtio-net-user.c vhost_user/fd_man.c # install includes diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index 611a3d4..7b3952c 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -166,6 +166,15 @@ gpa_to_vva(struct virtio_net *dev, uint64_t guest_pa) } /** + * Enum for vhost device types. + */ +enum rte_vhost_dev_type { + VHOST_DEV_CUSE, /* cuse driver */ + VHOST_DEV_USER, /* vhost-user driver */ + VHOST_DEV_MAX /* the number of vhost driver types */ +}; + +/** * Disable features in feature_mask. Returns 0 on success. */ int rte_vhost_feature_disable(uint64_t feature_mask); @@ -181,12 +190,14 @@ uint64_t rte_vhost_feature_get(void); int rte_vhost_enable_guest_notification(struct virtio_net *dev, uint16_t queue_id, int enable); /* Register vhost driver. dev_name could be different for multiple instance support. */ -int rte_vhost_driver_register(const char *dev_name); +int rte_vhost_driver_register(const char *dev_name, + enum rte_vhost_dev_type dev_type); /* Register callbacks. */ int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const); + /* Start vhost driver session blocking loop. */ -int rte_vhost_driver_session_start(void); +int rte_vhost_driver_session_start(enum rte_vhost_dev_type dev_type); /** * This function adds buffers to the virtio devices RX virtqueue. Buffers can diff --git a/lib/librte_vhost/vhost-net.c b/lib/librte_vhost/vhost-net.c new file mode 100644 index 000..d0316d7 --- /dev/null +++ b/lib/librte_vhost/vhost-net.c @@ -0,0 +1,74 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the do
[dpdk-dev] [PATCH 03/18] fm10k: Add empty fm10k files
On Fri, Jan 30, 2015 at 6:07 AM, Chen Jing D(Mark) wrote: > From: Jeff Shaw > > Define macros and basic data structure. > Define rte_log wrapper functions. > This comment applies to the logs macro (and the rest of the patchset). - don't use a build option for logs to be displayed, especially if these are init messages or error messages that prevent the pmd from working - you can remove this "Use RTE_LOG directly to make sure this error is seen." in fm10k_rx_queue_setup if you use a "init" macro that is not under a build option - don't use \n in logs, only one is enough Please, check the cleanup work that has been done in other Intel pmd (for example, ixgbe). I would really prefer we have consistent logs across dpdk. -- David Marchand > > Signed-off-by: Jeff Shaw > Signed-off-by: Chen Jing D(Mark) > --- > lib/librte_pmd_fm10k/Makefile | 96 > lib/librte_pmd_fm10k/fm10k.h | 224 > + > lib/librte_pmd_fm10k/fm10k_logs.h | 66 +++ > 3 files changed, 386 insertions(+), 0 deletions(-) > create mode 100644 lib/librte_pmd_fm10k/Makefile > create mode 100644 lib/librte_pmd_fm10k/fm10k.h > create mode 100644 lib/librte_pmd_fm10k/fm10k_ethdev.c > create mode 100644 lib/librte_pmd_fm10k/fm10k_logs.h > create mode 100644 lib/librte_pmd_fm10k/fm10k_rxtx.c > > diff --git a/lib/librte_pmd_fm10k/Makefile b/lib/librte_pmd_fm10k/Makefile > new file mode 100644 > index 000..3d76387 > --- /dev/null > +++ b/lib/librte_pmd_fm10k/Makefile > @@ -0,0 +1,96 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2013-2014 Intel Corporation. All rights reserved. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +include $(RTE_SDK)/mk/rte.vars.mk > + > +# > +# library name > +# > +LIB = librte_pmd_fm10k.a > + > +CFLAGS += -O3 > +CFLAGS += $(WERROR_FLAGS) > + > +ifeq ($(CC), icc) > +# > +# CFLAGS for icc > +# > +CFLAGS_BASE_DRIVER = -wd174 -wd593 -wd869 -wd981 -wd2259 > + > +else ifeq ($(CC), clang) > +# > +## CFLAGS for clang > +# > +CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value > +CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args > +CFLAGS_BASE_DRIVER += -Wno-unused-variable -Wno-unused-but-set-variable > +CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers > + > +else > +# > +# CFLAGS for gcc > +# > +ifneq ($(shell test $(GCC_MAJOR_VERSION) -le 4 -a $(GCC_MINOR_VERSION) > -le 3 && echo 1), 1) > +CFLAGS += -Wno-deprecated > +endif > +CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value > +CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args > +CFLAGS_BASE_DRIVER += -Wno-unused-variable -Wno-unused-but-set-variable > +CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers > +endif > + > +# > +# Add extra flags for base driver source files to disable warnings in them > +# > +BASE_DRIVER_OBJS=$(patsubst %.c,%.o,$(notdir $(wildcard > $(RTE_SDK)/lib/librte_pmd_fm10k/SHARED/*.c))) > +$(foreach obj, $(BASE_DRIVER_OBJS), $(eval > CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) > + > +VPATH += $(RTE_SDK)/lib/librte_pmd_fm10k/SHARED > + > +# > +# all source are stored in SRCS-y > +# > +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_ethdev.c > +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_rxtx.c > + > +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_pf.c > +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_tlv.c > +SRCS-$(CONFIG_RTE_LIBRTE_FM10
[dpdk-dev] [PATCH v6 0/7] rte_hash_crc reworked to be platform-independent
On Thu, Jan 29, 2015 at 02:48:11PM +0600, Yerden Zhumabekov wrote: > This is a rework of my previous patches improving performance of rte_hash_crc. > > Summary of changes: > * software implementation of CRC32 introduced; > * in the runtime, algorithm can fall back to software version if CPU doesn't > support SSE4.2; > * best available algorithm is automatically detected upon application startup; > * redundant compile checks removed from test utilities; > * assembly code for emitting SSE4.2 instructions is used instead of built-in > intrinsics; > * rte_hash_crc() function performance significantly improved. > > v6 changes: > * added 'const' qualifier to crc32c lookup tables declaration. > > v5 changes: > * given up gcc's builtin SSE4.2 intrinsics; > * add assembly code for emitting SSE4.2 instructions. > > v4 changes: > * icc-specific compile checks removed. > > v3 changes: > * setting default algorithm implementation as a constructor while application > startup; > * crc32 software implementation improved; > * removed compile-time checks from test_hash_perf and test_hash. > > v2 changes: > * added CRC32 software implementation; > * added rte_hash_crc_set_alg() function to control availability of SSE4.2; > * added fallback to sw crc32 in case SSE4.2 is not available, or if SSE4.2 is > intentionally disabled. > > Initial version (v1) changes: > * added rte_hash_crc_8byte() function to calculate CRC32 on 8-byte operand; > * reworked rte_hash_crc() function which leverages both versions of CRC32 > hash calculation functions with 4 and 8-byte operands. > > > Yerden Zhumabekov (7): > hash: add software CRC32 implementation > hash: add assembly implementation of CRC32 intrinsics > hash: replace built-in functions implementing SSE4.2 > hash: add rte_hash_crc_8byte function > hash: add fallback to software CRC32 implementation > hash: rte_hash_crc() slices data into 8-byte pieces > test: remove redundant compile checks > > app/test/test_hash.c |7 - > app/test/test_hash_perf.c | 11 - > lib/librte_hash/rte_hash_crc.h | 459 > +++- > 3 files changed, 448 insertions(+), 29 deletions(-) > > -- > 1.7.9.5 > > Just to be clear, this does build if you compile it against the "default" machine type, correct? Neil
[dpdk-dev] [PATCH 4/7] rte_sched: don't clear statistics when read
On Sun, Feb 01, 2015 at 10:03:48AM +, Stephen Hemminger wrote: > From: Stephen Hemminger > > Make rte_sched statistics API work like the ethernet statistics API. > Don't auto-clear statistics. > > Signed-off-by: Stephen Hemminger > --- > lib/librte_sched/rte_sched.c | 30 ++ > lib/librte_sched/rte_sched.h | 29 + > 2 files changed, 59 insertions(+) > > diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c > index 8cb8bf1..d891e50 100644 > --- a/lib/librte_sched/rte_sched.c > +++ b/lib/librte_sched/rte_sched.c > @@ -935,6 +935,21 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, > } > > int > +rte_sched_subport_stats_reset(struct rte_sched_port *port, > + uint32_t subport_id) > +{ > + struct rte_sched_subport *s; > + > + /* Check user parameters */ > + if (port == NULL || subport_id >= port->n_subports_per_port) > + return -1; > + > + s = port->subport + subport_id; > + memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats)); Its like this in the current implementation as well, but isn't this a bit racy? Like if we're clearning the stats while another thread is polling the interface? Would it be worth implementing a toggle mechanism whereby a reset does an atomic cmpxch on the stats pointer between two stats copies, then zeroing the exchanged copy? Neil > + return 0; > +} > + > +int > rte_sched_queue_read_stats(struct rte_sched_port *port, > uint32_t queue_id, > struct rte_sched_queue_stats *stats, > @@ -963,6 +978,21 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, > return 0; > } > > +int > +rte_sched_queue_stats_reset(struct rte_sched_port *port, > + uint32_t queue_id) > +{ > + struct rte_sched_queue_extra *qe; > + > + /* Check user parameters */ > + if (port == NULL || queue_id >= rte_sched_port_queues_per_port(port)) > + return -1; > + > + qe = port->queue_extra + queue_id; > + memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats)); > + return 0; > +} > + > static inline uint32_t > rte_sched_port_qindex(struct rte_sched_port *port, uint32_t subport, > uint32_t pipe, uint32_t traffic_class, uint32_t queue) > { > diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h > index d5a1d5b..64b4dd6 100644 > --- a/lib/librte_sched/rte_sched.h > +++ b/lib/librte_sched/rte_sched.h > @@ -316,6 +316,21 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, > struct rte_sched_subport_stats *stats, > uint32_t *tc_ov); > > + > +/** > + * Hierarchical scheduler subport statistics reset > + * > + * @param port > + * Handle to port scheduler instance > + * @param subport_id > + * Subport ID > + * @return > + * 0 upon success, error code otherwise > + */ > +int > +rte_sched_subport_stats_reset(struct rte_sched_port *port, > + uint32_t subport_id); > + > /** > * Hierarchical scheduler queue statistics read > * > @@ -337,6 +352,20 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, > struct rte_sched_queue_stats *stats, > uint16_t *qlen); > > +/** > + * Hierarchical scheduler queue statistics reset > + * > + * @param port > + * Handle to port scheduler instance > + * @param queue_id > + * Queue ID within port scheduler > + * @return > + * 0 upon success, error code otherwise > + */ > +int > +rte_sched_queue_stats_reset(struct rte_sched_port *port, > + uint32_t queue_id); > + > /* > * Run-time > * > -- > 2.1.4 > >
[dpdk-dev] [PATCH v6 0/7] rte_hash_crc reworked to be platform-independent
On Mon, Feb 02, 2015 at 09:07:45AM +0600, Yerden Zhumabekov wrote: > > 01.02.2015 20:13, Neil Horman ?: > > On Thu, Jan 29, 2015 at 02:48:11PM +0600, Yerden Zhumabekov wrote: > >> This is a rework of my previous patches improving performance of > >> rte_hash_crc. > >> > >> Summary of changes: > >> * software implementation of CRC32 introduced; > >> * in the runtime, algorithm can fall back to software version if CPU > >> doesn't support SSE4.2; > >> * best available algorithm is automatically detected upon application > >> startup; > >> * redundant compile checks removed from test utilities; > >> * assembly code for emitting SSE4.2 instructions is used instead of > >> built-in intrinsics; > >> * rte_hash_crc() function performance significantly improved. > >> > >> v6 changes: > >> * added 'const' qualifier to crc32c lookup tables declaration. > > Just to be clear, this does build if you compile it against the "default" > > machine type, correct? > > Neil > > I think so, I've just successfully built it against latest snapshot with > RTE_TARGET > equal to 'x86_64-native-linuxapp-gcc'. > Please confirm that setting the machine type to default builds and runs properly. Neil > -- > Sincerely, > > Yerden Zhumabekov > State Technical Service > Astana, KZ > > >
[dpdk-dev] [RFC PATCH 0/4] welcome doc for new nics and environments
Too many things are included in the programmers guide. I think it should cover only API and knowledge needed to make an application. That's why I suggest to move Xen and NICs doc outside. Then it will be easier to add doc for a new environment or a new NIC. Note that drivers or device-related libs like KNI, vhost or bonding stay in the programmer's guide because they are more high-level than NICs drivers. I suggest also to remove the HTML footer to be more vendor neutral and clearly welcome new contributors. Thomas Monjalon (4): doc: fix file attributes doc: move Xen guide out of programmers guide doc: nics guide doc: remove copyright footer MAINTAINERS| 15 +- doc/guides/conf.py | 3 +- doc/guides/index.rst | 2 + .../driver_vm_emul_dev.rst => nics/e1000em.rst}| 0 doc/guides/{prog_guide => nics}/img/console.png| Bin .../{prog_guide => nics}/img/fast_pkt_proc.png | Bin .../{prog_guide => nics}/img/forward_stats.png | Bin .../{prog_guide => nics}/img/host_vm_comms.png | Bin .../img/host_vm_comms_qemu.png | Bin .../{prog_guide => nics}/img/inter_vm_comms.png| Bin .../{prog_guide => nics}/img/perf_benchmark.png| Bin .../{prog_guide => nics}/img/single_port_nic.png | Bin .../{prog_guide => nics}/img/vm_vm_comms.png | Bin .../{prog_guide => nics}/img/vmxnet3_int.png | Bin doc/guides/{prog_guide => nics}/img/vswitch_vm.png | Bin doc/guides/{ => nics}/index.rst| 27 +-- .../intel_vf.rst} | 0 doc/guides/nics/ixgbe.rst | 184 + .../pcap_ring.rst} | 0 .../virtio.rst}| 0 .../vmxnet3.rst} | 0 doc/guides/prog_guide/index.rst| 18 -- doc/guides/prog_guide/poll_mode_drv.rst| 152 - .../img/dpdk_xen_pkt_switch.png| Bin doc/guides/{prog_guide => xen}/img/grant_refs.png | Bin doc/guides/{prog_guide => xen}/img/grant_table.png | Bin .../index.rst} | 2 + 27 files changed, 215 insertions(+), 188 deletions(-) rename doc/guides/{prog_guide/driver_vm_emul_dev.rst => nics/e1000em.rst} (100%) rename doc/guides/{prog_guide => nics}/img/console.png (100%) rename doc/guides/{prog_guide => nics}/img/fast_pkt_proc.png (100%) rename doc/guides/{prog_guide => nics}/img/forward_stats.png (100%) rename doc/guides/{prog_guide => nics}/img/host_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/host_vm_comms_qemu.png (100%) rename doc/guides/{prog_guide => nics}/img/inter_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/perf_benchmark.png (100%) rename doc/guides/{prog_guide => nics}/img/single_port_nic.png (100%) rename doc/guides/{prog_guide => nics}/img/vm_vm_comms.png (100%) rename doc/guides/{prog_guide => nics}/img/vmxnet3_int.png (100%) rename doc/guides/{prog_guide => nics}/img/vswitch_vm.png (100%) copy doc/guides/{ => nics}/index.rst (88%) rename doc/guides/{prog_guide/i40e_ixgbe_igb_virt_func_drv.rst => nics/intel_vf.rst} (100%) mode change 100755 => 100644 create mode 100644 doc/guides/nics/ixgbe.rst rename doc/guides/{prog_guide/libpcap_ring_based_poll_mode_drv.rst => nics/pcap_ring.rst} (100%) rename doc/guides/{prog_guide/poll_mode_drv_emulated_virtio_nic.rst => nics/virtio.rst} (100%) rename doc/guides/{prog_guide/poll_mode_drv_paravirtual_vmxnets_nic.rst => nics/vmxnet3.rst} (100%) mode change 100755 => 100644 doc/guides/prog_guide/poll_mode_drv.rst rename doc/guides/{prog_guide => xen}/img/dpdk_xen_pkt_switch.png (100%) rename doc/guides/{prog_guide => xen}/img/grant_refs.png (100%) rename doc/guides/{prog_guide => xen}/img/grant_table.png (100%) rename doc/guides/{prog_guide/intel_dpdk_xen_based_packet_switch_sol.rst => xen/index.rst} (99%) -- 2.2.2