From 4c39baf297d10c217e7d3e7370f26a1fede58308 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Fri, 11 Apr 2014 09:36:52 +0200 Subject: [PATCH] vdev: new registration API Instead of having a list of virtual device drivers in EAL code, add an API to register drivers. Thanks to this new registration method, we can remove the references to pmd_ring, pmd_pcap and pmd_xenvirt in EAL code. This also enables the ability to register a virtual device driver as a shared library. The registration is done in an init function flaged with __attribute__((constructor)). The new convention is to name this function rte_pmd_xyz_init(). The per-device init function is renamed rte_pmd_xyz_devinit(). By the way the internal PMDs are now also .so/standalone ready. Let's do it later on. It will be required to ease maintenance. Signed-off-by: Olivier Matz Acked-by: Thomas Monjalon --- app/test/test_pmd_ring.c | 6 +- lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_vdev.c | 80 ++++++++----------- .../common/include/rte_vdev.h} | 64 +++++++++++---- lib/librte_pmd_pcap/Makefile | 2 +- lib/librte_pmd_pcap/rte_eth_pcap.c | 18 ++++- lib/librte_pmd_ring/rte_eth_ring.c | 15 +++- lib/librte_pmd_ring/rte_eth_ring.h | 6 +- lib/librte_pmd_xenvirt/rte_eth_xenvirt.c | 16 +++- lib/librte_pmd_xenvirt/rte_eth_xenvirt.h | 8 -- 10 files changed, 133 insertions(+), 84 deletions(-) rename lib/{librte_pmd_pcap/rte_eth_pcap.h => librte_eal/common/include/rte_vdev.h} (56%) diff --git a/app/test/test_pmd_ring.c b/app/test/test_pmd_ring.c index c8242b3d2c..4d9c2ba5a0 100644 --- a/app/test/test_pmd_ring.c +++ b/app/test/test_pmd_ring.c @@ -315,12 +315,12 @@ test_pmd_ring_init(void) printf("Testing ring pmd init\n"); - if (rte_pmd_ring_init(name1, params_null) < 0) { + if (rte_pmd_ring_devinit(name1, params_null) < 0) { printf("Testing ring pmd init fail\n"); return -1; } - if (rte_pmd_ring_init(name2, params) < 0) { + if (rte_pmd_ring_devinit(name2, params) < 0) { printf("Testing ring pmd init fail\n"); return -1; } @@ -372,7 +372,7 @@ test_pmd_ring_init(void) rte_eth_dev_stop(RXTX_PORT2); /* Test init same name pmd ring */ - rte_pmd_ring_init(name1, params_null); + rte_pmd_ring_devinit(name1, params_null); return 0; } diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile index b9f3b8880f..2f99bf4227 100644 --- a/lib/librte_eal/common/Makefile +++ b/lib/librte_eal/common/Makefile @@ -38,7 +38,7 @@ INC += rte_pci_dev_ids.h rte_per_lcore.h rte_prefetch.h rte_random.h INC += rte_rwlock.h rte_spinlock.h rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_string_fns.h rte_cpuflags.h rte_version.h rte_tailq_elem.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h +INC += rte_hexdump.h rte_devargs.h rte_vdev.h ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y) INC += rte_warnings.h diff --git a/lib/librte_eal/common/eal_common_vdev.c b/lib/librte_eal/common/eal_common_vdev.c index 02d3fd6b46..62d03028c6 100644 --- a/lib/librte_eal/common/eal_common_vdev.c +++ b/lib/librte_eal/common/eal_common_vdev.c @@ -34,56 +34,43 @@ #include #include -#include -#ifdef RTE_LIBRTE_PMD_RING -#include -#endif -#ifdef RTE_LIBRTE_PMD_PCAP -#include -#endif -#ifdef RTE_LIBRTE_PMD_XENVIRT -#include -#endif +#include + +#include +#include #include #include + #include "eal_private.h" -struct device_init { - const char *dev_prefix; - int (*init_fn)(const char*, const char *); -}; +/** Global list of virtual device drivers. */ +static struct rte_vdev_driver_list vdev_driver_list = + TAILQ_HEAD_INITIALIZER(vdev_driver_list); -#define NUM_DEV_TYPES (sizeof(dev_types)/sizeof(dev_types[0])) -struct device_init dev_types[] = { -#ifdef RTE_LIBRTE_PMD_RING - { - .dev_prefix = RTE_ETH_RING_PARAM_NAME, - .init_fn = rte_pmd_ring_init - }, -#endif -#ifdef RTE_LIBRTE_PMD_PCAP - { - .dev_prefix = RTE_ETH_PCAP_PARAM_NAME, - .init_fn = rte_pmd_pcap_init - }, -#endif -#ifdef RTE_LIBRTE_PMD_XENVIRT - { - .dev_prefix = RTE_ETH_XENVIRT_PARAM_NAME, - .init_fn = rte_pmd_xenvirt_init - }, -#endif - { - .dev_prefix = "-nodev-", - .init_fn = NULL - } -}; +/* register a driver */ +void +rte_eal_vdev_driver_register(struct rte_vdev_driver *driver) +{ + TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next); +} + +/* unregister a driver */ +void +rte_eal_vdev_driver_unregister(struct rte_vdev_driver *driver) +{ + TAILQ_REMOVE(&vdev_driver_list, driver, next); +} int rte_eal_vdev_init(void) { struct rte_devargs *devargs; - uint8_t i; + struct rte_vdev_driver *driver; + + /* No need to register drivers that are embeded in DPDK + * (pmd_pcap, pmd_ring, ...). The initialization function have + * the ((constructor)) attribute so they will register at + * startup. */ /* call the init function for each virtual device */ TAILQ_FOREACH(devargs, &devargs_list, next) { @@ -91,18 +78,17 @@ rte_eal_vdev_init(void) if (devargs->type != RTE_DEVTYPE_VIRTUAL) continue; - for (i = 0; i < NUM_DEV_TYPES; i++) { + TAILQ_FOREACH(driver, &vdev_driver_list, next) { /* search a driver prefix in virtual device name */ - if (!strncmp(dev_types[i].dev_prefix, - devargs->virtual.drv_name, - sizeof(dev_types[i].dev_prefix) - 1)) { - dev_types[i].init_fn(devargs->virtual.drv_name, - devargs->args); + if (!strncmp(driver->name, devargs->virtual.drv_name, + strlen(driver->name))) { + driver->init(devargs->virtual.drv_name, + devargs->args); break; } } - if (i == NUM_DEV_TYPES) { + if (driver == NULL) { rte_panic("no driver found for %s\n", devargs->virtual.drv_name); } diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.h b/lib/librte_eal/common/include/rte_vdev.h similarity index 56% rename from lib/librte_pmd_pcap/rte_eth_pcap.h rename to lib/librte_eal/common/include/rte_vdev.h index 79373c0493..48f71b796c 100644 --- a/lib/librte_pmd_pcap/rte_eth_pcap.h +++ b/lib/librte_eal/common/include/rte_vdev.h @@ -1,23 +1,23 @@ /*- * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * + * Copyright(c) 2014 6WIND S.A. * 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 + * * Neither the name of 6WIND S.A. 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 @@ -31,24 +31,60 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _RTE_ETH_PCAP_H_ -#define _RTE_ETH_PCAP_H_ +#ifndef _RTE_VDEV_H_ +#define _RTE_VDEV_H_ + +/** + * @file + * + * RTE Virtual Devices Interface + * + * This file manages the list of the virtual device drivers. + */ #ifdef __cplusplus extern "C" { #endif -#include -#define RTE_ETH_PCAP_PARAM_NAME "eth_pcap" +#include + +/** Double linked list of virtual device drivers. */ +TAILQ_HEAD(rte_vdev_driver_list, rte_vdev_driver); + +/** + * Initialization function called for each virtual device probing. + */ +typedef int (rte_vdev_init_t)(const char *name, const char *args); + +/** + * A structure describing a virtual device driver. + */ +struct rte_vdev_driver { + TAILQ_ENTRY(rte_vdev_driver) next; /**< Next in list. */ + const char *name; /**< Driver name. */ + rte_vdev_init_t *init; /**< Device init. function. */ +}; /** - * For use by the EAL only. Called as part of EAL init to set up any dummy NICs - * configured on command line. + * Register a virtual device driver. + * + * @param driver + * A pointer to a rte_vdev structure describing the driver + * to be registered. */ -int rte_pmd_pcap_init(const char *name, const char *params); +void rte_eal_vdev_driver_register(struct rte_vdev_driver *driver); + +/** + * Unregister a virtual device driver. + * + * @param driver + * A pointer to a rte_vdev structure describing the driver + * to be unregistered. + */ +void rte_eal_vdev_driver_unregister(struct rte_vdev_driver *driver); #ifdef __cplusplus } #endif -#endif +#endif /* _RTE_VDEV_H_ */ diff --git a/lib/librte_pmd_pcap/Makefile b/lib/librte_pmd_pcap/Makefile index 5218f28885..a8b289fd97 100644 --- a/lib/librte_pmd_pcap/Makefile +++ b/lib/librte_pmd_pcap/Makefile @@ -48,7 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += rte_eth_pcap.c # # Export include files # -SYMLINK-y-include += rte_eth_pcap.h +SYMLINK-y-include += # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_mbuf diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c index fe94a79c50..680dfdce91 100644 --- a/lib/librte_pmd_pcap/rte_eth_pcap.c +++ b/lib/librte_pmd_pcap/rte_eth_pcap.c @@ -40,10 +40,11 @@ #include #include #include +#include #include -#include "rte_eth_pcap.h" +#include #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535 #define RTE_ETH_PCAP_SNAPLEN 4096 @@ -685,8 +686,8 @@ rte_eth_from_pcaps(pcap_t * const rx_queues[], } -int -rte_pmd_pcap_init(const char *name, const char *params) +static int +rte_pmd_pcap_devinit(const char *name, const char *params) { unsigned numa_node, using_dumpers = 0; int ret; @@ -766,3 +767,14 @@ rte_pmd_pcap_init(const char *name, const char *params) } +static struct rte_vdev_driver pmd_pcap_drv = { + .name = "eth_pcap", + .init = rte_pmd_pcap_devinit, +}; + +__attribute__((constructor)) +static void +rte_pmd_pcap_init(void) +{ + rte_eal_vdev_driver_register(&pmd_pcap_drv); +} diff --git a/lib/librte_pmd_ring/rte_eth_ring.c b/lib/librte_pmd_ring/rte_eth_ring.c index 24635f3e9d..cee3ffffee 100644 --- a/lib/librte_pmd_ring/rte_eth_ring.c +++ b/lib/librte_pmd_ring/rte_eth_ring.c @@ -37,6 +37,7 @@ #include #include #include +#include struct ring_queue { struct rte_ring *rng; @@ -382,7 +383,7 @@ rte_eth_ring_pair_attach(const char *name, const unsigned numa_node) } int -rte_pmd_ring_init(const char *name, const char *params) +rte_pmd_ring_devinit(const char *name, const char *params) { RTE_LOG(INFO, PMD, "Initializing pmd_ring for %s\n", name); @@ -395,3 +396,15 @@ rte_pmd_ring_init(const char *name, const char *params) } return 0; } + +static struct rte_vdev_driver pmd_ring_drv = { + .name = "eth_ring", + .init = rte_pmd_ring_devinit, +}; + +__attribute__((constructor)) +static void +rte_pmd_ring_init(void) +{ + rte_eal_vdev_driver_register(&pmd_ring_drv); +} diff --git a/lib/librte_pmd_ring/rte_eth_ring.h b/lib/librte_pmd_ring/rte_eth_ring.h index a222ecb757..b84a29ecc4 100644 --- a/lib/librte_pmd_ring/rte_eth_ring.h +++ b/lib/librte_pmd_ring/rte_eth_ring.h @@ -40,8 +40,6 @@ extern "C" { #include -#define RTE_ETH_RING_PARAM_NAME "eth_ring" - int rte_eth_from_rings(struct rte_ring * const rx_queues[], const unsigned nb_rx_queues, struct rte_ring *const tx_queues[], @@ -52,10 +50,10 @@ int rte_eth_ring_pair_create(const char *name, const unsigned numa_node); int rte_eth_ring_pair_attach(const char *name, const unsigned numa_node); /** - * For use by the EAL only. Called as part of EAL init to set up any dummy NICs + * For use by test apps only. Called as part of EAL init to set up any dummy NICs * configured on command line. */ -int rte_pmd_ring_init(const char *name, const char *params); +int rte_pmd_ring_devinit(const char *name, const char *params); #ifdef __cplusplus } diff --git a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c index bad8dd4264..533aa761bd 100644 --- a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c +++ b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c @@ -688,8 +688,8 @@ err: /*TODO: Support multiple process model */ -int -rte_pmd_xenvirt_init(const char *name, const char *params) +static int +rte_pmd_xenvirt_devinit(const char *name, const char *params) { if (virtio_idx == 0) { if (xenstore_init() != 0) { @@ -704,3 +704,15 @@ rte_pmd_xenvirt_init(const char *name, const char *params) eth_dev_xenvirt_create(name, params, rte_socket_id(), DEV_CREATE); return 0; } + +static struct rte_vdev_driver pmd_xenvirt_drv = { + .name = "eth_xenvirt", + .init = rte_pmd_xenvirt_devinit, +}; + +__attribute__((constructor)) +static void +rte_pmd_xenvirt_init(void) +{ + rte_eal_vdev_driver_register(&pmd_xenvirt_drv); +} diff --git a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.h b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.h index cb1924ad54..acdeb301b0 100644 --- a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.h +++ b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.h @@ -41,14 +41,6 @@ extern "C" { #include #include -#define RTE_ETH_XENVIRT_PARAM_NAME "eth_xenvirt" - -/** - * For use by the EAL only. Called as part of EAL init to set up any dummy NICs - * configured on command line. - */ -int rte_pmd_xenvirt_init(const char *name, const char *params); - /** * Creates mempool for xen virtio PMD. * This function uses memzone_reserve to allocate memory for meta data, -- 2.20.1