Device querying
Subsystems (3)
Re: [PATCH v5 02/21] eal: list acceptable init priorities
In reply to Gaëtan RivetQuoted 108 lines · Gaëtan Rivet
Hi Shreyansh,
Quoted 105 lines · Shreyansh Jain
Quoted 80 lines · Neil Horman
Quoted 70 lines · Gaëtan Rivet
Hello Neil,
Quoted 67 lines · Neil Horman
Quoted 55 lines · Gaetan Rivet
Build a central list to quickly see each used priorities for constructors, allowing to verify that they are both above 100 and in the proper order.
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Neil Horman <[email protected]>Acked-by Shreyansh Jain <[email protected]>--- lib/librte_eal/common/eal_common_log.c | 2 +- lib/librte_eal/common/include/rte_bus.h | 2 +- lib/librte_eal/common/include/rte_common.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-)lib/librte_eal/common/eal_common_log.c +1
-1@@ -260,7 +260,7 @@ static const struct logtype logtype_strings[] = { };/* Logging should be first initializer (before drivers and bus) */ -RTE_INIT_PRIO (rte_log_init,101 ); +RTE_INIT_PRIO (rte_log_init,LOG );static void rte_log_init (void ) {lib/librte_eal/common/include/rte_bus.h +1
-1@@ -325,7 +325,7 @@ enum rte_iova_mode rte_bus_get_iommu_class(void);* The constructor has higher priority than PMD constructors. */ #define RTE_REGISTER_BUS (nm, bus) \ -RTE_INIT_PRIO(businitfn_ ##nm, 110); \ +RTE_INIT_PRIO(businitfn_ ##nm, BUS); \ static void businitfn_ ##nm(void) \ {\ (bus).name = RTE_STR(nm);\lib/librte_eal/common/include/rte_common.h +6
-0@@ -81,6 +81,12 @@ typedef uint16_t unaligned_uint16_t;*/ #define RTE_SET_USED (x) (void)(x) +#define RTE_PRIORITY_LOG 101 +#define RTE_PRIORITY_BUS 110 + +#define RTE_PRIO (prio) \ + RTE_PRIORITY_ ## prio +/** * Run function before main() with low priority. * lib/librte_eal/common/include/rte_common.h static void __attribute__((constructor, used)) func(void) · line 111
Quoted 5 lines
lib/librte_eal/common/include/rte_common.h +1
-1@@ -102,7 +108,7 @@ static void __attribute__((constructor, used)) func(void)* Lowest number is the first to run. */ #define RTE_INIT_PRIO (func, prio) \ -static void __attribute__((constructor(prio), used)) func(void) +static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)It just occured to me, that perhaps you should add a
RTE_PRORITY_LASTpriority, and redefineRTE_INITtoRTE_INIT_PRIO(func, RTE_PRIORITY_LAST)for clarity. I presume that constructors with no explicit priority run last, but the gcc manual doesn't explicitly say that. It would be a heck of a bug to track down if somehow unprioritized constructors ran early.Quoted 9 lines
Quoted 2 lines
Neil
While certainly poorly documented, the behavior is well-defined. I don't see a situation where the bug you describe could arise.
Adding
RTE_PRIORITY_LASTis pretty harmless, but I'm not sure it's justified to add it. If you still think it is useful, I will do it.Quoted 6 lines
It was more just a way to unify the macros is all, probably not important.
Quoted 2 lines
I'd be curious to hear if anyone has had issues of this kind.
I've not had any, but I was suprised to see that the gcc manual didn't explicitly call out the implied priority of unprioritized constructors
I (tried to) looked into the gcc code base. It seems that when priority is not defined,
DEFAULT_INIT_PRIORITY65536, is used.--->8---
gcc/collect2.c---
/* Extractinit_pnumber from ctor/dtor name. */ pri = atoi (name + pos);
return pri ? pri :DEFAULT_INIT_PRIORITY;
--->8---Though, I couldn't find any documentation for this fact - and, I can never be confident about gcc code.
I found one of the ARM compiler (clang) does has a policy for using non-specified priority as lower than specified priority. [1]
Quoted 9 lines
Quoted 3 lines
A specified value for
RTE_PRIORITY_LASTis not a bad option - it would help in keeping the priorities bound without relying on the unknown of priority for unspecified constructors.This is interesting, thanks for looking up the GCC code. Ok, unless someone has a strong reason not to, I will add
RTE_PRIORITY_LAST. Not really convinced about it but not opposed enough either :) .
I concur. It sounds like gcc is safe, but clangs priority scheme makes me want our priorities to be explicit.
Neil
Quoted 5 lines
Regards,
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v5 02/21] eal: list acceptable init priorities
Hello Neil,
Quoted 113 lines · Neil Horman
Quoted 112 lines · Gaëtan Rivet
Hi Shreyansh,
Quoted 108 lines · Shreyansh Jain
Quoted 80 lines · Neil Horman
Quoted 70 lines · Gaëtan Rivet
Hello Neil,
Quoted 67 lines · Neil Horman
Quoted 55 lines · Gaetan Rivet
Build a central list to quickly see each used priorities for constructors, allowing to verify that they are both above 100 and in the proper order.
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Neil Horman <[email protected]>Acked-by Shreyansh Jain <[email protected]>--- lib/librte_eal/common/eal_common_log.c | 2 +- lib/librte_eal/common/include/rte_bus.h | 2 +- lib/librte_eal/common/include/rte_common.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-)lib/librte_eal/common/eal_common_log.c +1
-1@@ -260,7 +260,7 @@ static const struct logtype logtype_strings[] = { };/* Logging should be first initializer (before drivers and bus) */ -RTE_INIT_PRIO (rte_log_init,101 ); +RTE_INIT_PRIO (rte_log_init,LOG );static void rte_log_init (void ) {lib/librte_eal/common/include/rte_bus.h +1
-1@@ -325,7 +325,7 @@ enum rte_iova_mode rte_bus_get_iommu_class(void);* The constructor has higher priority than PMD constructors. */ #define RTE_REGISTER_BUS (nm, bus) \ -RTE_INIT_PRIO(businitfn_ ##nm, 110); \ +RTE_INIT_PRIO(businitfn_ ##nm, BUS); \ static void businitfn_ ##nm(void) \ {\ (bus).name = RTE_STR(nm);\lib/librte_eal/common/include/rte_common.h +6
-0@@ -81,6 +81,12 @@ typedef uint16_t unaligned_uint16_t;*/ #define RTE_SET_USED (x) (void)(x) +#define RTE_PRIORITY_LOG 101 +#define RTE_PRIORITY_BUS 110 + +#define RTE_PRIO (prio) \ + RTE_PRIORITY_ ## prio +/** * Run function before main() with low priority. * lib/librte_eal/common/include/rte_common.h static void __attribute__((constructor, used)) func(void) · line 111
Quoted 5 lines
lib/librte_eal/common/include/rte_common.h +1
-1@@ -102,7 +108,7 @@ static void __attribute__((constructor, used)) func(void)* Lowest number is the first to run. */ #define RTE_INIT_PRIO (func, prio) \ -static void __attribute__((constructor(prio), used)) func(void) +static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)It just occured to me, that perhaps you should add a
RTE_PRORITY_LASTpriority, and redefineRTE_INITtoRTE_INIT_PRIO(func, RTE_PRIORITY_LAST)for clarity. I presume that constructors with no explicit priority run last, but the gcc manual doesn't explicitly say that. It would be a heck of a bug to track down if somehow unprioritized constructors ran early.Quoted 9 lines
Quoted 2 lines
Neil
While certainly poorly documented, the behavior is well-defined. I don't see a situation where the bug you describe could arise.
Adding
RTE_PRIORITY_LASTis pretty harmless, but I'm not sure it's justified to add it. If you still think it is useful, I will do it.Quoted 6 lines
It was more just a way to unify the macros is all, probably not important.
Quoted 2 lines
I'd be curious to hear if anyone has had issues of this kind.
I've not had any, but I was suprised to see that the gcc manual didn't explicitly call out the implied priority of unprioritized constructors
I (tried to) looked into the gcc code base. It seems that when priority is not defined,
DEFAULT_INIT_PRIORITY65536, is used.--->8---
gcc/collect2.c---
/* Extractinit_pnumber from ctor/dtor name. */ pri = atoi (name + pos);
return pri ? pri :DEFAULT_INIT_PRIORITY;
--->8---Though, I couldn't find any documentation for this fact - and, I can never be confident about gcc code.
I found one of the ARM compiler (clang) does has a policy for using non-specified priority as lower than specified priority. [1]
A specified value for
RTE_PRIORITY_LASTis not a bad option - it would help in keeping the priorities bound without relying on the unknown of priority for unspecified constructors.
Quoted 7 lines
Quoted 5 lines
This is interesting, thanks for looking up the GCC code. Ok, unless someone has a strong reason not to, I will add
RTE_PRIORITY_LAST. Not really convinced about it but not opposed enough either :) .I concur. It sounds like gcc is safe, but clangs priority scheme makes me want our priorities to be explicit.
Unless I've misunderstood, clang documentation describes the same behavior as GCC?
Anyway, I've sent a new series with RTE_PRIORITY_LAST:
https://dpdk.org/dev/patchwork/patch/38126/
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v5 02/21] eal: list acceptable init priorities
Quoted 121 lines · Gaëtan Rivet
Hello Neil,
Quoted 118 lines · Neil Horman
Quoted 117 lines · Gaëtan Rivet
Hi Shreyansh,
Quoted 100 lines · Shreyansh Jain
Quoted 80 lines · Neil Horman
Quoted 70 lines · Gaëtan Rivet
Hello Neil,
Quoted 67 lines · Neil Horman
Quoted 55 lines · Gaetan Rivet
Build a central list to quickly see each used priorities for constructors, allowing to verify that they are both above 100 and in the proper order.
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Neil Horman <[email protected]>Acked-by Shreyansh Jain <[email protected]>--- lib/librte_eal/common/eal_common_log.c | 2 +- lib/librte_eal/common/include/rte_bus.h | 2 +- lib/librte_eal/common/include/rte_common.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-)lib/librte_eal/common/eal_common_log.c +1
-1@@ -260,7 +260,7 @@ static const struct logtype logtype_strings[] = { };/* Logging should be first initializer (before drivers and bus) */ -RTE_INIT_PRIO (rte_log_init,101 ); +RTE_INIT_PRIO (rte_log_init,LOG );static void rte_log_init (void ) {lib/librte_eal/common/include/rte_bus.h +1
-1@@ -325,7 +325,7 @@ enum rte_iova_mode rte_bus_get_iommu_class(void);* The constructor has higher priority than PMD constructors. */ #define RTE_REGISTER_BUS (nm, bus) \ -RTE_INIT_PRIO(businitfn_ ##nm, 110); \ +RTE_INIT_PRIO(businitfn_ ##nm, BUS); \ static void businitfn_ ##nm(void) \ {\ (bus).name = RTE_STR(nm);\lib/librte_eal/common/include/rte_common.h +6
-0@@ -81,6 +81,12 @@ typedef uint16_t unaligned_uint16_t;*/ #define RTE_SET_USED (x) (void)(x) +#define RTE_PRIORITY_LOG 101 +#define RTE_PRIORITY_BUS 110 + +#define RTE_PRIO (prio) \ + RTE_PRIORITY_ ## prio +/** * Run function before main() with low priority. * lib/librte_eal/common/include/rte_common.h static void __attribute__((constructor, used)) func(void) · line 111
Quoted 5 lines
lib/librte_eal/common/include/rte_common.h +1
-1@@ -102,7 +108,7 @@ static void __attribute__((constructor, used)) func(void)* Lowest number is the first to run. */ #define RTE_INIT_PRIO (func, prio) \ -static void __attribute__((constructor(prio), used)) func(void) +static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)It just occured to me, that perhaps you should add a
RTE_PRORITY_LASTpriority, and redefineRTE_INITtoRTE_INIT_PRIO(func, RTE_PRIORITY_LAST)for clarity. I presume that constructors with no explicit priority run last, but the gcc manual doesn't explicitly say that. It would be a heck of a bug to track down if somehow unprioritized constructors ran early.Quoted 9 lines
Quoted 2 lines
Neil
While certainly poorly documented, the behavior is well-defined. I don't see a situation where the bug you describe could arise.
Adding
RTE_PRIORITY_LASTis pretty harmless, but I'm not sure it's justified to add it. If you still think it is useful, I will do it.Quoted 6 lines
It was more just a way to unify the macros is all, probably not important.
Quoted 2 lines
I'd be curious to hear if anyone has had issues of this kind.
I've not had any, but I was suprised to see that the gcc manual didn't explicitly call out the implied priority of unprioritized constructors
I (tried to) looked into the gcc code base. It seems that when priority is not defined,
DEFAULT_INIT_PRIORITY65536, is used.--->8---
gcc/collect2.c---
/* Extractinit_pnumber from ctor/dtor name. */ pri = atoi (name + pos);
return pri ? pri :DEFAULT_INIT_PRIORITY;
--->8---Though, I couldn't find any documentation for this fact - and, I can never be confident about gcc code.
Quoted 8 lines
I found one of the ARM compiler (clang) does has a policy for using non-specified priority as lower than specified priority. [1]
A specified value for
RTE_PRIORITY_LASTis not a bad option - it would help in keeping the priorities bound without relying on the unknown of priority for unspecified constructors.This is interesting, thanks for looking up the GCC code. Ok, unless someone has a strong reason not to, I will add
RTE_PRIORITY_LAST. Not really convinced about it but not opposed enough either :) .
Quoted 6 lines
Quoted 2 lines
I concur. It sounds like gcc is safe, but clangs priority scheme makes me want our priorities to be explicit.
Unless I've misunderstood, clang documentation describes the same behavior as GCC?
hmm, from the description above, Shreyansh indicates that the default priority in GCC is 65535, which effectively means "run last". And in clang, the documentation above says regardless of value, unprioritized constructors always run after prioritized constructors.
So, yeah, you're right, the behavior is the same. Though the fact that it took me two emails and typing it out to confirm that to myself, probably suggests spelling it out is best :)
Quoted 4 lines
Anyway, I've sent a new series with
RTE_PRIORITY_LAST:
I think that makes the most sense. Thanks!
Neil
Quoted 4 lines
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v5 3/21 eal: introduce dtor macros
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
lib/librte_eal/common/include/rte_common.h +23 -0
@@ -111,6 +111,29 @@ static void __attribute__((constructor, used)) func(void)static void __attribute__((constructor (RTE_PRIO (prio)), used))func (void )/** +* Run after main() with high priority. +* +* The destructor will be run *before* prioritized destructors. +* +* @param func +* Destructor function name. + */ +#define RTE_FINI (func) \ +static void __attribute__((destructor, used)) func(void) + +/** +* Run after main() with low priority. +* +* @param func +* Destructor function name. +* @param prio +* Priority number must be above 100. +* Lowest number is the last to run. +*/ +#define RTE_FINI_PRIO (func, prio) \ +static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v5 4/21 eal: introduce device class abstraction
In reply to Gaetan Rivet--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 +++++++++++++++ lib/librte_eal/common/include/rte_class.h | 121 +++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 2 + 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
lib/librte_eal/common/Makefile +1 -1
@@ -11,7 +11,7 @@ INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h
lib/librte_eal/common/eal_common_class.c new file +62 -0
62 lines not on this page · raw message
lib/librte_eal/common/include/rte_class.h new file +121 -0
121 lines not on this page · raw message
lib/librte_eal/common/include/rte_common.h +1 -0
@@ -83,6 +83,7 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_CLASS 120#define RTE_PRIO (prio) \ RTE_PRIORITY_ ## prio
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -56,6 +56,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
lib/librte_eal/rte_eal_version.map +2 -0
@@ -218,6 +218,8 @@ EXPERIMENTAL { rte_eal_devargs_insert; rte_eal_devargs_parse; rte_eal_devargs_remove; + rte_class_register; + rte_class_unregister; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v5 5/21 eal/class: register destructor
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 5 +++++ 1 file changed, 5 insertions(+)
lib/librte_eal/common/include/rte_class.h +5 -0
@@ -112,6 +112,11 @@ static void classinitfn_ ##nm(void) \ {\ (cls).name =RTE_STR (nm);\rte_class_register (&cls); \ +} \ +RTE_FINI_PRIO(classfinifn_ ##nm, CLASS); \ +static void classfinifn_ ##nm(void) \ +{ \ + rte_class_unregister(&cls); \ }#ifdef __cplusplus
Signature · 1 line
2.11.0
PATCH v5 6/21 eal/dev: add device iterator interface
In reply to Gaetan RivetA device iterator allows iterating over a set of devices. This set is defined by the two descriptions offered,
* rte_bus
* rte_class
Only one description can be provided, or both. It is not allowed to provide no description at all.
Each layer of abstraction then performs a filter based on the description provided. This filtering allows iterating on their internal set of devices, stopping when a match is valid and returning the current iteration context.
This context allows starting the next iteration from the same point and going forward.
--- lib/librte_eal/common/include/rte_dev.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
lib/librte_eal/common/include/rte_dev.h +47 -0
@@ -263,6 +263,53 @@ __attribute__((used)) = str static const char DRV_EXP_TAG(name, kmod_dep_export)[] \ __attribute__((used)) = str +/** +* Iteration context. +* +* This context carries over the current iteration state. +*/ +struct rte_dev_iterator { +const char *devstr;/**< device string. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< class-related part of device string. */ +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +struct rte_device *device;/**< current position. */ +void *class_device;/**< additional specialized context. */ +}; + +/** +* Device iteration function. +* +* Find the next device matching properties passed in parameters. +* The function takes an additional ``start`` parameter, that is +* used as starting context when relevant. +* +* The function returns the current element in the iteration. +* This return value will potentially be used as a start parameter +* in subsequent calls to the function. +* +* The additional iterator parameter is only there if a specific +* implementation needs additional context. It must not be modified by +* the iteration function itself. +* +* @param start +* Starting iteration context. +* +* @param devstr +* Device description string. +* +* @param it +* Device iterator. +* +* @return +* The address of the current element matching the device description +* string. +*/ +typedef void *(*rte_dev_iterate_t )(const void *start, +const char *devstr, +const struct rte_dev_iterator *it); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v5 7/21 eal/class: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_class.h +1 -0
@@ -30,6 +30,7 @@ TAILQ_HEAD(rte_class_list, rte_class);struct rte_class {TAILQ_ENTRY (rte_class) next;/**< Next device class in linked list */ const char *name;/**< Name of the class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v5 8/21 eal/bus: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_bus.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_bus.h +1 -0
@@ -211,6 +211,7 @@ struct rte_bus {rte_bus_parse_t parse;/**< Parse a device name */ struct rte_bus_conf conf;/**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class;/**< Get iommu class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v5 9/21 eal/dev: implement device iteration initialization
In reply to Gaetan RivetParse a device description.
Split this description in their relevant part for each layers. No dynamic allocation is performed.
--- lib/Makefile | 1 + lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_dev.c | 148 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 24 ++++++ lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 1 + 6 files changed, 176 insertions(+)
lib/Makefile +1 -0
@@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal +DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -18,6 +18,7 @@ CFLAGS += $(WERROR_FLAGS) -O3 LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s +LDLIBS += -lrte_kvargs EXPORT_MAP := ../../rte_eal_version.map
lib/librte_eal/common/eal_common_dev.c +148 -0
160 lines not on this page · raw message
lib/librte_eal/common/include/rte_dev.h +24 -0
@@ -310,6 +310,30 @@ typedef void *(*rte_dev_iterate_t)(const void *start,const char *devstr, const struct rte_dev_iterator *it); +/** +* Initializes a device iterator. +* +* This iterator allows accessing a list of devices matching a criteria. +* The device matching is made among all buses and classes currently registered, +* filtered by the device description given as parameter. +* +* This function will not allocate any memory. It is safe to stop the +* iteration at any moment and let the iterator go out of context. +* +* @param it +* Device iterator handle. +* +* @param str +* Device description string. +* +* @return +* 0 on successful initialization. +* <0 on error. +*/ +__rte_experimental +int +rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -27,6 +27,7 @@ LDLIBS += -lrt ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif +LDLIBS += -lrte_kvargs # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
lib/librte_eal/rte_eal_version.map +1 -0
@@ -220,6 +220,7 @@ EXPERIMENTAL { rte_eal_devargs_remove; rte_class_register; rte_class_unregister; + rte_dev_iterator_init; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v5 10/21 eal/dev: implement device iteration
In reply to Gaetan RivetUse the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists.
--- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+)
lib/librte_eal/common/eal_common_dev.c +168 -0
@@ -20,6 +20,28 @@#include "eal_private.h" +struct dev_next_ctx { +struct rte_dev_iterator *it; +const char *busstr; +const char *clsstr; +}; + +#define CTX (it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) +static int cmp_detached_dev_name (const struct rte_device *dev,const void *_name) {
@@ -355,3 +377,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, }return -rte_errno; } + +static char * +dev_str_sane_copy (const char *str) +{ +size_t end; +char *copy; + + end =strcspn (str,",/" ); +if (str[end] ==',' ) { + copy =strdup (&str[end +1 ]); + }else { +/* '/' or '\0' */ + copy =strdup ("" ); + } +if (copy ==NULL ) { + rte_errno =ENOMEM ; + }else { +char *slash; + + slash =strchr (copy,'/' ); +if (slash !=NULL ) + slash[0 ] ='\0' ; + } +return copy; +} + +static int +class_next_dev_cmp (const struct rte_class *cls, +const void *ctx) +{ +struct rte_dev_iterator *it; +const char *clsstr =NULL ; +void *dev; + +if (cls->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + clsstr =CLSCTX (ctx); + dev = it->class_device; +/* it->clsstr != NULL means a class +* was specified in the devstr. +*/ +if (it->clsstr !=NULL && cls != it->cls) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; + dev = cls->dev_iterate (dev, clsstr, it); + it->class_device = dev; +return dev ==NULL ; +} + +static int +bus_next_dev_cmp (const struct rte_bus *bus, +const void *ctx) +{ +struct rte_device *dev =NULL ; +struct rte_class *cls =NULL ; +struct rte_dev_iterator *it; +const char *busstr =NULL ; + +if (bus->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + busstr =BUSCTX (ctx); + dev = it->device; +/* it->busstr != NULL means a bus +* was specified in the devstr. +*/ +if (it->busstr !=NULL && bus != it->bus) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; +if (it->clsstr ==NULL ) { + dev = bus->dev_iterate (dev, busstr, it); + goto end; + } +/* clsstr != NULL */ +if (dev ==NULL ) { +next_dev_on_bus: + dev = bus->dev_iterate (dev, busstr, it); + it->device = dev; + } +if (dev ==NULL ) +return 1 ; +if (it->cls !=NULL ) + cls =TAILQ_PREV (it->cls, rte_class_list, next); + cls =rte_class_find (cls, class_next_dev_cmp, ctx); +if (cls !=NULL ) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; +return dev ==NULL ; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it) +{ +struct rte_bus *bus =NULL ; +int old_errno = rte_errno; +char *busstr =NULL ; +char *clsstr =NULL ; + + rte_errno =0 ; +if (it->busstr ==NULL && it->clsstr ==NULL ) { +/* Invalid iterator. */ + rte_errno =EINVAL ; +return NULL ; + } +if (it->bus !=NULL ) + bus =TAILQ_PREV (it->bus, rte_bus_list, next); +if (it->busstr !=NULL ) { + busstr =dev_str_sane_copy (it->busstr); +if (busstr ==NULL ) + goto out; + } +if (it->clsstr !=NULL ) { + clsstr =dev_str_sane_copy (it->clsstr); +if (clsstr ==NULL ) + goto out; + } +while ((bus =rte_bus_find (bus, bus_next_dev_cmp, +CTX (it, busstr, clsstr)))) { +if (it->device !=NULL ) { + it->bus = bus; + goto out; + } +if (it->busstr !=NULL || + rte_errno !=0 ) +break ; + } +if (rte_errno ==0 ) + rte_errno = old_errno; +out: +free (busstr); +free (clsstr); +return it->device; +}
lib/librte_eal/common/include/rte_dev.h +26 -0
@@ -334,6 +334,32 @@ __rte_experimentalint rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); +/** +* Iterates on a device iterator. +* +* Generates a new rte_device handle corresponding to the next element +* in the list described in comprehension by the iterator. +* +* The next object is returned, and the iterator is updated. +* +* @param it +* Device iterator handle. +* +* @return +* An rte_device handle if found. +* NULL if an error occurred (rte_errno is set). +* NULL if no device could be found (rte_errno is not set). +*/ +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH (dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus }#endif
lib/librte_eal/rte_eal_version.map +1 -0
@@ -221,6 +221,7 @@ EXPERIMENTAL { rte_class_register; rte_class_unregister; rte_dev_iterator_init; + rte_dev_iterator_next; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v5 11/21 kvargs: add generic string matching callback
In reply to Gaetan RivetThis function can be used as a callback torte_kvargs_process.
This should reduce code duplication.
--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 46 insertions(+)
lib/Makefile +1 -0
@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci
lib/librte_kvargs/rte_kvargs.c +10 -0
@@ -180,3 +180,13 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -strcmp (str, value); +}
lib/librte_kvargs/rte_kvargs.h +28 -0
@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32
@@ -121,6 +123,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* +* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. +*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif
lib/librte_kvargs/rte_kvargs_version.map +7 -0
@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_strcmp; + +} DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v5 12/21 bus/pci: fix find device implementation
In reply to Gaetan RivetIf start is set, and a device before it matches the data passed for comparison, then this first device is returned.
This induces potentially infinite loops.
--- drivers/bus/pci/pci_common.c | 21 ++++++++++++--------- drivers/bus/pci/rte_bus_pci.h | 3 +++ 2 files changed, 15 insertions(+), 9 deletions(-)
drivers/bus/pci/pci_common.c +12 -9
@@ -459,17 +459,20 @@ static struct rte_device * pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { - struct rte_pci_device *dev; + const struct rte_pci_device *pstart; +struct rte_pci_device *pdev; -FOREACH_DEVICE_ON_PCIBUS (dev) { -if (start && &dev->device == start) { - start =NULL ;/* starting point found */ -continue ; - } -if (cmp (&dev->device, data) ==0 ) -return &dev->device; +if (start !=NULL ) { + pstart =RTE_DEV_TO_PCI_CONST (start); + pdev =TAILQ_NEXT (pstart, next); + }else { + pdev =TAILQ_FIRST (&rte_pci_bus.device_list); + } +while (pdev !=NULL ) { +if (cmp (&pdev->device, data) ==0 ) +return &pdev->device; + pdev =TAILQ_NEXT (pdev, next); } -return NULL ; }
drivers/bus/pci/rte_bus_pci.h +3 -0
@@ -74,6 +74,9 @@ struct rte_pci_device {*/ #define RTE_DEV_TO_PCI (ptr) container_of(ptr, struct rte_pci_device, device) +#define RTE_DEV_TO_PCI_CONST (ptr) \ + container_of(ptr, const struct rte_pci_device, device) +#define RTE_ETH_DEV_TO_PCI (eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)/** Any PCI device identifier (vendor, device, ...) */
Signature · 1 line
2.11.0
PATCH v5 13/21 bus/pci: implement device iteration and comparison
In reply to Gaetan Rivet--- drivers/bus/pci/Makefile | 2 +- drivers/bus/pci/pci_common.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/pci/Makefile +1 -1
@@ -50,7 +50,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring -LDLIBS += -lrte_ethdev -lrte_pci +LDLIBS += -lrte_ethdev -lrte_pci -lrte_kvargs include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))
drivers/bus/pci/pci_common.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v5 14/21 bus/pci: add device matching field id
In reply to Gaetan RivetThe PCI bus can now parse a matching field "id" as follows:
"bus=pci,id=0000:00:00.0"
or
"bus=pci,id=00:00.0"
--- drivers/bus/pci/pci_common.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
drivers/bus/pci/pci_common.c +26 -2
@@ -499,21 +499,45 @@ pci_unplug(struct rte_device *dev) }enum pci_params { +RTE_PCI_PARAMS_ID ,RTE_PCI_PARAMS_MAX , };static const char *const pci_params_keys[] = { + [RTE_PCI_PARAMS_ID ] ="id" , [RTE_PCI_PARAMS_MAX ] =NULL , };static int +pci_addr_kv_cmp(const char *key __rte_unused, +const char *value, +void *_addr2) +{ +struct rte_pci_addr _addr1; +struct rte_pci_addr *addr1 = &_addr1; +struct rte_pci_addr *addr2 = _addr2; + +if (rte_pci_addr_parse (value, addr1)) +return -1 ; +return rte_pci_addr_cmp (addr1, addr2); +} + +static int pci_dev_match (const struct rte_device *dev,const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_pci_device *pdev; - (void ) dev; - (void ) kvlist; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + pdev =RTE_DEV_TO_PCI_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"id" , + &pci_addr_kv_cmp, + (void *)(intptr_t )&pdev->addr)) +return 1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v5 15/21 bus/vdev: fix find device implementation
In reply to Gaetan RivetIf start is set and a device before it matches the data, this device is returned.
This induces potentially infinite loops.
--- drivers/bus/vdev/rte_bus_vdev.h | 3 +++ drivers/bus/vdev/vdev.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-)
drivers/bus/vdev/rte_bus_vdev.h +3 -0
@@ -53,6 +53,9 @@ struct rte_vdev_device {#define RTE_DEV_TO_VDEV (ptr) \ container_of(ptr, struct rte_vdev_device, device) +#define RTE_DEV_TO_VDEV_CONST (ptr) \ + container_of(ptr, const struct rte_vdev_device, device) +static inline const char *rte_vdev_device_name (const struct rte_vdev_device *dev) {
drivers/bus/vdev/vdev.c +9 -5
@@ -386,15 +386,19 @@ static struct rte_device * vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { + const struct rte_vdev_device *vstart;struct rte_vdev_device *dev; - TAILQ_FOREACH(dev, &vdev_device_list, next) { -if (start && &dev->device == start) { - start =NULL ; -continue ; - } +if (start !=NULL ) { + vstart =RTE_DEV_TO_VDEV_CONST (start); + dev =TAILQ_NEXT (vstart, next); + }else { + dev =TAILQ_FIRST (&vdev_device_list); + } +while (dev !=NULL ) {if (cmp (&dev->device, data) ==0 )return &dev->device; + dev =TAILQ_NEXT (dev, next); }return NULL ; }
Signature · 1 line
2.11.0
PATCH v5 16/21 bus/vdev: implement device iteration
In reply to Gaetan Rivet--- drivers/bus/vdev/Makefile | 2 +- drivers/bus/vdev/vdev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/vdev/Makefile +1 -1
@@ -19,7 +19,7 @@ LIBABIVER := 1 SRCS-y += vdev.c -LDLIBS += -lrte_eal +LDLIBS += -lrte_eal -lrte_kvargs # # Export include files
drivers/bus/vdev/vdev.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v5 17/21 bus/vdev: add device matching field driver
In reply to Gaetan RivetThe vdev bus parses a field "driver", matching
a vdev driver name with one passed as follows:
"bus=vdev,driver=xxxx"
--- drivers/bus/vdev/Makefile | 1 + drivers/bus/vdev/vdev.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)
drivers/bus/vdev/Makefile +1 -0
@@ -10,6 +10,7 @@ LIB = librte_bus_vdev.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API # versioning export map EXPORT_MAP := rte_bus_vdev_version.map
drivers/bus/vdev/vdev.c +12 -2
@@ -417,10 +417,12 @@ vdev_unplug(struct rte_device *dev) }enum vdev_params { +RTE_VDEV_PARAMS_DRIVER ,RTE_VDEV_PARAMS_MAX , };static const char *const vdev_params_keys[] = { + [RTE_VDEV_PARAMS_DRIVER ] ="driver" , [RTE_VDEV_PARAMS_MAX ] =NULL , };
@@ -429,9 +431,17 @@ vdev_dev_match(const struct rte_device *dev, const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_vdev_device *vdev; - (void ) kvlist; - (void ) dev; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + vdev =RTE_DEV_TO_VDEV_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"driver" , + rte_kvargs_strcmp, + (void *)(intptr_t )vdev->device.driver->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v5 18/21 ethdev: add private generic device iterator
In reply to Gaetan RivetThis iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to librte_ether.
--- lib/librte_ether/Makefile | 1 + lib/librte_ether/eth_private.c | 32 ++++++++++++++++++++++++++++++++ lib/librte_ether/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 lib/librte_ether/eth_private.c create mode 100644 lib/librte_ether/eth_private.h
lib/librte_ether/Makefile +1 -0
@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c
lib/librte_ether/eth_private.c new file +32 -0
@@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan +*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device (const void *_start,rte_eth_cmp_t cmp, +const void *data) +{ +const struct rte_eth_dev *start = _start; +struct rte_eth_dev *edev; +ptrdiff_t idx; + +/* Avoid Undefined Behaviour */ +if (start !=NULL && + (start < &rte_eth_devices[0 ] || + start > &rte_eth_devices[RTE_MAX_ETHPORTS ])) +return NULL ; +if (start !=NULL ) + idx = start - &rte_eth_devices[0 ] +1 ; +else + idx =0 ; +for (; idx <RTE_MAX_ETHPORTS ; idx++) { + edev = &rte_eth_devices[idx]; +if (cmp (edev, data) ==0 ) +return edev; + } +return NULL ; +} +
lib/librte_ether/eth_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan +*/ + +#ifndef _ETH_PRIVATE_H_ +#define _ETH_PRIVATE_H_ + +#include "rte_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic rte_eth_dev comparison function. */ +typedef int (*rte_eth_cmp_t )(const struct rte_eth_dev *,const void *); + +/* Generic rte_eth_dev iterator. */ +struct rte_eth_dev * +eth_find_device (const void *_start,rte_eth_cmp_t cmp, +const void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _ETH_PRIVATE_H_ */
Signature · 1 line
2.11.0
Re: [PATCH v5 18/21] ethdev: add private generic device iterator
Quoted 35 lines · Gaetan Rivet
This iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to
librte_ether.Signed-off-by Gaetan Rivet <[email protected]>--- lib/librte_ether/Makefile | 1 + lib/librte_ether/eth_private.c | 32 ++++++++++++++++++++++++++++++++ lib/librte_ether/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 lib/librte_ether/eth_private.c create mode 100644 lib/librte_ether/eth_private.hlib/librte_ether/Makefile +1
-0@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.clib/librte_ether/eth_private.c new file +0
-0
lib/librte_ether/eth_private.c line 2
Quoted 2 lines
lib/librte_ether/eth_private.c new file +2
-0@@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan
Forgot something here.
lib/librte_ether/eth_private.c line 9
Quoted 7 lines
lib/librte_ether/eth_private.c new file +7
-0+*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device(const void *_start, rte_eth_cmp_t cmp,
_start should be of type (const struct rte_eth_dev *), will update this patch.
Same changes to eth_private.h
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v5 19/21 ethdev: register ether layer as a class
In reply to Gaetan Rivet--- lib/Makefile | 2 +- lib/librte_ether/Makefile | 3 +- lib/librte_ether/rte_class_eth.c | 79 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 lib/librte_ether/rte_class_eth.c
lib/Makefile +1 -1
@@ -23,7 +23,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DEPDIRS-librte_cmdline := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring -DEPDIRS-librte_ether += librte_mbuf +DEPDIRS-librte_ether += librte_mbuf librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += librte_bbdev DEPDIRS-librte_bbdev := librte_eal librte_mempool librte_mbuf DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev
lib/librte_ether/Makefile +2 -1
@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
lib/librte_ether/rte_class_eth.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v5 20/21 ethdev: add device matching field name
In reply to Gaetan RivetThe eth device class can now parse a field name,
matching the eth_dev name with one passed as
"class=eth,name=xxxxxx"
--- lib/librte_ether/rte_class_eth.c | 7 +++++++ 1 file changed, 7 insertions(+)
lib/librte_ether/rte_class_eth.c +7 -0
@@ -15,10 +15,12 @@#include "eth_private.h" enum eth_params { +RTE_ETH_PARAMS_NAME ,RTE_ETH_PARAMS_MAX , };static const char *const eth_params_keys[] = { + [RTE_ETH_PARAMS_NAME ] ="name" , [RTE_ETH_PARAMS_MAX ] =NULL , };
@@ -39,6 +41,7 @@ eth_dev_match(const struct rte_eth_dev *edev, {const struct eth_dev_match_arg *arg = _arg;const struct rte_kvargs *kvlist = arg->kvlist; +struct rte_eth_dev_data *data;if (edev->state ==RTE_ETH_DEV_UNUSED )return -1 ;
@@ -47,6 +50,10 @@ eth_dev_match(const struct rte_eth_dev *edev,if (kvlist ==NULL )/* Empty string matches everything. */ return 0 ; + data = edev->data; +if (rte_kvargs_process (kvlist,"name" , + rte_kvargs_strcmp, data->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v5 21/21 app/testpmd: add show device command
In reply to Gaetan RivetA new interactive command is offered:
show device <device description>
This commands lists all rte_device element matching the device description. e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0
These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
--- app/test-pmd/cmdline.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
app/test-pmd/cmdline.c +52 -0
@@ -6701,6 +6701,57 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) +{ +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) +{ +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device " +"<device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;
@@ -16038,6 +16089,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall,
Signature · 1 line
2.11.0
v6 cover Device querying
In reply to Gaetan RivetThis patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).
* Both rte_bus and rte_class now offer a way to
list their devices and filter the result
using locally defined properties.
* The rte_dev API now has an rte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.
As an example, the "eth" device class is implemented.
Additionally, the device filters for
+ rte_bus_pci
+ rte_bus_vdev
+ rte_class_eth
are implemented and can be used with some
properties each, to show how to extend those.
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
---
v2:
* Reworked the dev_iterate callback to simplify
its implementation.
Now dev_iterate implementation do not need to learn about the intricacies of the rte_dev_iterator. The rte_dev_iterator is managed purely by the rte_dev_iterator_next function. Buses and classes then do not have to care about settings things right.
Additionally, dev_iterate implementations do not have to sanitize their dev string anymore, they are prepared by the rte_dev layer prior, which also reduces the number of dynamic allocations.
v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
using librte_kvargs instead.
* Reversed dependencies of librte_kvargs and
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.
v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
* rte_kvargs now includes rte_eal directly and keeps rte_log.
* added generic string comparison function to rte_kvargs, as some kind of comparison should probably be shared by many layers.
v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private generic rte_eth_dev iterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.
v6:
* Rebased on master
* Introduce RTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.
Gaetan Rivet (22):
kvargs: build before EAL
eal: list acceptable init priorities
eal: add last init priority
eal: introduce dtor macros
eal: introduce device class abstraction eal/class: register destructor
eal/dev: add device iterator interface eal/class: add device iteration
eal/bus: add device iteration
eal/dev: implement device iteration initialization eal/dev: implement device iteration
kvargs: add generic string matching callback bus/pci: fix find device implementation bus/pci: implement device iteration and comparison bus/pci: add device matching field id bus/vdev: fix find device implementation bus/vdev: implement device iteration bus/vdev: add device matching field driver
ethdev: add private generic device iterator
ethdev: register ether layer as a class
ethdev: add device matching field name app/testpmd: add show device command
app/test-pmd/cmdline.c | 52 ++++
drivers/bus/pci/Makefile | 2 +-
drivers/bus/pci/pci_common.c | 87 +++++-
drivers/bus/pci/rte_bus_pci.h | 3 +
drivers/bus/vdev/Makefile | 3 +-
drivers/bus/vdev/rte_bus_vdev.h | 3 +
drivers/bus/vdev/vdev.c | 66 ++++-
lib/Makefile | 7 +-
lib/librte_eal/bsdapp/eal/Makefile | 2 +
lib/librte_eal/common/Makefile | 4 +-
lib/librte_eal/common/eal_common_class.c | 62 ++++
lib/librte_eal/common/eal_common_dev.c | 316 +++++++++++++++++++++
lib/librte_eal/common/eal_common_log.c | 2 +-
lib/librte_eal/common/include/rte_bus.h | 3 +-
lib/librte_eal/common/include/rte_class.h | 127 +++++++++
lib/librte_eal/common/include/rte_common.h | 53 +++-
lib/librte_eal/common/include/rte_dev.h | 97 +++++++
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/rte_eal_version.map | 4 +
lib/librte_ether/Makefile | 4 +-
lib/librte_ether/eth_private.c | 31 ++
lib/librte_ether/eth_private.h | 26 ++
lib/librte_ether/rte_class_eth.c | 86 ++++++
lib/librte_kvargs/Makefile | 3 +-
lib/librte_kvargs/rte_kvargs.c | 12 +-
lib/librte_kvargs/rte_kvargs.h | 28 ++
lib/librte_kvargs/rte_kvargs_version.map | 7 +
.../include => librte_kvargs}/rte_string_fns.h | 0
28 files changed, 1055 insertions(+), 37 deletions(-)
create mode 100644 lib/librte_eal/common/eal_common_class.c
create mode 100644 lib/librte_eal/common/include/rte_class.h
create mode 100644 lib/librte_ether/eth_private.c
create mode 100644 lib/librte_ether/eth_private.h
create mode 100644 lib/librte_ether/rte_class_eth.c
rename lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h (100%)Signature · 1 line
2.11.0
PATCH v6 1/22 kvargs: build before EAL
---
lib/Makefile | 3 +--
lib/librte_eal/common/Makefile | 2 +-
lib/librte_kvargs/Makefile | 3 ++-
lib/librte_kvargs/rte_kvargs.c | 2 +-
lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h | 0
5 files changed, 5 insertions(+), 5 deletions(-)
rename lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h (100%)lib/Makefile +1 -2
@@ -4,6 +4,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat +DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
@@ -71,8 +72,6 @@ DEPDIRS-librte_flow_classify := librte_net librte_table librte_acl DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DEPDIRS-librte_sched := librte_eal librte_mempool librte_mbuf librte_net DEPDIRS-librte_sched += librte_timer -DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs -DEPDIRS-librte_kvargs := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += librte_distributor DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ether DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
lib/librte_eal/common/Makefile +1 -1
@@ -9,7 +9,7 @@ INC += rte_errno.h rte_launch.h rte_lcore.h INC += rte_log.h rte_memory.h rte_memzone.h INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h -INC += rte_string_fns.h rte_version.h +INC += rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
lib/librte_kvargs/Makefile +2 -1
@@ -37,7 +37,7 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_kvargs.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -LDLIBS += -lrte_eal +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include EXPORT_MAP := rte_kvargs_version.map
@@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := rte_kvargs.c # install includes INCS := rte_kvargs.h +INCS += rte_string_fns.h SYMLINK-$(CONFIG_RTE_LIBRTE_KVARGS)-include := $(INCS) include $(RTE_SDK)/mk/rte.lib.mk
lib/librte_kvargs/rte_kvargs.c +1 -1
@@ -7,8 +7,8 @@#include <stdlib.h> #include <rte_log.h> -#include <rte_string_fns.h> +#include "rte_string_fns.h" #include "rte_kvargs.h" /*
lib/librte_kvargs/rte_string_fns.h renamed from lib/librte_eal/common/include/rte_string_fns.h +0 -0
Signature · 1 line
2.11.0
PATCH v6 2/22 eal: list acceptable init priorities
In reply to Gaetan RivetBuild a central list to quickly see each used priorities for constructors, allowing to verify that they are both above 100 and in the proper order.
--- lib/librte_eal/common/eal_common_log.c | 2 +- lib/librte_eal/common/include/rte_bus.h | 2 +- lib/librte_eal/common/include/rte_common.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-)
lib/librte_eal/common/eal_common_log.c +1 -1
@@ -260,7 +260,7 @@ static const struct logtype logtype_strings[] = { };/* Logging should be first initializer (before drivers and bus) */ -RTE_INIT_PRIO (rte_log_init,101 ); +RTE_INIT_PRIO (rte_log_init,LOG );static void rte_log_init (void ) {
lib/librte_eal/common/include/rte_bus.h +1 -1
@@ -325,7 +325,7 @@ enum rte_iova_mode rte_bus_get_iommu_class(void);* The constructor has higher priority than PMD constructors. */ #define RTE_REGISTER_BUS (nm, bus) \ -RTE_INIT_PRIO(businitfn_ ##nm, 110); \ +RTE_INIT_PRIO(businitfn_ ##nm, BUS); \ static void businitfn_ ##nm(void) \ {\ (bus).name = RTE_STR(nm);\
lib/librte_eal/common/include/rte_common.h +7 -1
@@ -81,6 +81,12 @@ typedef uint16_t unaligned_uint16_t;*/ #define RTE_SET_USED (x) (void)(x) +#define RTE_PRIORITY_LOG 101 +#define RTE_PRIORITY_BUS 110 + +#define RTE_PRIO (prio) \ + RTE_PRIORITY_ ## prio +/** * Run function before main() with low priority. *
@@ -102,7 +108,7 @@ static void __attribute__((constructor, used)) func(void)* Lowest number is the first to run. */ #define RTE_INIT_PRIO (func, prio) \ -static void __attribute__((constructor(prio), used)) func(void) +static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)/** * Force a function to be inlined
Signature · 1 line
2.11.0
PATCH v6 3/22 eal: add last init priority
In reply to Gaetan RivetAdd the priority RTE_PRIORITY_LAST, used for initialization routines meant to be run after all other constructors.
This priority becomes the default priority for all DPDK constructors.
--- lib/librte_eal/common/include/rte_common.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
lib/librte_eal/common/include/rte_common.h +12 -11
@@ -83,22 +83,12 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \ RTE_PRIORITY_ ## prio/** -* Run function before main() with low priority. -* -* The constructor will be run after prioritized constructors. -* -* @param func -* Constructor function. -*/ -#define RTE_INIT (func) \ -static void __attribute__((constructor, used)) func(void) - -/** * Run function before main() with high priority. * * @param func
@@ -111,6 +101,17 @@ static void __attribute__((constructor, used)) func(void)static void __attribute__((constructor (RTE_PRIO (prio)), used))func (void )/** +* Run function before main() with low priority. +* +* The constructor will be run after prioritized constructors. +* +* @param func +* Constructor function. + */ +#define RTE_INIT (func) \ + RTE_INIT_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v6 4/22 eal: introduce dtor macros
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
lib/librte_eal/common/include/rte_common.h +23 -0
@@ -112,6 +112,29 @@ static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)RTE_INIT_PRIO (func,LAST )/** +* Run after main() with low priority. +* +* @param func +* Destructor function name. +* @param prio +* Priority number must be above 100. +* Lowest number is the last to run. + */ +#define RTE_FINI_PRIO (func, prio) \ +static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void) + +/** +* Run after main() with high priority. +* +* The destructor will be run *before* prioritized destructors. +* +* @param func +* Destructor function name. +*/ +#define RTE_FINI (func) \ + RTE_FINI_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v6 5/22 eal: introduce device class abstraction
In reply to Gaetan Rivet--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 +++++++++++++++ lib/librte_eal/common/include/rte_class.h | 121 +++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 2 + 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -51,6 +51,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
lib/librte_eal/common/Makefile +1 -1
@@ -11,7 +11,7 @@ INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h
lib/librte_eal/common/eal_common_class.c new file +62 -0
62 lines not on this page · raw message
lib/librte_eal/common/include/rte_class.h new file +121 -0
121 lines not on this page · raw message
lib/librte_eal/common/include/rte_common.h +1 -0
@@ -83,6 +83,7 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_CLASS 120#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -59,6 +59,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
lib/librte_eal/rte_eal_version.map +2 -0
@@ -221,6 +221,8 @@ EXPERIMENTAL { rte_eal_devargs_insert; rte_eal_devargs_parse; rte_eal_devargs_remove; + rte_class_register; + rte_class_unregister; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v6 6/22 eal/class: register destructor
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 5 +++++ 1 file changed, 5 insertions(+)
lib/librte_eal/common/include/rte_class.h +5 -0
@@ -112,6 +112,11 @@ static void classinitfn_ ##nm(void) \ {\ (cls).name =RTE_STR (nm);\rte_class_register (&cls); \ +} \ +RTE_FINI_PRIO(classfinifn_ ##nm, CLASS); \ +static void classfinifn_ ##nm(void) \ +{ \ + rte_class_unregister(&cls); \ }#ifdef __cplusplus
Signature · 1 line
2.11.0
PATCH v6 7/22 eal/dev: add device iterator interface
In reply to Gaetan RivetA device iterator allows iterating over a set of devices. This set is defined by the two descriptions offered,
* rte_bus
* rte_class
Only one description can be provided, or both. It is not allowed to provide no description at all.
Each layer of abstraction then performs a filter based on the description provided. This filtering allows iterating on their internal set of devices, stopping when a match is valid and returning the current iteration context.
This context allows starting the next iteration from the same point and going forward.
--- lib/librte_eal/common/include/rte_dev.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
lib/librte_eal/common/include/rte_dev.h +47 -0
@@ -282,6 +282,53 @@ __attribute__((used)) = str static const char DRV_EXP_TAG(name, kmod_dep_export)[] \ __attribute__((used)) = str +/** +* Iteration context. +* +* This context carries over the current iteration state. +*/ +struct rte_dev_iterator { +const char *devstr;/**< device string. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< class-related part of device string. */ +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +struct rte_device *device;/**< current position. */ +void *class_device;/**< additional specialized context. */ +}; + +/** +* Device iteration function. +* +* Find the next device matching properties passed in parameters. +* The function takes an additional ``start`` parameter, that is +* used as starting context when relevant. +* +* The function returns the current element in the iteration. +* This return value will potentially be used as a start parameter +* in subsequent calls to the function. +* +* The additional iterator parameter is only there if a specific +* implementation needs additional context. It must not be modified by +* the iteration function itself. +* +* @param start +* Starting iteration context. +* +* @param devstr +* Device description string. +* +* @param it +* Device iterator. +* +* @return +* The address of the current element matching the device description +* string. +*/ +typedef void *(*rte_dev_iterate_t )(const void *start, +const char *devstr, +const struct rte_dev_iterator *it); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v6 8/22 eal/class: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_class.h +1 -0
@@ -30,6 +30,7 @@ TAILQ_HEAD(rte_class_list, rte_class);struct rte_class {TAILQ_ENTRY (rte_class) next;/**< Next device class in linked list */ const char *name;/**< Name of the class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v6 9/22 eal/bus: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_bus.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_bus.h +1 -0
@@ -211,6 +211,7 @@ struct rte_bus {rte_bus_parse_t parse;/**< Parse a device name */ struct rte_bus_conf conf;/**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class;/**< Get iommu class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v6 10/22 eal/dev: implement device iteration initialization
In reply to Gaetan RivetParse a device description.
Split this description in their relevant part for each layers. No dynamic allocation is performed.
--- lib/Makefile | 1 + lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_dev.c | 148 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 24 ++++++ lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 1 + 6 files changed, 176 insertions(+)
lib/Makefile +1 -0
@@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal +DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -18,6 +18,7 @@ CFLAGS += $(WERROR_FLAGS) -O3 LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s +LDLIBS += -lrte_kvargs EXPORT_MAP := ../../rte_eal_version.map
lib/librte_eal/common/eal_common_dev.c +148 -0
160 lines not on this page · raw message
lib/librte_eal/common/include/rte_dev.h +24 -0
@@ -329,6 +329,30 @@ typedef void *(*rte_dev_iterate_t)(const void *start,const char *devstr, const struct rte_dev_iterator *it); +/** +* Initializes a device iterator. +* +* This iterator allows accessing a list of devices matching a criteria. +* The device matching is made among all buses and classes currently registered, +* filtered by the device description given as parameter. +* +* This function will not allocate any memory. It is safe to stop the +* iteration at any moment and let the iterator go out of context. +* +* @param it +* Device iterator handle. +* +* @param str +* Device description string. +* +* @return +* 0 on successful initialization. +* <0 on error. +*/ +__rte_experimental +int +rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -27,6 +27,7 @@ LDLIBS += -lrt ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif +LDLIBS += -lrte_kvargs # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
lib/librte_eal/rte_eal_version.map +1 -0
@@ -223,6 +223,7 @@ EXPERIMENTAL { rte_eal_devargs_remove; rte_class_register; rte_class_unregister; + rte_dev_iterator_init; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v6 11/22 eal/dev: implement device iteration
In reply to Gaetan RivetUse the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists.
--- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+)
lib/librte_eal/common/eal_common_dev.c +168 -0
@@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs;/* spinlock for device callbacks */ static rte_spinlock_t dev_event_lock =RTE_SPINLOCK_INITIALIZER ; +struct dev_next_ctx { +struct rte_dev_iterator *it; +const char *busstr; +const char *clsstr; +}; + +#define CTX (it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) +static int cmp_detached_dev_name (const struct rte_device *dev,const void *_name) {
@@ -516,3 +538,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, }return -rte_errno; } + +static char * +dev_str_sane_copy (const char *str) +{ +size_t end; +char *copy; + + end =strcspn (str,",/" ); +if (str[end] ==',' ) { + copy =strdup (&str[end +1 ]); + }else { +/* '/' or '\0' */ + copy =strdup ("" ); + } +if (copy ==NULL ) { + rte_errno =ENOMEM ; + }else { +char *slash; + + slash =strchr (copy,'/' ); +if (slash !=NULL ) + slash[0 ] ='\0' ; + } +return copy; +} + +static int +class_next_dev_cmp (const struct rte_class *cls, +const void *ctx) +{ +struct rte_dev_iterator *it; +const char *clsstr =NULL ; +void *dev; + +if (cls->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + clsstr =CLSCTX (ctx); + dev = it->class_device; +/* it->clsstr != NULL means a class +* was specified in the devstr. +*/ +if (it->clsstr !=NULL && cls != it->cls) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; + dev = cls->dev_iterate (dev, clsstr, it); + it->class_device = dev; +return dev ==NULL ; +} + +static int +bus_next_dev_cmp (const struct rte_bus *bus, +const void *ctx) +{ +struct rte_device *dev =NULL ; +struct rte_class *cls =NULL ; +struct rte_dev_iterator *it; +const char *busstr =NULL ; + +if (bus->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + busstr =BUSCTX (ctx); + dev = it->device; +/* it->busstr != NULL means a bus +* was specified in the devstr. +*/ +if (it->busstr !=NULL && bus != it->bus) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; +if (it->clsstr ==NULL ) { + dev = bus->dev_iterate (dev, busstr, it); + goto end; + } +/* clsstr != NULL */ +if (dev ==NULL ) { +next_dev_on_bus: + dev = bus->dev_iterate (dev, busstr, it); + it->device = dev; + } +if (dev ==NULL ) +return 1 ; +if (it->cls !=NULL ) + cls =TAILQ_PREV (it->cls, rte_class_list, next); + cls =rte_class_find (cls, class_next_dev_cmp, ctx); +if (cls !=NULL ) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; +return dev ==NULL ; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it) +{ +struct rte_bus *bus =NULL ; +int old_errno = rte_errno; +char *busstr =NULL ; +char *clsstr =NULL ; + + rte_errno =0 ; +if (it->busstr ==NULL && it->clsstr ==NULL ) { +/* Invalid iterator. */ + rte_errno =EINVAL ; +return NULL ; + } +if (it->bus !=NULL ) + bus =TAILQ_PREV (it->bus, rte_bus_list, next); +if (it->busstr !=NULL ) { + busstr =dev_str_sane_copy (it->busstr); +if (busstr ==NULL ) + goto out; + } +if (it->clsstr !=NULL ) { + clsstr =dev_str_sane_copy (it->clsstr); +if (clsstr ==NULL ) + goto out; + } +while ((bus =rte_bus_find (bus, bus_next_dev_cmp, +CTX (it, busstr, clsstr)))) { +if (it->device !=NULL ) { + it->bus = bus; + goto out; + } +if (it->busstr !=NULL || + rte_errno !=0 ) +break ; + } +if (rte_errno ==0 ) + rte_errno = old_errno; +out: +free (busstr); +free (clsstr); +return it->device; +}
lib/librte_eal/common/include/rte_dev.h +26 -0
@@ -353,6 +353,32 @@ __rte_experimentalint rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); +/** +* Iterates on a device iterator. +* +* Generates a new rte_device handle corresponding to the next element +* in the list described in comprehension by the iterator. +* +* The next object is returned, and the iterator is updated. +* +* @param it +* Device iterator handle. +* +* @return +* An rte_device handle if found. +* NULL if an error occurred (rte_errno is set). +* NULL if no device could be found (rte_errno is not set). +*/ +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH (dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus }#endif
lib/librte_eal/rte_eal_version.map +1 -0
@@ -224,6 +224,7 @@ EXPERIMENTAL { rte_class_register; rte_class_unregister; rte_dev_iterator_init; + rte_dev_iterator_next; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v6 12/22 kvargs: add generic string matching callback
In reply to Gaetan RivetThis function can be used as a callback torte_kvargs_process.
This should reduce code duplication.
--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 46 insertions(+)
lib/Makefile +1 -0
@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci
lib/librte_kvargs/rte_kvargs.c +10 -0
@@ -180,3 +180,13 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -strcmp (str, value); +}
lib/librte_kvargs/rte_kvargs.h +28 -0
@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32
@@ -121,6 +123,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* +* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. +*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif
lib/librte_kvargs/rte_kvargs_version.map +7 -0
@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_strcmp; + +} DPDK_2.0;
Signature · 1 line
2.11.0
Re: [PATCH v6 12/22] kvargs: add generic string matching callback
Quoted 72 lines · Gaetan Rivet
This function can be used as a callback to
rte_kvargs_process.This should reduce code duplication.
Signed-off-by Gaetan Rivet <[email protected]>--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 46 insertions(+)lib/Makefile +1
-0@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pcilib/librte_kvargs/rte_kvargs.c +10
-0@@ -180,3 +180,13 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -strcmp (str, value); +}lib/librte_kvargs/rte_kvargs.h +14
-0@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32@@ -121,6 +123,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +*
lib/librte_kvargs/rte_kvargs.h int rte_kvargs_process(const struct rte_kvargs *kvlist, · line 147
Quoted 10 lines
lib/librte_kvargs/rte_kvargs.h +10
-0+* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one.
Is the above comment valid?
lib/librte_kvargs/rte_kvargs.h int rte_kvargs_process(const struct rte_kvargs *kvlist, · line 148
Quoted 1 line
lib/librte_kvargs/rte_kvargs.h +1
-0+return -strcmp (str, value);
In case a negative is returned (when key opaque < value), this function would return a positive. So, effectively you have only reversed the values. Is that the expectation?
In 21/22:
--->8--- rte_kvargs_process ---
for (i = 0; i < kvlist->count; i++) {
pair = &kvlist->pairs[i];
if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
return -1;
}
}--->8---
This would only cause the opaque < value case to continue ahead but not the reverse.
Quoted 23 lines
lib/librte_kvargs/rte_kvargs.h +4
-0+*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif lib/librte_kvargs/rte_kvargs_version.map +7
-0@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_strcmp; + +} DPDK_2.0;
Re: [PATCH v6 12/22] kvargs: add generic string matching callback
Quoted 97 lines · Shreyansh Jain
Quoted 67 lines · Gaetan Rivet
This function can be used as a callback to
rte_kvargs_process.This should reduce code duplication.
Signed-off-by Gaetan Rivet <[email protected]>--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 46 insertions(+)lib/Makefile +1
-0@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pcilib/librte_kvargs/rte_kvargs.c +10
-0@@ -180,3 +180,13 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -strcmp (str, value); +}lib/librte_kvargs/rte_kvargs.h +14
-0@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32@@ -121,6 +123,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* lib/librte_kvargs/rte_kvargs.h int rte_kvargs_process(const struct rte_kvargs *kvlist, · line 146
Quoted 10 lines
lib/librte_kvargs/rte_kvargs.h +10
-0+* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. Is the above comment valid?
lib/librte_kvargs/rte_kvargs.h int rte_kvargs_process(const struct rte_kvargs *kvlist, · line 147
Quoted 1 line
lib/librte_kvargs/rte_kvargs.h +1
-0+return -strcmp (str, value);In case a negative is returned (when key opaque < value), this function would return a positive. So, effectively you have only reversed the values. Is that the expectation?
In 21/22:
--->8---
rte_kvargs_process---for (i = 0; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; if (key_match == NULL || strcmp(pair->key, key_match) == 0) { if ((*handler)(pair->key, pair->value, opaque_arg) < 0) return -1; } }
Quoted 5 lines
--->8---
This would only cause the opaque < value case to continue ahead but not the reverse.
Ah! yes, you're right of course.
This is not the expectation, I will fix this.
Thanks,
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v6 13/22 bus/pci: fix find device implementation
In reply to Gaetan RivetIf start is set, and a device before it matches the data passed for comparison, then this first device is returned.
This induces potentially infinite loops.
--- drivers/bus/pci/pci_common.c | 21 ++++++++++++--------- drivers/bus/pci/rte_bus_pci.h | 3 +++ 2 files changed, 15 insertions(+), 9 deletions(-)
drivers/bus/pci/pci_common.c +12 -9
@@ -459,17 +459,20 @@ static struct rte_device * pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { - struct rte_pci_device *dev; + const struct rte_pci_device *pstart; +struct rte_pci_device *pdev; -FOREACH_DEVICE_ON_PCIBUS (dev) { -if (start && &dev->device == start) { - start =NULL ;/* starting point found */ -continue ; - } -if (cmp (&dev->device, data) ==0 ) -return &dev->device; +if (start !=NULL ) { + pstart =RTE_DEV_TO_PCI_CONST (start); + pdev =TAILQ_NEXT (pstart, next); + }else { + pdev =TAILQ_FIRST (&rte_pci_bus.device_list); + } +while (pdev !=NULL ) { +if (cmp (&pdev->device, data) ==0 ) +return &pdev->device; + pdev =TAILQ_NEXT (pdev, next); } -return NULL ; }
drivers/bus/pci/rte_bus_pci.h +3 -0
@@ -74,6 +74,9 @@ struct rte_pci_device {*/ #define RTE_DEV_TO_PCI (ptr) container_of(ptr, struct rte_pci_device, device) +#define RTE_DEV_TO_PCI_CONST (ptr) \ + container_of(ptr, const struct rte_pci_device, device) +#define RTE_ETH_DEV_TO_PCI (eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)/** Any PCI device identifier (vendor, device, ...) */
Signature · 1 line
2.11.0
PATCH v6 14/22 bus/pci: implement device iteration and comparison
In reply to Gaetan Rivet--- drivers/bus/pci/Makefile | 2 +- drivers/bus/pci/pci_common.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/pci/Makefile +1 -1
@@ -53,7 +53,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring -LDLIBS += -lrte_ethdev -lrte_pci +LDLIBS += -lrte_ethdev -lrte_pci -lrte_kvargs include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))
drivers/bus/pci/pci_common.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v6 15/22 bus/pci: add device matching field id
In reply to Gaetan RivetThe PCI bus can now parse a matching field "id" as follows:
"bus=pci,id=0000:00:00.0"
or
"bus=pci,id=00:00.0"
--- drivers/bus/pci/pci_common.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
drivers/bus/pci/pci_common.c +26 -2
@@ -499,21 +499,45 @@ pci_unplug(struct rte_device *dev) }enum pci_params { +RTE_PCI_PARAMS_ID ,RTE_PCI_PARAMS_MAX , };static const char *const pci_params_keys[] = { + [RTE_PCI_PARAMS_ID ] ="id" , [RTE_PCI_PARAMS_MAX ] =NULL , };static int +pci_addr_kv_cmp(const char *key __rte_unused, +const char *value, +void *_addr2) +{ +struct rte_pci_addr _addr1; +struct rte_pci_addr *addr1 = &_addr1; +struct rte_pci_addr *addr2 = _addr2; + +if (rte_pci_addr_parse (value, addr1)) +return -1 ; +return rte_pci_addr_cmp (addr1, addr2); +} + +static int pci_dev_match (const struct rte_device *dev,const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_pci_device *pdev; - (void ) dev; - (void ) kvlist; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + pdev =RTE_DEV_TO_PCI_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"id" , + &pci_addr_kv_cmp, + (void *)(intptr_t )&pdev->addr)) +return 1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v6 16/22 bus/vdev: fix find device implementation
In reply to Gaetan RivetIf start is set and a device before it matches the data, this device is returned.
This induces potentially infinite loops.
--- drivers/bus/vdev/rte_bus_vdev.h | 3 +++ drivers/bus/vdev/vdev.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-)
drivers/bus/vdev/rte_bus_vdev.h +3 -0
@@ -25,6 +25,9 @@ struct rte_vdev_device {#define RTE_DEV_TO_VDEV (ptr) \ container_of(ptr, struct rte_vdev_device, device) +#define RTE_DEV_TO_VDEV_CONST (ptr) \ + container_of(ptr, const struct rte_vdev_device, device) +static inline const char *rte_vdev_device_name (const struct rte_vdev_device *dev) {
drivers/bus/vdev/vdev.c +9 -5
@@ -358,15 +358,19 @@ static struct rte_device * vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { + const struct rte_vdev_device *vstart;struct rte_vdev_device *dev; - TAILQ_FOREACH(dev, &vdev_device_list, next) { -if (start && &dev->device == start) { - start =NULL ; -continue ; - } +if (start !=NULL ) { + vstart =RTE_DEV_TO_VDEV_CONST (start); + dev =TAILQ_NEXT (vstart, next); + }else { + dev =TAILQ_FIRST (&vdev_device_list); + } +while (dev !=NULL ) {if (cmp (&dev->device, data) ==0 )return &dev->device; + dev =TAILQ_NEXT (dev, next); }return NULL ; }
Signature · 1 line
2.11.0
PATCH v6 17/22 bus/vdev: implement device iteration
In reply to Gaetan Rivet--- drivers/bus/vdev/Makefile | 2 +- drivers/bus/vdev/vdev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/vdev/Makefile +1 -1
@@ -19,7 +19,7 @@ LIBABIVER := 1 SRCS-y += vdev.c -LDLIBS += -lrte_eal +LDLIBS += -lrte_eal -lrte_kvargs # # Export include files
drivers/bus/vdev/vdev.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v6 18/22 bus/vdev: add device matching field driver
In reply to Gaetan RivetThe vdev bus parses a field "driver", matching
a vdev driver name with one passed as follows:
"bus=vdev,driver=xxxx"
--- drivers/bus/vdev/Makefile | 1 + drivers/bus/vdev/vdev.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)
drivers/bus/vdev/Makefile +1 -0
@@ -10,6 +10,7 @@ LIB = librte_bus_vdev.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API # versioning export map EXPORT_MAP := rte_bus_vdev_version.map
drivers/bus/vdev/vdev.c +12 -2
@@ -389,10 +389,12 @@ vdev_unplug(struct rte_device *dev) }enum vdev_params { +RTE_VDEV_PARAMS_DRIVER ,RTE_VDEV_PARAMS_MAX , };static const char *const vdev_params_keys[] = { + [RTE_VDEV_PARAMS_DRIVER ] ="driver" , [RTE_VDEV_PARAMS_MAX ] =NULL , };
@@ -401,9 +403,17 @@ vdev_dev_match(const struct rte_device *dev, const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_vdev_device *vdev; - (void ) kvlist; - (void ) dev; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + vdev =RTE_DEV_TO_VDEV_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"driver" , + rte_kvargs_strcmp, + (void *)(intptr_t )vdev->device.driver->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v6 19/22 ethdev: add private generic device iterator
In reply to Gaetan RivetThis iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to librte_ether.
--- lib/librte_ether/Makefile | 1 + lib/librte_ether/eth_private.c | 31 +++++++++++++++++++++++++++++++ lib/librte_ether/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 lib/librte_ether/eth_private.c create mode 100644 lib/librte_ether/eth_private.h
lib/librte_ether/Makefile +1 -0
@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c
lib/librte_ether/eth_private.c new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *start,rte_eth_cmp_t cmp, +const void *data) +{ +struct rte_eth_dev *edev; +ptrdiff_t idx; + +/* Avoid Undefined Behaviour */ +if (start !=NULL && + (start < &rte_eth_devices[0 ] || + start > &rte_eth_devices[RTE_MAX_ETHPORTS ])) +return NULL ; +if (start !=NULL ) + idx = start - &rte_eth_devices[0 ] +1 ; +else + idx =0 ; +for (; idx <RTE_MAX_ETHPORTS ; idx++) { + edev = &rte_eth_devices[idx]; +if (cmp (edev, data) ==0 ) +return edev; + } +return NULL ; +} +
lib/librte_ether/eth_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#ifndef _RTE_ETH_PRIVATE_H_ +#define _RTE_ETH_PRIVATE_H_ + +#include "rte_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic rte_eth_dev comparison function. */ +typedef int (*rte_eth_cmp_t )(const struct rte_eth_dev *,const void *); + +/* Generic rte_eth_dev iterator. */ +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *_start,rte_eth_cmp_t cmp, +const void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ETH_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v6 20/22 ethdev: register ether layer as a class
In reply to Gaetan Rivet--- lib/Makefile | 2 +- lib/librte_ether/Makefile | 3 +- lib/librte_ether/rte_class_eth.c | 79 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 lib/librte_ether/rte_class_eth.c
lib/Makefile +1 -1
@@ -23,7 +23,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DEPDIRS-librte_cmdline := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring -DEPDIRS-librte_ether += librte_mbuf +DEPDIRS-librte_ether += librte_mbuf librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += librte_bbdev DEPDIRS-librte_bbdev := librte_eal librte_mempool librte_mbuf DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev
lib/librte_ether/Makefile +2 -1
@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
lib/librte_ether/rte_class_eth.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v6 21/22 ethdev: add device matching field name
In reply to Gaetan RivetThe eth device class can now parse a field name,
matching the eth_dev name with one passed as
"class=eth,name=xxxxxx"
--- lib/librte_ether/rte_class_eth.c | 7 +++++++ 1 file changed, 7 insertions(+)
lib/librte_ether/rte_class_eth.c +7 -0
@@ -15,10 +15,12 @@#include "eth_private.h" enum eth_params { +RTE_ETH_PARAMS_NAME ,RTE_ETH_PARAMS_MAX , };static const char *const eth_params_keys[] = { + [RTE_ETH_PARAMS_NAME ] ="name" , [RTE_ETH_PARAMS_MAX ] =NULL , };
@@ -39,6 +41,7 @@ eth_dev_match(const struct rte_eth_dev *edev, {const struct eth_dev_match_arg *arg = _arg;const struct rte_kvargs *kvlist = arg->kvlist; +struct rte_eth_dev_data *data;if (edev->state ==RTE_ETH_DEV_UNUSED )return -1 ;
@@ -47,6 +50,10 @@ eth_dev_match(const struct rte_eth_dev *edev,if (kvlist ==NULL )/* Empty string matches everything. */ return 0 ; + data = edev->data; +if (rte_kvargs_process (kvlist,"name" , + rte_kvargs_strcmp, data->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v6 22/22 app/testpmd: add show device command
In reply to Gaetan RivetA new interactive command is offered:
show device <device description>
This commands lists all rte_device element matching the device description. e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0
These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
--- app/test-pmd/cmdline.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
app/test-pmd/cmdline.c +52 -0
@@ -6701,6 +6701,57 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) +{ +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) +{ +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device " +"<device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;
@@ -16038,6 +16089,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall,
Signature · 1 line
2.11.0
v7 cover Device querying
In reply to Gaetan RivetThis patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).
* Both rte_bus and rte_class now offer a way to
list their devices and filter the result
using locally defined properties.
* The rte_dev API now has an rte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.
As an example, the "eth" device class is implemented.
Additionally, the device filters for
+ rte_bus_pci
+ rte_bus_vdev
+ rte_class_eth
are implemented and can be used with some
properties each, to show how to extend those.
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
---
v2:
* Reworked the dev_iterate callback to simplify
its implementation.
Now dev_iterate implementation do not need to learn about the intricacies of the rte_dev_iterator. The rte_dev_iterator is managed purely by the rte_dev_iterator_next function. Buses and classes then do not have to care about settings things right.
Additionally, dev_iterate implementations do not have to sanitize their dev string anymore, they are prepared by the rte_dev layer prior, which also reduces the number of dynamic allocations.
v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
using librte_kvargs instead.
* Reversed dependencies of librte_kvargs and
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.
v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
* rte_kvargs now includes rte_eal directly and keeps rte_log.
* added generic string comparison function to rte_kvargs, as some kind of comparison should probably be shared by many layers.
v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private generic rte_eth_dev iterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.
v6:
* Rebased on master
* Introduce RTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.
v7:
* Rebased on master
* Fix rte_kvargs_strcmp return value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.
Gaetan Rivet (22):
kvargs: build before EAL
eal: list acceptable init priorities
eal: add last init priority
eal: introduce dtor macros
eal: introduce device class abstraction eal/class: register destructor
eal/dev: add device iterator interface eal/class: add device iteration
eal/bus: add device iteration
eal/dev: implement device iteration initialization eal/dev: implement device iteration
kvargs: add generic string matching callback bus/pci: fix find device implementation bus/pci: implement device iteration and comparison bus/pci: add device matching field id bus/vdev: fix find device implementation bus/vdev: implement device iteration bus/vdev: add device matching field driver
ethdev: add private generic device iterator
ethdev: register ether layer as a class
ethdev: add device matching field name app/testpmd: add show device command
app/test-pmd/cmdline.c | 52 ++++
drivers/bus/pci/Makefile | 2 +-
drivers/bus/pci/pci_common.c | 87 +++++-
drivers/bus/pci/rte_bus_pci.h | 3 +
drivers/bus/vdev/Makefile | 3 +-
drivers/bus/vdev/rte_bus_vdev.h | 3 +
drivers/bus/vdev/vdev.c | 66 ++++-
lib/Makefile | 7 +-
lib/librte_eal/bsdapp/eal/Makefile | 2 +
lib/librte_eal/common/Makefile | 4 +-
lib/librte_eal/common/eal_common_class.c | 62 ++++
lib/librte_eal/common/eal_common_dev.c | 317 +++++++++++++++++++++
lib/librte_eal/common/eal_common_log.c | 2 +-
lib/librte_eal/common/include/rte_bus.h | 3 +-
lib/librte_eal/common/include/rte_class.h | 127 +++++++++
lib/librte_eal/common/include/rte_common.h | 53 +++-
lib/librte_eal/common/include/rte_dev.h | 97 +++++++
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/rte_eal_version.map | 4 +
lib/librte_ether/Makefile | 4 +-
lib/librte_ether/eth_private.c | 31 ++
lib/librte_ether/eth_private.h | 26 ++
lib/librte_ether/rte_class_eth.c | 86 ++++++
lib/librte_kvargs/Makefile | 3 +-
lib/librte_kvargs/rte_kvargs.c | 12 +-
lib/librte_kvargs/rte_kvargs.h | 28 ++
lib/librte_kvargs/rte_kvargs_version.map | 7 +
.../include => librte_kvargs}/rte_string_fns.h | 0
28 files changed, 1056 insertions(+), 37 deletions(-)
create mode 100644 lib/librte_eal/common/eal_common_class.c
create mode 100644 lib/librte_eal/common/include/rte_class.h
create mode 100644 lib/librte_ether/eth_private.c
create mode 100644 lib/librte_ether/eth_private.h
create mode 100644 lib/librte_ether/rte_class_eth.c
rename lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h (100%)Signature · 1 line
2.11.0
PATCH v7 1/22 kvargs: build before EAL
---
lib/Makefile | 3 +--
lib/librte_eal/common/Makefile | 2 +-
lib/librte_kvargs/Makefile | 3 ++-
lib/librte_kvargs/rte_kvargs.c | 2 +-
lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h | 0
5 files changed, 5 insertions(+), 5 deletions(-)
rename lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h (100%)lib/Makefile +1 -2
@@ -4,6 +4,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat +DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
@@ -71,8 +72,6 @@ DEPDIRS-librte_flow_classify := librte_net librte_table librte_acl DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DEPDIRS-librte_sched := librte_eal librte_mempool librte_mbuf librte_net DEPDIRS-librte_sched += librte_timer -DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs -DEPDIRS-librte_kvargs := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += librte_distributor DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ether DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
lib/librte_eal/common/Makefile +1 -1
@@ -9,7 +9,7 @@ INC += rte_errno.h rte_launch.h rte_lcore.h INC += rte_log.h rte_memory.h rte_memzone.h INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h -INC += rte_string_fns.h rte_version.h +INC += rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
lib/librte_kvargs/Makefile +2 -1
@@ -37,7 +37,7 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_kvargs.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -LDLIBS += -lrte_eal +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include EXPORT_MAP := rte_kvargs_version.map
@@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := rte_kvargs.c # install includes INCS := rte_kvargs.h +INCS += rte_string_fns.h SYMLINK-$(CONFIG_RTE_LIBRTE_KVARGS)-include := $(INCS) include $(RTE_SDK)/mk/rte.lib.mk
lib/librte_kvargs/rte_kvargs.c +1 -1
@@ -7,8 +7,8 @@#include <stdlib.h> #include <rte_log.h> -#include <rte_string_fns.h> +#include "rte_string_fns.h" #include "rte_kvargs.h" /*
lib/librte_kvargs/rte_string_fns.h renamed from lib/librte_eal/common/include/rte_string_fns.h +0 -0
Signature · 1 line
2.11.0
Re: [PATCH v7 01/22] kvargs: build before EAL
Quoted 10 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>--- lib/Makefile | 3 +-- lib/librte_eal/common/Makefile | 2 +- lib/librte_kvargs/Makefile | 3 ++- lib/librte_kvargs/rte_kvargs.c | 2 +- lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename lib/{librte_eal/common/include => librte_kvargs}/rte_string_fns.h (100%)
This fails for me when building DPDK for shared libs, due to the dependency on rte_log. I think if we to have kvargs built first it needs to be completely independent.
/Bruce
PATCH v7 2/22 eal: list acceptable init priorities
In reply to Gaetan RivetBuild a central list to quickly see each used priorities for constructors, allowing to verify that they are both above 100 and in the proper order.
--- lib/librte_eal/common/eal_common_log.c | 2 +- lib/librte_eal/common/include/rte_bus.h | 2 +- lib/librte_eal/common/include/rte_common.h | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-)
lib/librte_eal/common/eal_common_log.c +1 -1
@@ -260,7 +260,7 @@ static const struct logtype logtype_strings[] = { };/* Logging should be first initializer (before drivers and bus) */ -RTE_INIT_PRIO (rte_log_init,101 ); +RTE_INIT_PRIO (rte_log_init,LOG );static void rte_log_init (void ) {
lib/librte_eal/common/include/rte_bus.h +1 -1
@@ -325,7 +325,7 @@ enum rte_iova_mode rte_bus_get_iommu_class(void);* The constructor has higher priority than PMD constructors. */ #define RTE_REGISTER_BUS (nm, bus) \ -RTE_INIT_PRIO(businitfn_ ##nm, 110); \ +RTE_INIT_PRIO(businitfn_ ##nm, BUS); \ static void businitfn_ ##nm(void) \ {\ (bus).name = RTE_STR(nm);\
lib/librte_eal/common/include/rte_common.h +7 -1
@@ -81,6 +81,12 @@ typedef uint16_t unaligned_uint16_t;*/ #define RTE_SET_USED (x) (void)(x) +#define RTE_PRIORITY_LOG 101 +#define RTE_PRIORITY_BUS 110 + +#define RTE_PRIO (prio) \ + RTE_PRIORITY_ ## prio +/** * Run function before main() with low priority. *
@@ -102,7 +108,7 @@ static void __attribute__((constructor, used)) func(void)* Lowest number is the first to run. */ #define RTE_INIT_PRIO (func, prio) \ -static void __attribute__((constructor(prio), used)) func(void) +static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)/** * Force a function to be inlined
Signature · 1 line
2.11.0
PATCH v7 3/22 eal: add last init priority
In reply to Gaetan RivetAdd the priority RTE_PRIORITY_LAST, used for initialization routines meant to be run after all other constructors.
This priority becomes the default priority for all DPDK constructors.
--- lib/librte_eal/common/include/rte_common.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
lib/librte_eal/common/include/rte_common.h +12 -11
@@ -83,22 +83,12 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \ RTE_PRIORITY_ ## prio/** -* Run function before main() with low priority. -* -* The constructor will be run after prioritized constructors. -* -* @param func -* Constructor function. -*/ -#define RTE_INIT (func) \ -static void __attribute__((constructor, used)) func(void) - -/** * Run function before main() with high priority. * * @param func
@@ -111,6 +101,17 @@ static void __attribute__((constructor, used)) func(void)static void __attribute__((constructor (RTE_PRIO (prio)), used))func (void )/** +* Run function before main() with low priority. +* +* The constructor will be run after prioritized constructors. +* +* @param func +* Constructor function. + */ +#define RTE_INIT (func) \ + RTE_INIT_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v7 4/22 eal: introduce dtor macros
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
lib/librte_eal/common/include/rte_common.h +23 -0
@@ -112,6 +112,29 @@ static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)RTE_INIT_PRIO (func,LAST )/** +* Run after main() with low priority. +* +* @param func +* Destructor function name. +* @param prio +* Priority number must be above 100. +* Lowest number is the last to run. + */ +#define RTE_FINI_PRIO (func, prio) \ +static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void) + +/** +* Run after main() with high priority. +* +* The destructor will be run *before* prioritized destructors. +* +* @param func +* Destructor function name. +*/ +#define RTE_FINI (func) \ + RTE_FINI_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v7 5/22 eal: introduce device class abstraction
In reply to Gaetan Rivet--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 +++++++++++++++ lib/librte_eal/common/include/rte_class.h | 121 +++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 2 + 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -51,6 +51,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
lib/librte_eal/common/Makefile +1 -1
@@ -11,7 +11,7 @@ INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h
lib/librte_eal/common/eal_common_class.c new file +62 -0
62 lines not on this page · raw message
lib/librte_eal/common/include/rte_class.h new file +121 -0
121 lines not on this page · raw message
lib/librte_eal/common/include/rte_common.h +1 -0
@@ -83,6 +83,7 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_CLASS 120#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -59,6 +59,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
lib/librte_eal/rte_eal_version.map +2 -0
@@ -221,6 +221,8 @@ EXPERIMENTAL { rte_eal_devargs_insert; rte_eal_devargs_parse; rte_eal_devargs_remove; + rte_class_register; + rte_class_unregister; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v7 6/22 eal/class: register destructor
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 5 +++++ 1 file changed, 5 insertions(+)
lib/librte_eal/common/include/rte_class.h +5 -0
@@ -112,6 +112,11 @@ static void classinitfn_ ##nm(void) \ {\ (cls).name =RTE_STR (nm);\rte_class_register (&cls); \ +} \ +RTE_FINI_PRIO(classfinifn_ ##nm, CLASS); \ +static void classfinifn_ ##nm(void) \ +{ \ + rte_class_unregister(&cls); \ }#ifdef __cplusplus
Signature · 1 line
2.11.0
PATCH v7 7/22 eal/dev: add device iterator interface
In reply to Gaetan RivetA device iterator allows iterating over a set of devices. This set is defined by the two descriptions offered,
* rte_bus
* rte_class
Only one description can be provided, or both. It is not allowed to provide no description at all.
Each layer of abstraction then performs a filter based on the description provided. This filtering allows iterating on their internal set of devices, stopping when a match is valid and returning the current iteration context.
This context allows starting the next iteration from the same point and going forward.
--- lib/librte_eal/common/include/rte_dev.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
lib/librte_eal/common/include/rte_dev.h +47 -0
@@ -282,6 +282,53 @@ __attribute__((used)) = str static const char DRV_EXP_TAG(name, kmod_dep_export)[] \ __attribute__((used)) = str +/** +* Iteration context. +* +* This context carries over the current iteration state. +*/ +struct rte_dev_iterator { +const char *devstr;/**< device string. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< class-related part of device string. */ +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +struct rte_device *device;/**< current position. */ +void *class_device;/**< additional specialized context. */ +}; + +/** +* Device iteration function. +* +* Find the next device matching properties passed in parameters. +* The function takes an additional ``start`` parameter, that is +* used as starting context when relevant. +* +* The function returns the current element in the iteration. +* This return value will potentially be used as a start parameter +* in subsequent calls to the function. +* +* The additional iterator parameter is only there if a specific +* implementation needs additional context. It must not be modified by +* the iteration function itself. +* +* @param start +* Starting iteration context. +* +* @param devstr +* Device description string. +* +* @param it +* Device iterator. +* +* @return +* The address of the current element matching the device description +* string. +*/ +typedef void *(*rte_dev_iterate_t )(const void *start, +const char *devstr, +const struct rte_dev_iterator *it); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v7 8/22 eal/class: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_class.h +1 -0
@@ -30,6 +30,7 @@ TAILQ_HEAD(rte_class_list, rte_class);struct rte_class {TAILQ_ENTRY (rte_class) next;/**< Next device class in linked list */ const char *name;/**< Name of the class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v7 9/22 eal/bus: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_bus.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_bus.h +1 -0
@@ -211,6 +211,7 @@ struct rte_bus {rte_bus_parse_t parse;/**< Parse a device name */ struct rte_bus_conf conf;/**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class;/**< Get iommu class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v7 10/22 eal/dev: implement device iteration initialization
In reply to Gaetan RivetParse a device description.
Split this description in their relevant part for each layers. No dynamic allocation is performed.
--- lib/Makefile | 1 + lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_dev.c | 149 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 24 +++++ lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 1 + 6 files changed, 177 insertions(+)
lib/Makefile +1 -0
@@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal +DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -18,6 +18,7 @@ CFLAGS += $(WERROR_FLAGS) -O3 LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s +LDLIBS += -lrte_kvargs EXPORT_MAP := ../../rte_eal_version.map
lib/librte_eal/common/eal_common_dev.c +149 -0
161 lines not on this page · raw message
lib/librte_eal/common/include/rte_dev.h +24 -0
@@ -329,6 +329,30 @@ typedef void *(*rte_dev_iterate_t)(const void *start,const char *devstr, const struct rte_dev_iterator *it); +/** +* Initializes a device iterator. +* +* This iterator allows accessing a list of devices matching a criteria. +* The device matching is made among all buses and classes currently registered, +* filtered by the device description given as parameter. +* +* This function will not allocate any memory. It is safe to stop the +* iteration at any moment and let the iterator go out of context. +* +* @param it +* Device iterator handle. +* +* @param str +* Device description string. +* +* @return +* 0 on successful initialization. +* <0 on error. +*/ +__rte_experimental +int +rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -27,6 +27,7 @@ LDLIBS += -lrt ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif +LDLIBS += -lrte_kvargs # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
lib/librte_eal/rte_eal_version.map +1 -0
@@ -223,6 +223,7 @@ EXPERIMENTAL { rte_eal_devargs_remove; rte_class_register; rte_class_unregister; + rte_dev_iterator_init; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v7 11/22 eal/dev: implement device iteration
In reply to Gaetan RivetUse the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists.
--- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+)
lib/librte_eal/common/eal_common_dev.c +168 -0
@@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs;/* spinlock for device callbacks */ static rte_spinlock_t dev_event_lock =RTE_SPINLOCK_INITIALIZER ; +struct dev_next_ctx { +struct rte_dev_iterator *it; +const char *busstr; +const char *clsstr; +}; + +#define CTX (it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) +static int cmp_detached_dev_name (const struct rte_device *dev,const void *_name) {
@@ -517,3 +539,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, }return -rte_errno; } + +static char * +dev_str_sane_copy (const char *str) +{ +size_t end; +char *copy; + + end =strcspn (str,",/" ); +if (str[end] ==',' ) { + copy =strdup (&str[end +1 ]); + }else { +/* '/' or '\0' */ + copy =strdup ("" ); + } +if (copy ==NULL ) { + rte_errno =ENOMEM ; + }else { +char *slash; + + slash =strchr (copy,'/' ); +if (slash !=NULL ) + slash[0 ] ='\0' ; + } +return copy; +} + +static int +class_next_dev_cmp (const struct rte_class *cls, +const void *ctx) +{ +struct rte_dev_iterator *it; +const char *clsstr =NULL ; +void *dev; + +if (cls->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + clsstr =CLSCTX (ctx); + dev = it->class_device; +/* it->clsstr != NULL means a class +* was specified in the devstr. +*/ +if (it->clsstr !=NULL && cls != it->cls) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; + dev = cls->dev_iterate (dev, clsstr, it); + it->class_device = dev; +return dev ==NULL ; +} + +static int +bus_next_dev_cmp (const struct rte_bus *bus, +const void *ctx) +{ +struct rte_device *dev =NULL ; +struct rte_class *cls =NULL ; +struct rte_dev_iterator *it; +const char *busstr =NULL ; + +if (bus->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + busstr =BUSCTX (ctx); + dev = it->device; +/* it->busstr != NULL means a bus +* was specified in the devstr. +*/ +if (it->busstr !=NULL && bus != it->bus) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; +if (it->clsstr ==NULL ) { + dev = bus->dev_iterate (dev, busstr, it); + goto end; + } +/* clsstr != NULL */ +if (dev ==NULL ) { +next_dev_on_bus: + dev = bus->dev_iterate (dev, busstr, it); + it->device = dev; + } +if (dev ==NULL ) +return 1 ; +if (it->cls !=NULL ) + cls =TAILQ_PREV (it->cls, rte_class_list, next); + cls =rte_class_find (cls, class_next_dev_cmp, ctx); +if (cls !=NULL ) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; +return dev ==NULL ; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it) +{ +struct rte_bus *bus =NULL ; +int old_errno = rte_errno; +char *busstr =NULL ; +char *clsstr =NULL ; + + rte_errno =0 ; +if (it->busstr ==NULL && it->clsstr ==NULL ) { +/* Invalid iterator. */ + rte_errno =EINVAL ; +return NULL ; + } +if (it->bus !=NULL ) + bus =TAILQ_PREV (it->bus, rte_bus_list, next); +if (it->busstr !=NULL ) { + busstr =dev_str_sane_copy (it->busstr); +if (busstr ==NULL ) + goto out; + } +if (it->clsstr !=NULL ) { + clsstr =dev_str_sane_copy (it->clsstr); +if (clsstr ==NULL ) + goto out; + } +while ((bus =rte_bus_find (bus, bus_next_dev_cmp, +CTX (it, busstr, clsstr)))) { +if (it->device !=NULL ) { + it->bus = bus; + goto out; + } +if (it->busstr !=NULL || + rte_errno !=0 ) +break ; + } +if (rte_errno ==0 ) + rte_errno = old_errno; +out: +free (busstr); +free (clsstr); +return it->device; +}
lib/librte_eal/common/include/rte_dev.h +26 -0
@@ -353,6 +353,32 @@ __rte_experimentalint rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); +/** +* Iterates on a device iterator. +* +* Generates a new rte_device handle corresponding to the next element +* in the list described in comprehension by the iterator. +* +* The next object is returned, and the iterator is updated. +* +* @param it +* Device iterator handle. +* +* @return +* An rte_device handle if found. +* NULL if an error occurred (rte_errno is set). +* NULL if no device could be found (rte_errno is not set). +*/ +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH (dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus }#endif
lib/librte_eal/rte_eal_version.map +1 -0
@@ -224,6 +224,7 @@ EXPERIMENTAL { rte_class_register; rte_class_unregister; rte_dev_iterator_init; + rte_dev_iterator_next; rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops;
Signature · 1 line
2.11.0
PATCH v7 12/22 kvargs: add generic string matching callback
In reply to Gaetan RivetThis function can be used as a callback torte_kvargs_process.
This should reduce code duplication.
--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 46 insertions(+)
lib/Makefile +1 -0
@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci
lib/librte_kvargs/rte_kvargs.c +10 -0
@@ -180,3 +180,13 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -abs (strcmp (str, value)); +}
lib/librte_kvargs/rte_kvargs.h +28 -0
@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32
@@ -121,6 +123,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* +* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. +*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif
lib/librte_kvargs/rte_kvargs_version.map +7 -0
@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_strcmp; + +} DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v7 13/22 bus/pci: fix find device implementation
In reply to Gaetan RivetIf start is set, and a device before it matches the data passed for comparison, then this first device is returned.
This induces potentially infinite loops.
--- drivers/bus/pci/pci_common.c | 21 ++++++++++++--------- drivers/bus/pci/rte_bus_pci.h | 3 +++ 2 files changed, 15 insertions(+), 9 deletions(-)
drivers/bus/pci/pci_common.c +12 -9
@@ -459,17 +459,20 @@ static struct rte_device * pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { - struct rte_pci_device *dev; + const struct rte_pci_device *pstart; +struct rte_pci_device *pdev; -FOREACH_DEVICE_ON_PCIBUS (dev) { -if (start && &dev->device == start) { - start =NULL ;/* starting point found */ -continue ; - } -if (cmp (&dev->device, data) ==0 ) -return &dev->device; +if (start !=NULL ) { + pstart =RTE_DEV_TO_PCI_CONST (start); + pdev =TAILQ_NEXT (pstart, next); + }else { + pdev =TAILQ_FIRST (&rte_pci_bus.device_list); + } +while (pdev !=NULL ) { +if (cmp (&pdev->device, data) ==0 ) +return &pdev->device; + pdev =TAILQ_NEXT (pdev, next); } -return NULL ; }
drivers/bus/pci/rte_bus_pci.h +3 -0
@@ -74,6 +74,9 @@ struct rte_pci_device {*/ #define RTE_DEV_TO_PCI (ptr) container_of(ptr, struct rte_pci_device, device) +#define RTE_DEV_TO_PCI_CONST (ptr) \ + container_of(ptr, const struct rte_pci_device, device) +#define RTE_ETH_DEV_TO_PCI (eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)/** Any PCI device identifier (vendor, device, ...) */
Signature · 1 line
2.11.0
PATCH v7 14/22 bus/pci: implement device iteration and comparison
In reply to Gaetan Rivet--- drivers/bus/pci/Makefile | 2 +- drivers/bus/pci/pci_common.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/pci/Makefile +1 -1
@@ -53,7 +53,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring -LDLIBS += -lrte_ethdev -lrte_pci +LDLIBS += -lrte_ethdev -lrte_pci -lrte_kvargs include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))
drivers/bus/pci/pci_common.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v7 15/22 bus/pci: add device matching field id
In reply to Gaetan RivetThe PCI bus can now parse a matching field "id" as follows:
"bus=pci,id=0000:00:00.0"
or
"bus=pci,id=00:00.0"
--- drivers/bus/pci/pci_common.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
drivers/bus/pci/pci_common.c +26 -2
@@ -499,21 +499,45 @@ pci_unplug(struct rte_device *dev) }enum pci_params { +RTE_PCI_PARAMS_ID ,RTE_PCI_PARAMS_MAX , };static const char *const pci_params_keys[] = { + [RTE_PCI_PARAMS_ID ] ="id" , [RTE_PCI_PARAMS_MAX ] =NULL , };static int +pci_addr_kv_cmp(const char *key __rte_unused, +const char *value, +void *_addr2) +{ +struct rte_pci_addr _addr1; +struct rte_pci_addr *addr1 = &_addr1; +struct rte_pci_addr *addr2 = _addr2; + +if (rte_pci_addr_parse (value, addr1)) +return -1 ; +return rte_pci_addr_cmp (addr1, addr2); +} + +static int pci_dev_match (const struct rte_device *dev,const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_pci_device *pdev; - (void ) dev; - (void ) kvlist; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + pdev =RTE_DEV_TO_PCI_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"id" , + &pci_addr_kv_cmp, + (void *)(intptr_t )&pdev->addr)) +return 1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v7 16/22 bus/vdev: fix find device implementation
In reply to Gaetan RivetIf start is set and a device before it matches the data, this device is returned.
This induces potentially infinite loops.
--- drivers/bus/vdev/rte_bus_vdev.h | 3 +++ drivers/bus/vdev/vdev.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-)
drivers/bus/vdev/rte_bus_vdev.h +3 -0
@@ -25,6 +25,9 @@ struct rte_vdev_device {#define RTE_DEV_TO_VDEV (ptr) \ container_of(ptr, struct rte_vdev_device, device) +#define RTE_DEV_TO_VDEV_CONST (ptr) \ + container_of(ptr, const struct rte_vdev_device, device) +static inline const char *rte_vdev_device_name (const struct rte_vdev_device *dev) {
drivers/bus/vdev/vdev.c +9 -5
@@ -358,15 +358,19 @@ static struct rte_device * vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data) { + const struct rte_vdev_device *vstart;struct rte_vdev_device *dev; - TAILQ_FOREACH(dev, &vdev_device_list, next) { -if (start && &dev->device == start) { - start =NULL ; -continue ; - } +if (start !=NULL ) { + vstart =RTE_DEV_TO_VDEV_CONST (start); + dev =TAILQ_NEXT (vstart, next); + }else { + dev =TAILQ_FIRST (&vdev_device_list); + } +while (dev !=NULL ) {if (cmp (&dev->device, data) ==0 )return &dev->device; + dev =TAILQ_NEXT (dev, next); }return NULL ; }
Signature · 1 line
2.11.0
PATCH v7 17/22 bus/vdev: implement device iteration
In reply to Gaetan Rivet--- drivers/bus/vdev/Makefile | 2 +- drivers/bus/vdev/vdev.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-)
drivers/bus/vdev/Makefile +1 -1
@@ -19,7 +19,7 @@ LIBABIVER := 1 SRCS-y += vdev.c -LDLIBS += -lrte_eal +LDLIBS += -lrte_eal -lrte_kvargs # # Export include files
drivers/bus/vdev/vdev.c +42 -0
60 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v7 18/22 bus/vdev: add device matching field driver
In reply to Gaetan RivetThe vdev bus parses a field "driver", matching
a vdev driver name with one passed as follows:
"bus=vdev,driver=xxxx"
--- drivers/bus/vdev/Makefile | 1 + drivers/bus/vdev/vdev.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)
drivers/bus/vdev/Makefile +1 -0
@@ -10,6 +10,7 @@ LIB = librte_bus_vdev.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API # versioning export map EXPORT_MAP := rte_bus_vdev_version.map
drivers/bus/vdev/vdev.c +12 -2
@@ -389,10 +389,12 @@ vdev_unplug(struct rte_device *dev) }enum vdev_params { +RTE_VDEV_PARAMS_DRIVER ,RTE_VDEV_PARAMS_MAX , };static const char *const vdev_params_keys[] = { + [RTE_VDEV_PARAMS_DRIVER ] ="driver" , [RTE_VDEV_PARAMS_MAX ] =NULL , };
@@ -401,9 +403,17 @@ vdev_dev_match(const struct rte_device *dev, const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_vdev_device *vdev; - (void ) kvlist; - (void ) dev; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + vdev =RTE_DEV_TO_VDEV_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"driver" , + rte_kvargs_strcmp, + (void *)(intptr_t )vdev->device.driver->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v7 19/22 ethdev: add private generic device iterator
In reply to Gaetan RivetThis iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to librte_ether.
--- lib/librte_ether/Makefile | 1 + lib/librte_ether/eth_private.c | 31 +++++++++++++++++++++++++++++++ lib/librte_ether/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 lib/librte_ether/eth_private.c create mode 100644 lib/librte_ether/eth_private.h
lib/librte_ether/Makefile +1 -0
@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c
lib/librte_ether/eth_private.c new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *start,rte_eth_cmp_t cmp, +const void *data) +{ +struct rte_eth_dev *edev; +ptrdiff_t idx; + +/* Avoid Undefined Behaviour */ +if (start !=NULL && + (start < &rte_eth_devices[0 ] || + start > &rte_eth_devices[RTE_MAX_ETHPORTS ])) +return NULL ; +if (start !=NULL ) + idx = start - &rte_eth_devices[0 ] +1 ; +else + idx =0 ; +for (; idx <RTE_MAX_ETHPORTS ; idx++) { + edev = &rte_eth_devices[idx]; +if (cmp (edev, data) ==0 ) +return edev; + } +return NULL ; +} +
lib/librte_ether/eth_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#ifndef _RTE_ETH_PRIVATE_H_ +#define _RTE_ETH_PRIVATE_H_ + +#include "rte_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic rte_eth_dev comparison function. */ +typedef int (*rte_eth_cmp_t )(const struct rte_eth_dev *,const void *); + +/* Generic rte_eth_dev iterator. */ +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *_start,rte_eth_cmp_t cmp, +const void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ETH_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v7 20/22 ethdev: register ether layer as a class
In reply to Gaetan Rivet--- lib/Makefile | 2 +- lib/librte_ether/Makefile | 3 +- lib/librte_ether/rte_class_eth.c | 79 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 lib/librte_ether/rte_class_eth.c
lib/Makefile +1 -1
@@ -23,7 +23,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DEPDIRS-librte_cmdline := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether DEPDIRS-librte_ether := librte_net librte_eal librte_mempool librte_ring -DEPDIRS-librte_ether += librte_mbuf +DEPDIRS-librte_ether += librte_mbuf librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += librte_bbdev DEPDIRS-librte_bbdev := librte_eal librte_mempool librte_mbuf DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += librte_cryptodev
lib/librte_ether/Makefile +2 -1
@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
lib/librte_ether/rte_class_eth.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v7 21/22 ethdev: add device matching field name
In reply to Gaetan RivetThe eth device class can now parse a field name,
matching the eth_dev name with one passed as
"class=eth,name=xxxxxx"
--- lib/librte_ether/rte_class_eth.c | 7 +++++++ 1 file changed, 7 insertions(+)
lib/librte_ether/rte_class_eth.c +7 -0
@@ -15,10 +15,12 @@#include "eth_private.h" enum eth_params { +RTE_ETH_PARAMS_NAME ,RTE_ETH_PARAMS_MAX , };static const char *const eth_params_keys[] = { + [RTE_ETH_PARAMS_NAME ] ="name" , [RTE_ETH_PARAMS_MAX ] =NULL , };
@@ -39,6 +41,7 @@ eth_dev_match(const struct rte_eth_dev *edev, {const struct eth_dev_match_arg *arg = _arg;const struct rte_kvargs *kvlist = arg->kvlist; +struct rte_eth_dev_data *data;if (edev->state ==RTE_ETH_DEV_UNUSED )return -1 ;
@@ -47,6 +50,10 @@ eth_dev_match(const struct rte_eth_dev *edev,if (kvlist ==NULL )/* Empty string matches everything. */ return 0 ; + data = edev->data; +if (rte_kvargs_process (kvlist,"name" , + rte_kvargs_strcmp, data->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v7 22/22 app/testpmd: add show device command
In reply to Gaetan RivetA new interactive command is offered:
show device <device description>
This commands lists all rte_device element matching the device description. e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0
These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
--- app/test-pmd/cmdline.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
app/test-pmd/cmdline.c +52 -0
@@ -6701,6 +6701,57 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) +{ +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) +{ +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device " +"<device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;
@@ -16038,6 +16089,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall,
Signature · 1 line
2.11.0
Re: [PATCH v7 22/22] app/testpmd: add show device command
Hi Gaetan,
Quoted 69 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Sunday, April 15, 2018 4:08 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v7 22/22] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the device description. e.g.:show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
40b31ad7e..8ac5fb3ca100644app/test-pmd/cmdline.c +31
-0@@ -6701,6 +6701,57 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result,
app/test-pmd/cmdline.c cmdline_parse_inst_t cmd_showportall = { · line 6744
Quoted 10 lines
app/test-pmd/cmdline.c +10
-0+ device, "device"); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device " +"<device string>" ,
.help_str should be on one line to avoid checkpatch warning.
Quoted 20 lines
app/test-pmd/cmdline.c +9
-1+ .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, + NULL, + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result { cmdline_fixed_string_t show;@@ -16038,6 +16089,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, --
Quoted 1 line
2.11.0
This patch fails to compile on dpdk_18.08.rc0
There should probably be an update to the testpmd documentation also in doc/guides/testpmd_app_ug/*.rst
Regards,
Bernard.
Re: [PATCH v7 22/22] app/testpmd: add show device command
Hi Bernard,
Quoted 75 lines · Bernard
Hi Gaetan,
Quoted 73 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Sunday, April 15, 2018 4:08 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v7 22/22] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the device description. e.g.:show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
40b31ad7e..8ac5fb3ca100644app/test-pmd/cmdline.c +35
-0@@ -6701,6 +6701,57 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL );
Quoted 9 lines
app/test-pmd/cmdline.c cmdline_parse_inst_t cmd_showportall = { · line 6746
Quoted 6 lines
app/test-pmd/cmdline.c +6
-0+ +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device " +"<device string>" ,.help_str should be on one line to avoid checkpatch warning.
Thanks, will fix.
Quoted 15 lines
Quoted 15 lines
app/test-pmd/cmdline.c +8
-0+ .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, + NULL, + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result { cmdline_fixed_string_t show;@@ -16038,6 +16089,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file,
Quoted 9 lines
Quoted 6 lines
app/test-pmd/cmdline.c +1
-1+ (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, --2.11.0
This patch fails to compile on dpdk_18.08.rc0
I have rebased the series in 18.08-rc0, I will send it as a v8.
Quoted 1 line
There should probably be an update to the testpmd documentation also in doc/guides/testpmd_app_ug/*.rst
I will look into it.
Regards,
Signature · 2 lines
Gaëtan Rivet 6WIND
15/04/2018 17:07, Gaetan Rivet:
Quoted 27 lines
This patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "
rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).* Both
rte_busandrte_classnow offer a way to
list their devices and filter the result
using locally defined properties.* The
rte_devAPI now has anrte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.As an example, the "eth" device class is implemented.
Additionally, the device filters for
+
rte_bus_pci
+rte_bus_vdev
+rte_class_ethare implemented and can be used with some
properties each, to show how to extend those.
Quoted 8 lines
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
Thanks for the very big work Gaetan.
This series has some cleanups, fixes, and more importantly, introduces the framework for a generic device syntax.
I am not clear what is missing in the properties parsing? In various buses and classes implementations?
Are we close of the next step, revisiting -w/-b and --vdev options?
Quoted 37 lines · Thomas Monjalon
15/04/2018 17:07, Gaetan Rivet:
Quoted 27 lines
This patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "
rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).* Both
rte_busandrte_classnow offer a way to
list their devices and filter the result
using locally defined properties.* The
rte_devAPI now has anrte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.As an example, the "eth" device class is implemented.
Additionally, the device filters for
+
rte_bus_pci
+rte_bus_vdev
+rte_class_ethare implemented and can be used with some
properties each, to show how to extend those.Quoted 8 lines
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
Quoted 6 lines
Thanks for the very big work Gaetan.
This series has some cleanups, fixes, and more importantly, introduces the framework for a generic device syntax.
I am not clear what is missing in the properties parsing?
For properties, parsing is *mostly* done. The general framework is there for other devs to populate as they see fit.
A thing that will arise when doing so, is that librte_kvargs is somewhat cumbersome to use as it is, when the "/" character is not considered "end-of-string". This adds cruft in a lot of places otherwise. So I think we need to add some way to configure this (or even have this behavior by default). Otherwise most things are available.
Quoted 4 lines
In various buses and classes implementations?
Are we close of the next step, revisiting -w/-b and --vdev options?
I started this part to see the scope. It's quite large.
I have issues with the current device declaration syntax, that needs to be discussed.
1.
One issue is that buses are working on a best-effort basis to probe drivers. When the "driver=" layer is given, a driver is then explicitly choosen by the user. This contradicts the current bus logic. The "driver" layer is necessary to give any device parameters, and choosing the proper driver beforehand seems user-hostile.
I think the "driver=" part should actually be dropped altogether, which would simplify the declaration. We'll see if another solution can be attained.
2.
A second issue is regarding the standing of the "class" layer. The parsing of devices goes like this:
0. bus, class and driver is parsed and put in its relevant part in the devargs.
1. Bus parses the devargs and uses its part within it (necessary to find the proper device identifier for example).
2. Bus probes all drivers to find the one able to handle the device. At this point, the devargs is passed down to the driver, with all three layers (bus, class, driver) parts.
Driver uses the driver part for its initialization.
3. Driver calls the device creation function of a class (passing the devargs), for example to spawn an rte_eth_dev.
The class thus parses the class part of the devargs and uses it for initialization.
In matter of layer hierarchy, this is not neat and clean:
bus -> driver -> class.
Drivers are the one having to choose whether to spawn an eth or crypto of compress device (or any other, in any numbers). Having the class initialize after the driver however seems prone to conflicts in configuration (between the hardware init and the higher device class properties for example).
Another issue that I sidestepped in the device ident, is how to recognize and handle ambiguous device declarations. Something like:
--dev bus=pci
would thus match all PCI devices on the system. All would be probed (akin to blacklist mode), with default parameters. Not aberrant.
However something like
--dev class=eth
does not mean anything. This cannot be recognized at devargs parsing time. Such devargs would not actually identify a specific device on a bus. PCI might be able to handle such case, vdev not. Other buses might not as well.
So I think it is necessary that at least the bus identifier is given. The bus identifier is a bus property that is bus-specific: for PCI it is the "id" property. For vdev it is "driver" (for driver name). This is not user-friendly. Requiring the bus identifier is not actually, but this is what was implicitly done by the current devargs "name" field.
But let's think about possible secondary properties: for example, in PCI bus the vendor id could be a property. Should a devargs "bus=pci,vendor=0x8086" be accepted, as a set of PCI device could actually be matched? If multiple devices match the devargs, should the devargs be cloned for each? I'm tempted to say no, for the sake of simplicity, but this might be worth thinking about it.
So, as you see, this work is far from done and there are standing issues that will I think require some discussion from the community.
Signature · 2 lines
Gaëtan Rivet 6WIND
v8 cover Device querying
In reply to Gaetan RivetThis patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).
* Both rte_bus and rte_class now offer a way to
list their devices and filter the result
using locally defined properties.
* The rte_dev API now has an rte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.
As an example, the "eth" device class is implemented.
Additionally, the device filters for
+ rte_bus_pci
+ rte_bus_vdev
+ rte_class_eth
are implemented and can be used with some
properties each, to show how to extend those.
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
---
v2:
* Reworked the dev_iterate callback to simplify
its implementation.
Now dev_iterate implementation do not need to learn about the intricacies of the rte_dev_iterator. The rte_dev_iterator is managed purely by the rte_dev_iterator_next function. Buses and classes then do not have to care about settings things right.
Additionally, dev_iterate implementations do not have to sanitize their dev string anymore, they are prepared by the rte_dev layer prior, which also reduces the number of dynamic allocations.
v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
using librte_kvargs instead.
* Reversed dependencies of librte_kvargs and
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.
v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
* rte_kvargs now includes rte_eal directly and keeps rte_log.
* added generic string comparison function to rte_kvargs, as some kind of comparison should probably be shared by many layers.
v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private generic rte_eth_dev iterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.
v6:
* Rebased on master
* Introduce RTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.
v7:
* Rebased on master
* Fix rte_kvargs_strcmp return value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.
v8:
* Rebased on master
* Cleaned kvargs use: introduced
a new parser function, that simplifies using the library for DPDK devargs.
* Refactored devargs parsing in a single function within rte_devargs.
This function is useful both for rte_dev parsing its iterator, and for rte_devargs parsing --dev parameters (not yet implemented).
* A few small bugfixes.
Gaetan Rivet (21):
devargs: add non-variadic parsing function
kvargs: build before EAL
kvargs: introduce a more flexible parsing function
eal: introduce dtor macros
eal: introduce device class abstraction eal/class: register destructor
devargs: add function to parse device layers eal/dev: add device iterator interface eal/class: add device iteration
eal/bus: add device iteration
eal/dev: implement device iteration initialization eal/dev: implement device iteration
kvargs: add generic string matching callback bus/pci: implement device iteration and comparison bus/pci: add device matching field id bus/vdev: implement device iteration bus/vdev: add device matching field driver
ethdev: add private generic device iterator
ethdev: register ether layer as a class
ethdev: add device matching field name app/testpmd: add show device command
app/test-pmd/cmdline.c | 51 +++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 +++ drivers/bus/pci/Makefile | 3 +- drivers/bus/pci/pci_common.c | 3 +- drivers/bus/pci/pci_params.c | 78 ++++++++++ drivers/bus/pci/private.h | 25 +++ drivers/bus/vdev/Makefile | 3 +- drivers/bus/vdev/vdev.c | 10 +- drivers/bus/vdev/vdev_params.c | 62 ++++++++ drivers/bus/vdev/vdev_private.h | 26 ++++ drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/Makefile | 5 +- lib/librte_eal/bsdapp/eal/Makefile | 2 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 ++++++++ lib/librte_eal/common/eal_common_dev.c | 227 +++++++++++++++++++++++++++- lib/librte_eal/common/eal_common_devargs.c | 186 +++++++++++++++++++++-- lib/librte_eal/common/eal_private.h | 27 ++++ lib/librte_eal/common/include/rte_bus.h | 1 + lib/librte_eal/common/include/rte_class.h | 127 ++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 24 +++ lib/librte_eal/common/include/rte_dev.h | 97 ++++++++++++ lib/librte_eal/common/include/rte_devargs.h | 53 ++++++- lib/librte_eal/linuxapp/eal/Makefile | 2 + lib/librte_eal/rte_eal_version.map | 5 + lib/librte_ethdev/Makefile | 4 +- lib/librte_ethdev/eth_private.c | 31 ++++ lib/librte_ethdev/eth_private.h | 26 ++++ lib/librte_ethdev/rte_class_eth.c | 86 +++++++++++ lib/librte_ethdev/rte_ethdev.c | 2 +- lib/librte_kvargs/Makefile | 2 +- lib/librte_kvargs/rte_kvargs.c | 35 +++++ lib/librte_kvargs/rte_kvargs.h | 58 +++++++ lib/librte_kvargs/rte_kvargs_version.map | 8 + 35 files changed, 1328 insertions(+), 33 deletions(-) create mode 100644 drivers/bus/pci/pci_params.c create mode 100644 drivers/bus/vdev/vdev_params.c create mode 100644 drivers/bus/vdev/vdev_private.h create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h create mode 100644 lib/librte_ethdev/eth_private.c create mode 100644 lib/librte_ethdev/eth_private.h create mode 100644 lib/librte_ethdev/rte_class_eth.c
Signature · 1 line
2.11.0
PATCH v8 1/21 devargs: add non-variadic parsing function
rte_devargs_parse becomes non-variadic,rte_devargs_parsef becomes the variadic version, to be used to compose device strings.
--- drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 4 +-- lib/librte_eal/common/eal_common_devargs.c | 42 ++++++++++++++++++++++------- lib/librte_eal/common/include/rte_devargs.h | 40 +++++++++++++++++++++++++-- lib/librte_eal/rte_eal_version.map | 1 + lib/librte_ethdev/rte_ethdev.c | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)
drivers/net/failsafe/failsafe_args.c +1 -1
@@ -63,7 +63,7 @@ fs_parse_device(struct sub_device *sdev, char *args) d = &sdev->devargs;DEBUG ("%s" , args); - ret =rte_devargs_parse (d,"%s" , args); + ret =rte_devargs_parse (d, args);if (ret) {DEBUG ("devargs parsing failed with code %d" , ret);return ret;
drivers/net/failsafe/failsafe_eal.c +1 -1
@@ -86,7 +86,7 @@ fs_bus_init(struct rte_eth_dev *dev)else snprintf (devstr,sizeof (devstr),"%s" , rte_eth_devices[pid].device->name); - ret =rte_devargs_parse (da,"%s" , devstr); + ret =rte_devargs_parse (da, devstr);if (ret) {ERROR ("Probed devargs parsing failed with code" " %d" , ret);
lib/librte_eal/common/eal_common_dev.c +2 -2
@@ -138,8 +138,8 @@ int __rte_experimental rte_eal_hotplug_add(const char *busname, const char *devnif (da ==NULL )return -ENOMEM ; - ret =rte_devargs_parse (da,"%s:%s,%s" , - busname, devname, devargs); + ret =rte_devargs_parsef (da,"%s:%s,%s" , + busname, devname, devargs);if (ret) goto err_devarg;
lib/librte_eal/common/eal_common_devargs.c +32 -10
69 lines not on this page · raw message
lib/librte_eal/common/include/rte_devargs.h +38 -2
@@ -96,6 +96,42 @@ int rte_eal_parse_devargs_str(const char *devargs_str,* in argument. Store which bus will handle the device, its name * and the eventual device parameters. * +* The syntax is: +* +* bus:device_identifier,arg1=val1,arg2=val2 +* +* where "bus:" is the bus name followed by any character separator. +* The bus name is optional. If no bus name is specified, each bus +* will attempt to recognize the device identifier. The first one +* to succeed will be used. +* +* Examples: +* +* pci:0000:05.00.0,arg=val +* 05.00.0,arg=val +* vdev:net_ring0 +* +* @param da +* The devargs structure holding the device information. +* +* @param dev +* String describing a device. +* +* @return +* - 0 on success. +* - Negative errno on error. +*/ +__rte_experimental +int +rte_devargs_parse (struct rte_devargs *da,const char *dev); + +/** +* Parse a device string. +* +* Verify that a bus is capable of handling the device passed +* in argument. Store which bus will handle the device, its name +* and the eventual device parameters. +* * The device string is built with a printf-like syntax. * * The syntax is:
@@ -124,8 +160,8 @@ int rte_eal_parse_devargs_str(const char *devargs_str,*/ __rte_experimental int -rte_devargs_parse (struct rte_devargs *da, -const char *format, ...) +rte_devargs_parsef (struct rte_devargs *da, +const char *format, ...) __attribute__((format (printf,2 ,0 )));/**
lib/librte_eal/rte_eal_version.map +1 -0
@@ -254,6 +254,7 @@ EXPERIMENTAL { rte_devargs_insert; rte_devargs_next; rte_devargs_parse; + rte_devargs_parsef; rte_devargs_remove; rte_devargs_type_count; rte_eal_cleanup;
lib/librte_ethdev/rte_ethdev.c +1 -1
@@ -654,7 +654,7 @@ rte_eth_dev_attach(const char *devargs, uint16_t *port_id) }/* parse devargs */ -if (rte_devargs_parse (&da,"%s" , devargs)) +if (rte_devargs_parse (&da, devargs)) goto err; ret =rte_eal_hotplug_add (da.bus->name, da.name, da.args);
Signature · 1 line
2.11.0
PATCH v8 2/21 kvargs: build before EAL
In reply to Gaetan Rivet--- lib/Makefile | 3 +-- lib/librte_kvargs/Makefile | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-)
lib/Makefile +1 -2
@@ -4,6 +4,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat +DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
@@ -76,8 +77,6 @@ DEPDIRS-librte_flow_classify := librte_net librte_table librte_acl DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DEPDIRS-librte_sched := librte_eal librte_mempool librte_mbuf librte_net DEPDIRS-librte_sched += librte_timer -DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs -DEPDIRS-librte_kvargs := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += librte_distributor DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
lib/librte_kvargs/Makefile +1 -1
@@ -7,7 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_kvargs.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -LDLIBS += -lrte_eal +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include EXPORT_MAP := rte_kvargs_version.map
Signature · 1 line
2.11.0
PATCH v8 3/21 kvargs: introduce a more flexible parsing function
In reply to Gaetan RivetThis function permits defining additional terminating characters, ending the parsing to arbitrary delimiters.
--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 25 +++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs.h | 30 ++++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 63 insertions(+)
lib/Makefile +1 -0
@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
lib/librte_kvargs/rte_kvargs.c +25 -0
@@ -180,3 +180,28 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +struct rte_kvargs * +rte_kvargs_parse2 (const char *args,const char *const valid_keys[], +const char *valid_ends) +{ +struct rte_kvargs *kvlist =NULL ; +char *copy; +size_t len; + +if (valid_ends ==NULL ) +return rte_kvargs_parse (args, valid_keys); + + copy =strdup (args); +if (copy ==NULL ) +return NULL ; + + len =strcspn (copy, valid_ends); + copy[len] ='\0' ; + + kvlist =rte_kvargs_parse (copy, valid_keys); + +free (copy); +return kvlist; +}
lib/librte_kvargs/rte_kvargs.h +30 -0
@@ -72,6 +72,36 @@ struct rte_kvargs *rte_kvargs_parse(const char *args, const char *const valid_keys[]);/** +* Allocate a rte_kvargs and store key/value associations from a string. +* This version will consider any byte from valid_ends as a possible +* terminating character, and will not parse beyond any of their occurence. +* +* The function allocates and fills an rte_kvargs structure from a given +* string whose format is key1=value1,key2=value2,... +* +* The structure can be freed with rte_kvargs_free(). +* +* @param args +* The input string containing the key/value associations +* +* @param valid_keys +* A list of valid keys (table of const char *, the last must be NULL). +* This argument is ignored if NULL +* +* @param valid_ends +* Acceptable terminating characters. +* If NULL, the behavior is the same as ``rte_kvargs_parse``. +* +* @return +* - A pointer to an allocated rte_kvargs structure on success +* - NULL on error +*/ +__rte_experimental +struct rte_kvargs *rte_kvargs_parse2(const char *args, +const char *const valid_keys[], +const char *valid_ends); + +/** * Free a rte_kvargs structure * * Free a rte_kvargs structure previously allocated with
lib/librte_kvargs/rte_kvargs_version.map +7 -0
@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_parse2; + +} DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v8 4/21 eal: introduce dtor macros
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
lib/librte_eal/common/include/rte_common.h +23 -0
@@ -112,6 +112,29 @@ static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)RTE_INIT_PRIO (func,LAST )/** +* Run after main() with low priority. +* +* @param func +* Destructor function name. +* @param prio +* Priority number must be above 100. +* Lowest number is the last to run. + */ +#define RTE_FINI_PRIO (func, prio) \ +static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void) + +/** +* Run after main() with high priority. +* +* The destructor will be run *before* prioritized destructors. +* +* @param func +* Destructor function name. +*/ +#define RTE_FINI (func) \ + RTE_FINI_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v8 5/21 eal: introduce device class abstraction
In reply to Gaetan Rivet--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 +++++++++++++++ lib/librte_eal/common/include/rte_class.h | 121 +++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 2 + 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -52,6 +52,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
lib/librte_eal/common/Makefile +1 -1
@@ -11,7 +11,7 @@ INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_string_fns.h rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h
lib/librte_eal/common/eal_common_class.c new file +62 -0
62 lines not on this page · raw message
lib/librte_eal/common/include/rte_class.h new file +121 -0
121 lines not on this page · raw message
lib/librte_eal/common/include/rte_common.h +1 -0
@@ -83,6 +83,7 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_CLASS 120#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
lib/librte_eal/rte_eal_version.map +2 -0
@@ -244,6 +244,8 @@ DPDK_18.05 { EXPERIMENTAL { global: + rte_class_register; + rte_class_unregister; rte_ctrl_thread_create; rte_dev_event_callback_register; rte_dev_event_callback_unregister;
Signature · 1 line
2.11.0
PATCH v8 6/21 eal/class: register destructor
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 5 +++++ 1 file changed, 5 insertions(+)
lib/librte_eal/common/include/rte_class.h +5 -0
@@ -112,6 +112,11 @@ static void classinitfn_ ##nm(void) \ {\ (cls).name =RTE_STR (nm);\rte_class_register (&cls); \ +} \ +RTE_FINI_PRIO(classfinifn_ ##nm, CLASS); \ +static void classfinifn_ ##nm(void) \ +{ \ + rte_class_unregister(&cls); \ }#ifdef __cplusplus
Signature · 1 line
2.11.0
PATCH v8 7/21 devargs: add function to parse device layers
In reply to Gaetan RivetThis function is private to the EAL.
It is used to parse each layers in a device description string, and store the result in an rte_devargs structure.
--- lib/librte_eal/common/eal_common_devargs.c | 144 ++++++++++++++++++++++++++++ lib/librte_eal/common/eal_private.h | 27 ++++++ lib/librte_eal/common/include/rte_devargs.h | 13 ++- 3 files changed, 181 insertions(+), 3 deletions(-)
lib/librte_eal/common/eal_common_devargs.c +144 -0
@@ -13,9 +13,13 @@#include <string.h> #include <stdarg.h> +#include <rte_bus.h> +#include <rte_class.h> #include <rte_compat.h> #include <rte_dev.h> #include <rte_devargs.h> +#include <rte_kvargs.h> +#include <rte_errno.h> #include <rte_tailq.h> #include "eal_private.h"
@@ -56,6 +60,146 @@ rte_eal_parse_devargs_str(const char *devargs_str,return 0 ; } +static size_t +devargs_layer_count (const char *s) +{ +size_t i = s ?1 :0 ; + +while (s !=NULL && s[0 ] !='\0' ) { + i += s[0 ] =='/' ; + s++; + } +return i; +} + +int +rte_devargs_layers_parse (struct rte_devargs *da, +const char *devstr) +{ +struct { +const char *key; +const char *str; +struct rte_kvargs *kvlist; + } layers[] = { + {"bus=" ,NULL ,NULL , }, + {"class=" ,NULL ,NULL , }, + {"driver=" ,NULL ,NULL , }, + }; +struct rte_kvargs_pair *kv =NULL ; +struct rte_class *cls =NULL ; +struct rte_bus *bus =NULL ; +const char *s = devstr; +size_t nblayer; +size_t i =0 ; +int ret =0 ; + +/* Split each sub-lists. */ + nblayer =devargs_layer_count (devstr); +if (nblayer >RTE_DIM (layers)) { +RTE_LOG (ERR ,EAL ,"Invalid format: too many layers (%zu)\n" , + nblayer); + ret = -E2BIG ; + goto get_out; + } + +/* If the devargs points the devstr +* as source data, then it should not allocate +* anything and keep referring only to it. +*/ +if (da->data != devstr) { + da->data =strdup (devstr); +if (da->data ==NULL ) { +RTE_LOG (ERR ,EAL ,"OOM\n" ); + ret = -ENOMEM ; + goto get_out; + } + s = da->data; + } + +while (s !=NULL ) { +if (strncmp (layers[i].key, s, +strlen (layers[i].key)) && +/* The last layer is free-form. +* The "driver" key is not required (but accepted). +*/ + i !=RTE_DIM (layers) -1 ) + goto next_layer; + layers[i].str = s; + layers[i].kvlist =rte_kvargs_parse2 (s,NULL ,"/" ); +if (layers[i].kvlist ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not parse %s\n" , s); + ret = -EINVAL ; + goto get_out; + } + s =strchr (s,'/' ); +if (s !=NULL ) + s++; +next_layer: +if (i >=RTE_DIM (layers)) { +RTE_LOG (ERR ,EAL ,"Unrecognized layer %s\n" , s); + ret = -EINVAL ; + goto get_out; + } + i++; + } + +/* Parse each sub-list. */ +for (i =0 ; i <RTE_DIM (layers); i++) { +if (layers[i].kvlist ==NULL ) +continue ; + kv = &layers[i].kvlist->pairs[0 ]; +if (strcmp (kv->key,"bus" ) ==0 ) { + bus =rte_bus_find_by_name (kv->value); +if (bus ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not find bus \"%s\"\n" , + kv->value); + ret = -EFAULT ; + goto get_out; + } + }else if (strcmp (kv->key,"class" ) ==0 ) { + cls =rte_class_find_by_name (kv->value); +if (cls ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not find class \"%s\"\n" , + kv->value); + ret = -EFAULT ; + goto get_out; + } + }else if (strcmp (kv->key,"driver" ) ==0 ) { +/* Ignore */ +continue ; + } + } + +/* Fill devargs fields. */ + da->busstr = layers[0 ].str; + da->clsstr = layers[1 ].str; + da->drvstr = layers[2 ].str; + da->bus = bus; + da->cls = cls; + +/* If we own the data, clean up a bit +* the several layers string, to ease +* their parsing afterward. +*/ +if (da->data != devstr) { +char *s = (void *)(intptr_t )(da->data); + +while ((s =strchr (s,'/' ))) { + *s ='\0' ; + s++; + } + } + +get_out: +for (i =0 ; i <RTE_DIM (layers); i++) { +if (layers[i].kvlist) +rte_kvargs_free (layers[i].kvlist); + } +if (ret !=0 ) + rte_errno = -ret; +return ret; +} +static int bus_name_cmp (const struct rte_bus *bus,const void *name) {
lib/librte_eal/common/eal_private.h +27 -0
@@ -258,4 +258,31 @@ int rte_mp_channel_init(void);*/ void dev_callback_process (char *device_name,enum rte_dev_event_type event); +/** +* @internal +* Parse a device string and store its information in an +* rte_devargs structure. +* +* Note: if the "data" field of da points to devstr, +* then no dynamic allocation is performed and the rte_devargs +* can be safely discarded. +* +* Otherwise ``data`` will hold a workable copy of devstr, that will be +* used by layers descriptors within rte_devargs. In this case, +* any rte_devargs should be cleaned-up before being freed. +* +* @param da +* rte_devargs structure to fill. +* +* @param devstr +* Device string. +* +* @return +* 0 on success. +* Negative errno values on error (rte_errno is set). +*/ +int +rte_devargs_layers_parse (struct rte_devargs *da, +const char *devstr); +#endif /* _EAL_PRIVATE_H_ */
lib/librte_eal/common/include/rte_devargs.h +10 -3
@@ -51,12 +51,19 @@ struct rte_devargs {enum rte_devtype type;/** Device policy. */ enum rte_dev_policy policy; -/** Bus handle for the device. */ -struct rte_bus *bus;/** Name of the device. */ char name[RTE_DEV_NAME_MAX_LEN ]; +RTE_STD_C11 + union {/** Arguments string as given by user or "" for no argument. */ -char *args; +char *args; +const char *drvstr; + }; +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< bus-related part of device string. */ +const char *data;/**< Device string storage. */ };/**
Signature · 1 line
2.11.0
PATCH v8 8/21 eal/dev: add device iterator interface
In reply to Gaetan RivetA device iterator allows iterating over a set of devices. This set is defined by the two descriptions offered,
* rte_bus
* rte_class
Only one description can be provided, or both. It is not allowed to provide no description at all.
Each layer of abstraction then performs a filter based on the description provided. This filtering allows iterating on their internal set of devices, stopping when a match is valid and returning the current iteration context.
This context allows starting the next iteration from the same point and going forward.
--- lib/librte_eal/common/include/rte_dev.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
lib/librte_eal/common/include/rte_dev.h +47 -0
@@ -285,6 +285,53 @@ __attribute__((used)) = str static const char DRV_EXP_TAG(name, kmod_dep_export)[] \ __attribute__((used)) = str +/** +* Iteration context. +* +* This context carries over the current iteration state. +*/ +struct rte_dev_iterator { +const char *devstr;/**< device string. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< class-related part of device string. */ +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +struct rte_device *device;/**< current position. */ +void *class_device;/**< additional specialized context. */ +}; + +/** +* Device iteration function. +* +* Find the next device matching properties passed in parameters. +* The function takes an additional ``start`` parameter, that is +* used as starting context when relevant. +* +* The function returns the current element in the iteration. +* This return value will potentially be used as a start parameter +* in subsequent calls to the function. +* +* The additional iterator parameter is only there if a specific +* implementation needs additional context. It must not be modified by +* the iteration function itself. +* +* @param start +* Starting iteration context. +* +* @param devstr +* Device description string. +* +* @param it +* Device iterator. +* +* @return +* The address of the current element matching the device description +* string. +*/ +typedef void *(*rte_dev_iterate_t )(const void *start, +const char *devstr, +const struct rte_dev_iterator *it); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v8 9/21 eal/class: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_class.h +1 -0
@@ -30,6 +30,7 @@ TAILQ_HEAD(rte_class_list, rte_class);struct rte_class {TAILQ_ENTRY (rte_class) next;/**< Next device class in linked list */ const char *name;/**< Name of the class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v8 10/21 eal/bus: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_bus.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_bus.h +1 -0
@@ -211,6 +211,7 @@ struct rte_bus {rte_bus_parse_t parse;/**< Parse a device name */ struct rte_bus_conf conf;/**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class;/**< Get iommu class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v8 11/21 eal/dev: implement device iteration initialization
In reply to Gaetan RivetParse a device description.
Split this description in their relevant part for each layers. No dynamic allocation is performed.
--- lib/Makefile | 1 + lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_dev.c | 55 +++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 24 ++++++++++++++ lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 1 + 6 files changed, 83 insertions(+)
lib/Makefile +1 -0
@@ -7,6 +7,7 @@ DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal +DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -18,6 +18,7 @@ CFLAGS += $(WERROR_FLAGS) -O3 LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s +LDLIBS += -lrte_kvargs EXPORT_MAP := ../../rte_eal_version.map
lib/librte_eal/common/eal_common_dev.c +55 -0
67 lines not on this page · raw message
lib/librte_eal/common/include/rte_dev.h +24 -0
@@ -332,6 +332,30 @@ typedef void *(*rte_dev_iterate_t)(const void *start,const char *devstr, const struct rte_dev_iterator *it); +/** +* Initializes a device iterator. +* +* This iterator allows accessing a list of devices matching a criteria. +* The device matching is made among all buses and classes currently registered, +* filtered by the device description given as parameter. +* +* This function will not allocate any memory. It is safe to stop the +* iteration at any moment and let the iterator go out of context. +* +* @param it +* Device iterator handle. +* +* @param str +* Device description string. +* +* @return +* 0 on successful initialization. +* <0 on error. +*/ +__rte_experimental +int +rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -27,6 +27,7 @@ LDLIBS += -lrt ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif +LDLIBS += -lrte_kvargs # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
lib/librte_eal/rte_eal_version.map +1 -0
@@ -251,6 +251,7 @@ EXPERIMENTAL { rte_dev_event_callback_unregister; rte_dev_event_monitor_start; rte_dev_event_monitor_stop; + rte_dev_iterator_init; rte_devargs_add; rte_devargs_dump; rte_devargs_insert;
Signature · 1 line
2.11.0
PATCH v8 12/21 eal/dev: implement device iteration
In reply to Gaetan RivetUse the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists.
--- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+)
lib/librte_eal/common/eal_common_dev.c +168 -0
@@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs;/* spinlock for device callbacks */ static rte_spinlock_t dev_event_lock =RTE_SPINLOCK_INITIALIZER ; +struct dev_next_ctx { +struct rte_dev_iterator *it; +const char *busstr; +const char *clsstr; +}; + +#define CTX (it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) +static int cmp_detached_dev_name (const struct rte_device *dev,const void *_name) {
@@ -398,3 +420,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, get_out:return -rte_errno; } + +static char * +dev_str_sane_copy (const char *str) +{ +size_t end; +char *copy; + + end =strcspn (str,",/" ); +if (str[end] ==',' ) { + copy =strdup (&str[end +1 ]); + }else { +/* '/' or '\0' */ + copy =strdup ("" ); + } +if (copy ==NULL ) { + rte_errno =ENOMEM ; + }else { +char *slash; + + slash =strchr (copy,'/' ); +if (slash !=NULL ) + slash[0 ] ='\0' ; + } +return copy; +} + +static int +class_next_dev_cmp (const struct rte_class *cls, +const void *ctx) +{ +struct rte_dev_iterator *it; +const char *clsstr =NULL ; +void *dev; + +if (cls->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + clsstr =CLSCTX (ctx); + dev = it->class_device; +/* it->clsstr != NULL means a class +* was specified in the devstr. +*/ +if (it->clsstr !=NULL && cls != it->cls) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; + dev = cls->dev_iterate (dev, clsstr, it); + it->class_device = dev; +return dev ==NULL ; +} + +static int +bus_next_dev_cmp (const struct rte_bus *bus, +const void *ctx) +{ +struct rte_device *dev =NULL ; +struct rte_class *cls =NULL ; +struct rte_dev_iterator *it; +const char *busstr =NULL ; + +if (bus->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + busstr =BUSCTX (ctx); + dev = it->device; +/* it->busstr != NULL means a bus +* was specified in the devstr. +*/ +if (it->busstr !=NULL && bus != it->bus) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; +if (it->clsstr ==NULL ) { + dev = bus->dev_iterate (dev, busstr, it); + goto end; + } +/* clsstr != NULL */ +if (dev ==NULL ) { +next_dev_on_bus: + dev = bus->dev_iterate (dev, busstr, it); + it->device = dev; + } +if (dev ==NULL ) +return 1 ; +if (it->cls !=NULL ) + cls =TAILQ_PREV (it->cls, rte_class_list, next); + cls =rte_class_find (cls, class_next_dev_cmp, ctx); +if (cls !=NULL ) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; +return dev ==NULL ; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it) +{ +struct rte_bus *bus =NULL ; +int old_errno = rte_errno; +char *busstr =NULL ; +char *clsstr =NULL ; + + rte_errno =0 ; +if (it->busstr ==NULL && it->clsstr ==NULL ) { +/* Invalid iterator. */ + rte_errno =EINVAL ; +return NULL ; + } +if (it->bus !=NULL ) + bus =TAILQ_PREV (it->bus, rte_bus_list, next); +if (it->busstr !=NULL ) { + busstr =dev_str_sane_copy (it->busstr); +if (busstr ==NULL ) + goto out; + } +if (it->clsstr !=NULL ) { + clsstr =dev_str_sane_copy (it->clsstr); +if (clsstr ==NULL ) + goto out; + } +while ((bus =rte_bus_find (bus, bus_next_dev_cmp, +CTX (it, busstr, clsstr)))) { +if (it->device !=NULL ) { + it->bus = bus; + goto out; + } +if (it->busstr !=NULL || + rte_errno !=0 ) +break ; + } +if (rte_errno ==0 ) + rte_errno = old_errno; +out: +free (busstr); +free (clsstr); +return it->device; +}
lib/librte_eal/common/include/rte_dev.h +26 -0
@@ -356,6 +356,32 @@ __rte_experimentalint rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); +/** +* Iterates on a device iterator. +* +* Generates a new rte_device handle corresponding to the next element +* in the list described in comprehension by the iterator. +* +* The next object is returned, and the iterator is updated. +* +* @param it +* Device iterator handle. +* +* @return +* An rte_device handle if found. +* NULL if an error occurred (rte_errno is set). +* NULL if no device could be found (rte_errno is not set). +*/ +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH (dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus }#endif
lib/librte_eal/rte_eal_version.map +1 -0
@@ -252,6 +252,7 @@ EXPERIMENTAL { rte_dev_event_monitor_start; rte_dev_event_monitor_stop; rte_dev_iterator_init; + rte_dev_iterator_next; rte_devargs_add; rte_devargs_dump; rte_devargs_insert;
Signature · 1 line
2.11.0
PATCH v8 13/21 kvargs: add generic string matching callback
In reply to Gaetan RivetThis function can be used as a callback torte_kvargs_process.
This should reduce code duplication.
--- lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 1 + 3 files changed, 39 insertions(+)
lib/librte_kvargs/rte_kvargs.c +10 -0
@@ -205,3 +205,13 @@ rte_kvargs_parse2(const char *args, const char * const valid_keys[],free (copy);return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -abs (strcmp (str, value)); +}
lib/librte_kvargs/rte_kvargs.h +28 -0
@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32
@@ -151,6 +153,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* +* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. +*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif
lib/librte_kvargs/rte_kvargs_version.map +1 -0
@@ -13,5 +13,6 @@ EXPERIMENTAL { global: rte_kvargs_parse2; + rte_kvargs_strcmp; } DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v8 14/21 bus/pci: implement device iteration and comparison
In reply to Gaetan Rivet--- drivers/bus/pci/Makefile | 3 ++- drivers/bus/pci/pci_common.c | 3 +-- drivers/bus/pci/pci_params.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ drivers/bus/pci/private.h | 25 +++++++++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 drivers/bus/pci/pci_params.c
drivers/bus/pci/Makefile +2 -1
@@ -26,10 +26,11 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring -LDLIBS += -lrte_ethdev -lrte_pci +LDLIBS += -lrte_ethdev -lrte_pci -lrte_kvargs include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS)) +SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_params.c SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_common.c SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_common_uio.c
drivers/bus/pci/pci_common.c +1 -2
@@ -26,8 +26,6 @@#include "private.h" -extern struct rte_pci_bus rte_pci_bus; -#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"const char *rte_pci_get_sysfs_path (void )
@@ -502,6 +500,7 @@ struct rte_pci_bus rte_pci_bus = { .unplug = pci_unplug, .parse = pci_parse, .get_iommu_class = rte_pci_get_iommu_class, + .dev_iterate = rte_pci_dev_iterate, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
drivers/bus/pci/pci_params.c new file +53 -0
53 lines not on this page · raw message
drivers/bus/pci/private.h +25 -0
@@ -10,6 +10,8 @@#include <rte_pci.h> #include <rte_bus_pci.h> +extern struct rte_pci_bus rte_pci_bus; +struct rte_pci_driver ;struct rte_pci_device ;
@@ -216,4 +218,27 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,enum rte_iova_mode rte_pci_get_iommu_class (void ); +/* +* Iterate over internal devices, +* matching any device against the provided +* string. +* +* @param start +* Iteration starting point. +* +* @param str +* Device string to match against. +* +* @param it +* (unused) iterator structure. +* +* @return +* A pointer to the next matching device if any. +* NULL otherwise. +*/ +void * +rte_pci_dev_iterate (const void *start, +const char *str, +const struct rte_dev_iterator *it); +#endif /* _PCI_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v8 15/21 bus/pci: add device matching field id
In reply to Gaetan RivetThe PCI bus can now parse a matching field "id" as follows:
"bus=pci,id=0000:00:00.0"
or
"bus=pci,id=00:00.0"
--- drivers/bus/pci/pci_params.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
drivers/bus/pci/pci_params.c +27 -2
@@ -3,6 +3,7 @@*/ #include <rte_bus.h> +#include <rte_bus_pci.h> #include <rte_dev.h> #include <rte_errno.h> #include <rte_kvargs.h>
@@ -11,21 +12,45 @@#include "private.h" enum pci_params { +RTE_PCI_PARAMS_ID ,RTE_PCI_PARAMS_MAX , };static const char *const pci_params_keys[] = { + [RTE_PCI_PARAMS_ID ] ="id" , [RTE_PCI_PARAMS_MAX ] =NULL , };static int +pci_addr_kv_cmp(const char *key __rte_unused, +const char *value, +void *_addr2) +{ +struct rte_pci_addr _addr1; +struct rte_pci_addr *addr1 = &_addr1; +struct rte_pci_addr *addr2 = _addr2; + +if (rte_pci_addr_parse (value, addr1)) +return -1 ; +return -abs (rte_pci_addr_cmp (addr1, addr2)); +} + +static int pci_dev_match (const struct rte_device *dev,const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_pci_device *pdev; - (void ) dev; - (void ) kvlist; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + pdev =RTE_DEV_TO_PCI_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"id" , + &pci_addr_kv_cmp, + (void *)(intptr_t )&pdev->addr)) +return 1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v8 16/21 bus/vdev: implement device iteration
In reply to Gaetan Rivet--- drivers/bus/vdev/Makefile | 3 ++- drivers/bus/vdev/vdev.c | 10 ++++---- drivers/bus/vdev/vdev_params.c | 51 +++++++++++++++++++++++++++++++++++++++++ drivers/bus/vdev/vdev_private.h | 26 +++++++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 drivers/bus/vdev/vdev_params.c create mode 100644 drivers/bus/vdev/vdev_private.h
drivers/bus/vdev/Makefile +2 -1
@@ -19,8 +19,9 @@ EXPORT_MAP := rte_bus_vdev_version.map LIBABIVER := 1 SRCS-y += vdev.c +SRCS-y += vdev_params.c -LDLIBS += -lrte_eal +LDLIBS += -lrte_eal -lrte_kvargs # # Export include files
drivers/bus/vdev/vdev.c +6 -4
@@ -23,6 +23,7 @@#include "rte_bus_vdev.h" #include "vdev_logs.h" +#include "vdev_private.h" #define VDEV_MP_KEY "bus_vdev_mp"
@@ -493,9 +494,9 @@ vdev_probe(void)return ret; } -static struct rte_device * -vdev_find_device (const struct rte_device *start,rte_dev_cmp_t cmp, -const void *data) +struct rte_device * +rte_vdev_find_device (const struct rte_device *start,rte_dev_cmp_t cmp, +const void *data) {const struct rte_vdev_device *vstart;struct rte_vdev_device *dev;
@@ -532,10 +533,11 @@ vdev_unplug(struct rte_device *dev)static struct rte_bus rte_vdev_bus = { .scan = vdev_scan, .probe = vdev_probe, - .find_device = vdev_find_device, + .find_device = rte_vdev_find_device, .plug = vdev_plug, .unplug = vdev_unplug, .parse = vdev_parse, + .dev_iterate = rte_vdev_dev_iterate, };RTE_REGISTER_BUS (vdev, rte_vdev_bus);
drivers/bus/vdev/vdev_params.c new file +51 -0
51 lines not on this page · raw message
drivers/bus/vdev/vdev_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright 2018 Gaëtan Rivet +*/ + +#ifndef _VDEV_PRIVATE_H_ +#define _VDEV_PRIVATE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct rte_device * +rte_vdev_find_device (const struct rte_device *start, +rte_dev_cmp_t cmp, +const void *data); + +void * +rte_vdev_dev_iterate (const void *start, +const char *str, +const struct rte_dev_iterator *it); + +#ifdef __cplusplus +} +#endif + +#endif /* _VDEV_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v8 17/21 bus/vdev: add device matching field driver
In reply to Gaetan RivetThe vdev bus parses a field "driver", matching
a vdev driver name with one passed as follows:
"bus=vdev,driver=xxxx"
--- drivers/bus/vdev/vdev_params.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/bus/vdev/vdev_params.c +13 -2
@@ -4,6 +4,7 @@#include <rte_dev.h> #include <rte_bus.h> +#include <rte_bus_vdev.h> #include <rte_kvargs.h> #include <rte_errno.h>
@@ -11,10 +12,12 @@#include "vdev_private.h" enum vdev_params { +RTE_VDEV_PARAMS_DRIVER ,RTE_VDEV_PARAMS_MAX , };static const char *const vdev_params_keys[] = { + [RTE_VDEV_PARAMS_DRIVER ] ="driver" , [RTE_VDEV_PARAMS_MAX ] =NULL , };
@@ -23,9 +26,17 @@ vdev_dev_match(const struct rte_device *dev, const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_vdev_device *vdev; - (void ) kvlist; - (void ) dev; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + vdev =RTE_DEV_TO_VDEV_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"driver" , + rte_kvargs_strcmp, + (void *)(intptr_t )vdev->device.driver->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v8 18/21 ethdev: add private generic device iterator
In reply to Gaetan RivetThis iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to librte_ethdev.
--- lib/librte_ethdev/Makefile | 1 + lib/librte_ethdev/eth_private.c | 31 +++++++++++++++++++++++++++++++ lib/librte_ethdev/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 lib/librte_ethdev/eth_private.c create mode 100644 lib/librte_ethdev/eth_private.h
lib/librte_ethdev/Makefile +1 -0
@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c
lib/librte_ethdev/eth_private.c new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *start,rte_eth_cmp_t cmp, +const void *data) +{ +struct rte_eth_dev *edev; +ptrdiff_t idx; + +/* Avoid Undefined Behaviour */ +if (start !=NULL && + (start < &rte_eth_devices[0 ] || + start > &rte_eth_devices[RTE_MAX_ETHPORTS ])) +return NULL ; +if (start !=NULL ) + idx = start - &rte_eth_devices[0 ] +1 ; +else + idx =0 ; +for (; idx <RTE_MAX_ETHPORTS ; idx++) { + edev = &rte_eth_devices[idx]; +if (cmp (edev, data) ==0 ) +return edev; + } +return NULL ; +} +
lib/librte_ethdev/eth_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#ifndef _RTE_ETH_PRIVATE_H_ +#define _RTE_ETH_PRIVATE_H_ + +#include "rte_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic rte_eth_dev comparison function. */ +typedef int (*rte_eth_cmp_t )(const struct rte_eth_dev *,const void *); + +/* Generic rte_eth_dev iterator. */ +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *_start,rte_eth_cmp_t cmp, +const void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ETH_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v8 19/21 ethdev: register ether layer as a class
In reply to Gaetan Rivet--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 lib/librte_ethdev/rte_class_eth.c
lib/librte_ethdev/Makefile +2 -1
@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
lib/librte_ethdev/rte_class_eth.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH v8 20/21 ethdev: add device matching field name
In reply to Gaetan RivetThe eth device class can now parse a field name,
matching the eth_dev name with one passed as
"class=eth,name=xxxxxx"
--- lib/librte_ethdev/rte_class_eth.c | 7 +++++++ 1 file changed, 7 insertions(+)
lib/librte_ethdev/rte_class_eth.c +7 -0
@@ -15,10 +15,12 @@#include "eth_private.h" enum eth_params { +RTE_ETH_PARAMS_NAME ,RTE_ETH_PARAMS_MAX , };static const char *const eth_params_keys[] = { + [RTE_ETH_PARAMS_NAME ] ="name" , [RTE_ETH_PARAMS_MAX ] =NULL , };
@@ -39,6 +41,7 @@ eth_dev_match(const struct rte_eth_dev *edev, {const struct eth_dev_match_arg *arg = _arg;const struct rte_kvargs *kvlist = arg->kvlist; +struct rte_eth_dev_data *data;if (edev->state ==RTE_ETH_DEV_UNUSED )return -1 ;
@@ -47,6 +50,10 @@ eth_dev_match(const struct rte_eth_dev *edev,if (kvlist ==NULL )/* Empty string matches everything. */ return 0 ; + data = edev->data; +if (rte_kvargs_process (kvlist,"name" , + rte_kvargs_strcmp, data->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v8 21/21 app/testpmd: add show device command
In reply to Gaetan RivetA new interactive command is offered:
show device <device description>
This commands lists all rte_device element matching the device description. e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0
These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
--- app/test-pmd/cmdline.c | 51 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 ++++++++++++++ 2 files changed, 75 insertions(+)
app/test-pmd/cmdline.c +51 -0
@@ -7083,6 +7083,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) +{ +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) +{ +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;
@@ -17262,6 +17312,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall,
doc/guides/testpmd_app_ug/testpmd_funcs.rst +24 -0
@@ -2628,6 +2628,30 @@ set the traffic management default hierarchy on the port:: testpmd> set port tm hierarchy default (port_id) +Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and ``class`` + drivers. + Filter Functions ----------------
Signature · 1 line
2.11.0
Re: [PATCH v8 21/21] app/testpmd: add show device command
Hi Gaetan,
Quoted 136 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Tuesday, June 26, 2018 5:56 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the device description. e.g.:show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 51 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 ++++++++++++++ 2 files changed, 75 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
27e2aa8c8..872492b88100644app/test-pmd/cmdline.c +49
-0@@ -7083,6 +7083,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;@@ -17262,6 +17312,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, diff --git
a/doc/guides/testpmd_app_ug/testpmd_funcs.rstb/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index0d6fd50ca..4f1009a3a100644doc/guides/testpmd_app_ug/testpmd_funcs.rst +0
-0@@ -2628,6 +2628,30 @@ set the traffic management default hierarchy onthe port::
testpmd> set port tm hierarchy default (
port_id)doc/guides/testpmd_app_ug/testpmd_funcs.rst +24
-1+Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and + ``class`` drivers. + Filter Functions ---------------- --
Quoted 1 line
2.11.0
This patch fails to compile on the latest 18_08 master branch.
There is no update to the internal testpmd documentation about this new command.
Regards,
Bernard.
Re: [PATCH v8 21/21] app/testpmd: add show device command
Hi Bernard,
Quoted 137 lines · Bernard
Hi Gaetan,
Quoted 135 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Tuesday, June 26, 2018 5:56 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the device description. e.g.:show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 51 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 ++++++++++++++ 2 files changed, 75 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
27e2aa8c8..872492b88100644app/test-pmd/cmdline.c +49
-0@@ -7083,6 +7083,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;@@ -17262,6 +17312,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, diff --git
a/doc/guides/testpmd_app_ug/testpmd_funcs.rstb/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index0d6fd50ca..4f1009a3a100644doc/guides/testpmd_app_ug/testpmd_funcs.rst +0
-0@@ -2628,6 +2628,30 @@ set the traffic management default hierarchy onthe port::
testpmd> set port tm hierarchy default (
port_id)doc/guides/testpmd_app_ug/testpmd_funcs.rst +24
-0+Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and + ``class`` drivers. + Filter Functions ----------------
Quoted 5 lines
Quoted 2 lines
--
2.11.0This patch fails to compile on the latest 18_08 master branch.
I had it rebased a few days ago, it was fine. It seems there has been some movement lately, will rebase again.
Quoted 2 lines
There is no update to the internal testpmd documentation about this new command.
There is some documentation added todoc/guides/testpmd_app_ug/testpmd_funcs.rst
Are you referring to some other kind of documentation?
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v8 21/21] app/testpmd: add show device command
Hi Gaetan,
Quoted 162 lines
-----Original Message-----
From: Gaëtan Rivet [mailto:[email protected]]
Sent: Thursday, June 28, 2018 11:10 AM
To: Iremonger, Bernard <[email protected]>
Cc: [email protected]
Subject: Re: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandHi Bernard,
Quoted 15 lines · Bernard
Hi Gaetan,
Quoted 13 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Tuesday, June 26, 2018 5:56 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the devicedescription.
Quoted 122 lines
Quoted 122 lines
e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 51 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 ++++++++++++++ 2 files changed, 75 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
27e2aa8c8..872492b88100644app/test-pmd/cmdline.c +49
-0@@ -7083,6 +7083,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;@@ -17262,6 +17312,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, diff --git
a/doc/guides/testpmd_app_ug/testpmd_funcs.rstb/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index0d6fd50ca..4f1009a3a100644doc/guides/testpmd_app_ug/testpmd_funcs.rst +0
-0@@ -2628,6 +2628,30 @@ set the traffic management default hierarchyon the port::
testpmd> set port tm hierarchy default (
port_id)doc/guides/testpmd_app_ug/testpmd_funcs.rst +24
-0+Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and + ``class`` drivers. + Filter Functions ----------------Quoted 5 lines
Quoted 2 lines
--
2.11.0This patch fails to compile on the latest 18_08 master branch.
I had it rebased a few days ago, it was fine. It seems there has been some movement lately, will rebase again.
Quoted 1 line
There is no update to the internal testpmd documentation about this new
command.
Quoted 1 line
Quoted 8 lines
There is some documentation added to
doc/guides/testpmd_app_ug/testpmd_funcs.rstAre you referring to some other kind of documentation?
--
Gaëtan Rivet
6WIND
There should be an update to the testpmd "help" command. See line 122 to 1133 in cmdline .c
Regards,
Bernard
Re: [PATCH v8 21/21] app/testpmd: add show device command
Quoted 174 lines · Bernard
Hi Gaetan,
Quoted 162 lines
-----Original Message-----
From: Gaëtan Rivet [mailto:[email protected]]
Sent: Thursday, June 28, 2018 11:10 AM
To: Iremonger, Bernard <[email protected]>
Cc: [email protected]
Subject: Re: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandHi Bernard,
Quoted 15 lines · Bernard
Hi Gaetan,
Quoted 13 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Gaetan Rivet
Sent: Tuesday, June 26, 2018 5:56 PM
To: [email protected]
Cc: Gaetan Rivet <[email protected]>
Subject: [dpdk-dev] [PATCH v8 21/21] app/testpmd: add show device commandA new interactive command is offered:
show device <device description>
This commands lists all
rte_deviceelement matching the devicedescription.
Quoted 122 lines
Quoted 122 lines
e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
Signed-off-by Gaetan Rivet <[email protected]>--- app/test-pmd/cmdline.c | 51 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 ++++++++++++++ 2 files changed, 75 insertions(+)app/test-pmd/cmdline.c index renamed from app/test-pmd/cmdline.c +0
-0
27e2aa8c8..872492b88100644app/test-pmd/cmdline.c +49
-0@@ -7083,6 +7083,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) { +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) { +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;@@ -17262,6 +17312,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, diff --git
a/doc/guides/testpmd_app_ug/testpmd_funcs.rstb/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index0d6fd50ca..4f1009a3a100644doc/guides/testpmd_app_ug/testpmd_funcs.rst +0
-0@@ -2628,6 +2628,30 @@ set the traffic management default hierarchyon the port::
testpmd> set port tm hierarchy default (
port_id)doc/guides/testpmd_app_ug/testpmd_funcs.rst +24
-0+Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and + ``class`` drivers. + Filter Functions ----------------Quoted 5 lines
Quoted 2 lines
--
2.11.0This patch fails to compile on the latest 18_08 master branch.
I had it rebased a few days ago, it was fine. It seems there has been some movement lately, will rebase again.
Quoted 1 line
There is no update to the internal testpmd documentation about this new
command.
Quoted 1 line
Quoted 8 lines
There is some documentation added to
doc/guides/testpmd_app_ug/testpmd_funcs.rstAre you referring to some other kind of documentation?
--
Gaëtan Rivet
6WIND
Quoted 7 lines
There should be an update to the testpmd "help" command. See line 122 to 1133 in cmdline .c
Regards,
Bernard
Ah, ok, I will update it.
Signature · 2 lines
Gaëtan Rivet 6WIND
Quoted 108 lines · Gaetan Rivet
This patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "
rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).* Both
rte_busandrte_classnow offer a way to
list their devices and filter the result
using locally defined properties.* The
rte_devAPI now has anrte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.As an example, the "eth" device class is implemented.
Additionally, the device filters for
+
rte_bus_pci
+rte_bus_vdev
+rte_class_ethare implemented and can be used with some
properties each, to show how to extend those.Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"---
v2:
* Reworked the
dev_iteratecallback to simplify
its implementation.Now
dev_iterateimplementation do not need to learn about the intricacies of therte_dev_iterator. Therte_dev_iteratoris managed purely by therte_dev_iterator_nextfunction. Buses and classes then do not have to care about settings things right.Additionally,
dev_iterateimplementations do not have to sanitize their dev string anymore, they are prepared by therte_devlayer prior, which also reduces the number of dynamic allocations.v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
usinglibrte_kvargsinstead.
* Reversed dependencies oflibrte_kvargsand
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
*rte_kvargsnow includesrte_ealdirectly and keepsrte_log.
* added generic string comparison function torte_kvargs, as some kind of comparison should probably be shared by many layers.v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private genericrte_eth_deviterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.v6:
* Rebased on master
* IntroduceRTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.v7:
* Rebased on master
* Fixrte_kvargs_strcmpreturn value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.v8:
Quoted 11 lines
* Rebased on master
* Cleaned kvargs use: introduced
a new parser function, that simplifies using the library for DPDK devargs.
* Refactored devargs parsing in a single function withinrte_devargs.
This function is useful both forrte_devparsing its iterator, and forrte_devargsparsing --dev parameters (not yet implemented).
* A few small bugfixes.
Hi Gaetan,
did you test building with shared library builds? I get build failures for shared libs after applying this set. It appears you may still have a circular dependency between EAL and kvargs libs.
/Bruce
Quoted 121 lines · Bruce Richardson
Quoted 108 lines · Gaetan Rivet
This patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "
rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).* Both
rte_busandrte_classnow offer a way to
list their devices and filter the result
using locally defined properties.* The
rte_devAPI now has anrte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.As an example, the "eth" device class is implemented.
Additionally, the device filters for
+
rte_bus_pci
+rte_bus_vdev
+rte_class_ethare implemented and can be used with some
properties each, to show how to extend those.Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"---
v2:
* Reworked the
dev_iteratecallback to simplify
its implementation.Now
dev_iterateimplementation do not need to learn about the intricacies of therte_dev_iterator. Therte_dev_iteratoris managed purely by therte_dev_iterator_nextfunction. Buses and classes then do not have to care about settings things right.Additionally,
dev_iterateimplementations do not have to sanitize their dev string anymore, they are prepared by therte_devlayer prior, which also reduces the number of dynamic allocations.v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
usinglibrte_kvargsinstead.
* Reversed dependencies oflibrte_kvargsand
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
*rte_kvargsnow includesrte_ealdirectly and keepsrte_log.
* added generic string comparison function torte_kvargs, as some kind of comparison should probably be shared by many layers.v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private genericrte_eth_deviterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.v6:
* Rebased on master
* IntroduceRTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.v7:
* Rebased on master
* Fixrte_kvargs_strcmpreturn value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.v8:
Quoted 11 lines
* Rebased on master
* Cleaned kvargs use: introduced
a new parser function, that simplifies using the library for DPDK devargs.
* Refactored devargs parsing in a single function withinrte_devargs.
This function is useful both forrte_devparsing its iterator, and forrte_devargsparsing --dev parameters (not yet implemented).
* A few small bugfixes.
Quoted 7 lines
Hi Gaetan,
did you test building with shared library builds? I get build failures for shared libs after applying this set. It appears you may still have a circular dependency between EAL and kvargs libs.
/Bruce
Hi Bruce,
Ha, yes, I forgot about that, there is a simple fix, I will update it. I have other fixes as well, a v9 is on its way.
Signature · 2 lines
Gaëtan Rivet 6WIND
v9 cover Device querying
In reply to Gaetan RivetThis patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).
* Both rte_bus and rte_class now offer a way to
list their devices and filter the result
using locally defined properties.
* The rte_dev API now has an rte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.
As an example, the "eth" device class is implemented.
Additionally, the device filters for
+ rte_bus_pci
+ rte_bus_vdev
+ rte_class_eth
are implemented and can be used with some
properties each, to show how to extend those.
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
---
v2:
* Reworked the dev_iterate callback to simplify
its implementation.
Now dev_iterate implementation do not need to learn about the intricacies of the rte_dev_iterator. The rte_dev_iterator is managed purely by the rte_dev_iterator_next function. Buses and classes then do not have to care about settings things right.
Additionally, dev_iterate implementations do not have to sanitize their dev string anymore, they are prepared by the rte_dev layer prior, which also reduces the number of dynamic allocations.
v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
using librte_kvargs instead.
* Reversed dependencies of librte_kvargs and
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.
v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
* rte_kvargs now includes rte_eal directly and keeps rte_log.
* added generic string comparison function to rte_kvargs, as some kind of comparison should probably be shared by many layers.
v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private generic rte_eth_dev iterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.
v6:
* Rebased on master
* Introduce RTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.
v7:
* Rebased on master
* Fix rte_kvargs_strcmp return value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.
v8:
* Rebased on master
* Cleaned kvargs use: introduced
a new parser function, that simplifies using the library for DPDK devargs.
* Refactored devargs parsing in a single function within rte_devargs.
This function is useful both for rte_dev parsing its iterator, and for rte_devargs parsing --dev parameters (not yet implemented).
* A few small bugfixes.
v9:
* Rebased on master
* Fixed cyclic dependency kvargs <-> eal
* Fixed a few checkpatch issues
* Added dynamic help to testpmd for new "show device" command
* Added devargs processing stubs to
primary buses / classes
* Added new --dev generic device declaration option
Gaetan Rivet (27):
devargs: add non-variadic parsing function
kvargs: remove error logs
kvargs: build before EAL
kvargs: introduce a more flexible parsing function
eal: introduce dtor macros
eal: introduce device class abstraction eal/class: register destructor
devargs: add function to parse device layers eal/dev: add device iterator interface eal/class: add device iteration
eal/bus: add device iteration
eal/dev: implement device iteration initialization eal/dev: implement device iteration
kvargs: add generic string matching callback bus/pci: implement device iteration and comparison bus/pci: add device matching field id bus/vdev: implement device iteration bus/vdev: add device matching field driver
ethdev: add private generic device iterator
ethdev: register ether layer as a class
ethdev: add device matching field name app/testpmd: add show device command bus/pci: pre-process declarative PCI devargs bus/vdev: pre-process declarative vdev devargs bus/pci: process declarative PCI devargs
ethdev: process declarative eth devargs
eal: add generic dev parameter
app/test-pmd/cmdline.c | 54 +++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 +++ drivers/bus/pci/Makefile | 3 +- drivers/bus/pci/bsd/pci.c | 5 + drivers/bus/pci/linux/pci.c | 5 + drivers/bus/pci/pci_common.c | 4 + drivers/bus/pci/pci_params.c | 143 ++++++++++++++++++ drivers/bus/pci/private.h | 54 +++++++ drivers/bus/vdev/Makefile | 3 +- drivers/bus/vdev/vdev.c | 20 ++- drivers/bus/vdev/vdev_params.c | 112 ++++++++++++++ drivers/bus/vdev/vdev_private.h | 32 ++++ drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/Makefile | 5 +- lib/librte_eal/bsdapp/eal/Makefile | 2 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 ++++++++ lib/librte_eal/common/eal_common_dev.c | 227 +++++++++++++++++++++++++++- lib/librte_eal/common/eal_common_devargs.c | 190 +++++++++++++++++++++-- lib/librte_eal/common/eal_common_options.c | 36 ++++- lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/common/eal_private.h | 27 ++++ lib/librte_eal/common/include/rte_bus.h | 1 + lib/librte_eal/common/include/rte_class.h | 127 ++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 24 +++ lib/librte_eal/common/include/rte_dev.h | 97 ++++++++++++ lib/librte_eal/common/include/rte_devargs.h | 53 ++++++- lib/librte_eal/linuxapp/eal/Makefile | 2 + lib/librte_eal/rte_eal_version.map | 5 + lib/librte_ethdev/Makefile | 4 +- lib/librte_ethdev/eth_private.c | 31 ++++ lib/librte_ethdev/eth_private.h | 31 ++++ lib/librte_ethdev/rte_class_eth.c | 147 ++++++++++++++++++ lib/librte_ethdev/rte_ethdev.c | 9 +- lib/librte_kvargs/Makefile | 2 +- lib/librte_kvargs/rte_kvargs.c | 57 ++++--- lib/librte_kvargs/rte_kvargs.h | 58 +++++++ lib/librte_kvargs/rte_kvargs_version.map | 8 + 39 files changed, 1615 insertions(+), 57 deletions(-) create mode 100644 drivers/bus/pci/pci_params.c create mode 100644 drivers/bus/vdev/vdev_params.c create mode 100644 drivers/bus/vdev/vdev_private.h create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h create mode 100644 lib/librte_ethdev/eth_private.c create mode 100644 lib/librte_ethdev/eth_private.h create mode 100644 lib/librte_ethdev/rte_class_eth.c
Signature · 1 line
2.11.0
PATCH v9 1/27 devargs: add non-variadic parsing function
rte_devargs_parse becomes non-variadic,rte_devargs_parsef becomes the variadic version, to be used to compose device strings.
--- drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 4 +-- lib/librte_eal/common/eal_common_devargs.c | 42 ++++++++++++++++++++++------- lib/librte_eal/common/include/rte_devargs.h | 40 +++++++++++++++++++++++++-- lib/librte_eal/rte_eal_version.map | 1 + lib/librte_ethdev/rte_ethdev.c | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)
drivers/net/failsafe/failsafe_args.c +1 -1
@@ -63,7 +63,7 @@ fs_parse_device(struct sub_device *sdev, char *args) d = &sdev->devargs;DEBUG ("%s" , args); - ret =rte_devargs_parse (d,"%s" , args); + ret =rte_devargs_parse (d, args);if (ret) {DEBUG ("devargs parsing failed with code %d" , ret);return ret;
drivers/net/failsafe/failsafe_eal.c +1 -1
@@ -86,7 +86,7 @@ fs_bus_init(struct rte_eth_dev *dev)else snprintf (devstr,sizeof (devstr),"%s" , rte_eth_devices[pid].device->name); - ret =rte_devargs_parse (da,"%s" , devstr); + ret =rte_devargs_parse (da, devstr);if (ret) {ERROR ("Probed devargs parsing failed with code" " %d" , ret);
lib/librte_eal/common/eal_common_dev.c +2 -2
@@ -138,8 +138,8 @@ int __rte_experimental rte_eal_hotplug_add(const char *busname, const char *devnif (da ==NULL )return -ENOMEM ; - ret =rte_devargs_parse (da,"%s:%s,%s" , - busname, devname, devargs); + ret =rte_devargs_parsef (da,"%s:%s,%s" , + busname, devname, devargs);if (ret) goto err_devarg;
lib/librte_eal/common/eal_common_devargs.c +32 -10
69 lines not on this page · raw message
lib/librte_eal/common/include/rte_devargs.h +38 -2
@@ -96,6 +96,42 @@ int rte_eal_parse_devargs_str(const char *devargs_str,* in argument. Store which bus will handle the device, its name * and the eventual device parameters. * +* The syntax is: +* +* bus:device_identifier,arg1=val1,arg2=val2 +* +* where "bus:" is the bus name followed by any character separator. +* The bus name is optional. If no bus name is specified, each bus +* will attempt to recognize the device identifier. The first one +* to succeed will be used. +* +* Examples: +* +* pci:0000:05.00.0,arg=val +* 05.00.0,arg=val +* vdev:net_ring0 +* +* @param da +* The devargs structure holding the device information. +* +* @param dev +* String describing a device. +* +* @return +* - 0 on success. +* - Negative errno on error. +*/ +__rte_experimental +int +rte_devargs_parse (struct rte_devargs *da,const char *dev); + +/** +* Parse a device string. +* +* Verify that a bus is capable of handling the device passed +* in argument. Store which bus will handle the device, its name +* and the eventual device parameters. +* * The device string is built with a printf-like syntax. * * The syntax is:
@@ -124,8 +160,8 @@ int rte_eal_parse_devargs_str(const char *devargs_str,*/ __rte_experimental int -rte_devargs_parse (struct rte_devargs *da, -const char *format, ...) +rte_devargs_parsef (struct rte_devargs *da, +const char *format, ...) __attribute__((format (printf,2 ,0 )));/**
lib/librte_eal/rte_eal_version.map +1 -0
@@ -254,6 +254,7 @@ EXPERIMENTAL { rte_devargs_insert; rte_devargs_next; rte_devargs_parse; + rte_devargs_parsef; rte_devargs_remove; rte_devargs_type_count; rte_eal_cleanup;
lib/librte_ethdev/rte_ethdev.c +1 -1
@@ -654,7 +654,7 @@ rte_eth_dev_attach(const char *devargs, uint16_t *port_id) }/* parse devargs */ -if (rte_devargs_parse (&da,"%s" , devargs)) +if (rte_devargs_parse (&da, devargs)) goto err; ret =rte_eal_hotplug_add (da.bus->name, da.name, da.args);
Signature · 1 line
2.11.0
PATCH v9 2/27 kvargs: remove error logs
In reply to Gaetan RivetError logs in kvargs parsing should be better handled in components calling the library.
This library must be as lean as possible.
--- lib/librte_kvargs/rte_kvargs.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-)
lib/librte_kvargs/rte_kvargs.c +5 -17
@@ -6,7 +6,6 @@#include <string.h> #include <stdlib.h> -#include <rte_log.h> #include <rte_string_fns.h> #include "rte_kvargs.h"
@@ -28,29 +27,22 @@ rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params)* to pass to rte_strsplit */ kvlist->str =strdup (params); -if (kvlist->str ==NULL ) { -RTE_LOG (ERR ,PMD ,"Cannot parse arguments: not enough memory\n" ); +if (kvlist->str ==NULL )return -1 ; - }/* browse each key/value pair and add it in kvlist */ str = kvlist->str;while ((str =strtok_r (str,RTE_KVARGS_PAIRS_DELIM , &ctx1)) !=NULL ) { i = kvlist->count; -if (i >=RTE_KVARGS_MAX ) { -RTE_LOG (ERR ,PMD ,"Cannot parse arguments: list full\n" ); +if (i >=RTE_KVARGS_MAX )return -1 ; - } kvlist->pairs[i].key =strtok_r (str,RTE_KVARGS_KV_DELIM , &ctx2); kvlist->pairs[i].value =strtok_r (NULL ,RTE_KVARGS_KV_DELIM , &ctx2); -if (kvlist->pairs[i].key ==NULL || kvlist->pairs[i].value ==NULL ) { -RTE_LOG (ERR ,PMD , -"Cannot parse arguments: wrong key or value\n" -"params=<%s>\n" , params); +if (kvlist->pairs[i].key ==NULL || + kvlist->pairs[i].value ==NULL )return -1 ; - } kvlist->count++; str =NULL ;
@@ -89,12 +81,8 @@ check_for_valid_keys(struct rte_kvargs *kvlist,for (i =0 ; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; ret =is_valid_key (valid, pair->key); -if (!ret) { -RTE_LOG (ERR ,PMD , -"Error parsing device, invalid key <%s>\n" , - pair->key); +if (!ret)return -1 ; - } }return 0 ; }
Signature · 1 line
2.11.0
PATCH v9 3/27 kvargs: build before EAL
In reply to Gaetan Rivet--- lib/Makefile | 3 +-- lib/librte_kvargs/Makefile | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-)
lib/Makefile +1 -2
@@ -4,6 +4,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat +DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
@@ -76,8 +77,6 @@ DEPDIRS-librte_flow_classify := librte_net librte_table librte_acl DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DEPDIRS-librte_sched := librte_eal librte_mempool librte_mbuf librte_net DEPDIRS-librte_sched += librte_timer -DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs -DEPDIRS-librte_kvargs := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += librte_distributor DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ethdev DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
lib/librte_kvargs/Makefile +1 -1
@@ -7,7 +7,7 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_kvargs.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -LDLIBS += -lrte_eal +CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include EXPORT_MAP := rte_kvargs_version.map
Signature · 1 line
2.11.0
PATCH v9 4/27 kvargs: introduce a more flexible parsing function
In reply to Gaetan RivetThis function permits defining additional terminating characters, ending the parsing to arbitrary delimiters.
--- lib/Makefile | 1 + lib/librte_kvargs/rte_kvargs.c | 25 +++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs.h | 30 ++++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 7 +++++++ 4 files changed, 63 insertions(+)
lib/Makefile +1 -0
@@ -5,6 +5,7 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs +DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal
lib/librte_kvargs/rte_kvargs.c +25 -0
@@ -168,3 +168,28 @@ rte_kvargs_parse(const char *args, const char * const valid_keys[])return kvlist; } + +__rte_experimental +struct rte_kvargs * +rte_kvargs_parse2 (const char *args,const char *const valid_keys[], +const char *valid_ends) +{ +struct rte_kvargs *kvlist =NULL ; +char *copy; +size_t len; + +if (valid_ends ==NULL ) +return rte_kvargs_parse (args, valid_keys); + + copy =strdup (args); +if (copy ==NULL ) +return NULL ; + + len =strcspn (copy, valid_ends); + copy[len] ='\0' ; + + kvlist =rte_kvargs_parse (copy, valid_keys); + +free (copy); +return kvlist; +}
lib/librte_kvargs/rte_kvargs.h +30 -0
@@ -72,6 +72,36 @@ struct rte_kvargs *rte_kvargs_parse(const char *args, const char *const valid_keys[]);/** +* Allocate a rte_kvargs and store key/value associations from a string. +* This version will consider any byte from valid_ends as a possible +* terminating character, and will not parse beyond any of their occurrence. +* +* The function allocates and fills an rte_kvargs structure from a given +* string whose format is key1=value1,key2=value2,... +* +* The structure can be freed with rte_kvargs_free(). +* +* @param args +* The input string containing the key/value associations +* +* @param valid_keys +* A list of valid keys (table of const char *, the last must be NULL). +* This argument is ignored if NULL +* +* @param valid_ends +* Acceptable terminating characters. +* If NULL, the behavior is the same as ``rte_kvargs_parse``. +* +* @return +* - A pointer to an allocated rte_kvargs structure on success +* - NULL on error +*/ +__rte_experimental +struct rte_kvargs *rte_kvargs_parse2(const char *args, +const char *const valid_keys[], +const char *valid_ends); + +/** * Free a rte_kvargs structure * * Free a rte_kvargs structure previously allocated with
lib/librte_kvargs/rte_kvargs_version.map +7 -0
@@ -8,3 +8,10 @@ DPDK_2.0 { local: *; }; + +EXPERIMENTAL { + global: + + rte_kvargs_parse2; + +} DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v9 5/27 eal: introduce dtor macros
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
lib/librte_eal/common/include/rte_common.h +23 -0
@@ -112,6 +112,29 @@ static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)RTE_INIT_PRIO (func,LAST )/** +* Run after main() with low priority. +* +* @param func +* Destructor function name. +* @param prio +* Priority number must be above 100. +* Lowest number is the last to run. + */ +#define RTE_FINI_PRIO (func, prio) \ +static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void) + +/** +* Run after main() with high priority. +* +* The destructor will be run *before* prioritized destructors. +* +* @param func +* Destructor function name. +*/ +#define RTE_FINI (func) \ + RTE_FINI_PRIO(func, LAST) + +/** * Force a function to be inlined */ #define __rte_always_inline inline __attribute__((always_inline))
Signature · 1 line
2.11.0
PATCH v9 6/27 eal: introduce device class abstraction
In reply to Gaetan Rivet--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 +++++++++++++++ lib/librte_eal/common/include/rte_class.h | 121 +++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_common.h | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 2 + 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -52,6 +52,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
lib/librte_eal/common/Makefile +1 -1
@@ -11,7 +11,7 @@ INC += rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_string_fns.h rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h -INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h +INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h
lib/librte_eal/common/eal_common_class.c new file +62 -0
62 lines not on this page · raw message
lib/librte_eal/common/include/rte_class.h new file +121 -0
121 lines not on this page · raw message
lib/librte_eal/common/include/rte_common.h +1 -0
@@ -83,6 +83,7 @@ typedef uint16_t unaligned_uint16_t;#define RTE_PRIORITY_LOG 101#define RTE_PRIORITY_BUS 110 +#define RTE_PRIORITY_CLASS 120#define RTE_PRIORITY_LAST 65535#define RTE_PRIO (prio) \
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hypervisor.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_class.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
lib/librte_eal/rte_eal_version.map +2 -0
@@ -244,6 +244,8 @@ DPDK_18.05 { EXPERIMENTAL { global: + rte_class_register; + rte_class_unregister; rte_ctrl_thread_create; rte_dev_event_callback_register; rte_dev_event_callback_unregister;
Signature · 1 line
2.11.0
PATCH v9 7/27 eal/class: register destructor
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 5 +++++ 1 file changed, 5 insertions(+)
lib/librte_eal/common/include/rte_class.h +5 -0
@@ -112,6 +112,11 @@ static void classinitfn_ ##nm(void) \ {\ (cls).name =RTE_STR (nm);\rte_class_register (&cls); \ +} \ +RTE_FINI_PRIO(classfinifn_ ##nm, CLASS); \ +static void classfinifn_ ##nm(void) \ +{ \ + rte_class_unregister(&cls); \ }#ifdef __cplusplus
Signature · 1 line
2.11.0
PATCH v9 8/27 devargs: add function to parse device layers
In reply to Gaetan RivetThis function is private to the EAL.
It is used to parse each layers in a device description string, and store the result in an rte_devargs structure.
--- lib/librte_eal/common/eal_common_devargs.c | 144 ++++++++++++++++++++++++++++ lib/librte_eal/common/eal_private.h | 27 ++++++ lib/librte_eal/common/include/rte_devargs.h | 13 ++- 3 files changed, 181 insertions(+), 3 deletions(-)
lib/librte_eal/common/eal_common_devargs.c +144 -0
@@ -13,9 +13,13 @@#include <string.h> #include <stdarg.h> +#include <rte_bus.h> +#include <rte_class.h> #include <rte_compat.h> #include <rte_dev.h> #include <rte_devargs.h> +#include <rte_kvargs.h> +#include <rte_errno.h> #include <rte_tailq.h> #include "eal_private.h"
@@ -56,6 +60,146 @@ rte_eal_parse_devargs_str(const char *devargs_str,return 0 ; } +static size_t +devargs_layer_count (const char *s) +{ +size_t i = s ?1 :0 ; + +while (s !=NULL && s[0 ] !='\0' ) { + i += s[0 ] =='/' ; + s++; + } +return i; +} + +int +rte_devargs_layers_parse (struct rte_devargs *da, +const char *devstr) +{ +struct { +const char *key; +const char *str; +struct rte_kvargs *kvlist; + } layers[] = { + {"bus=" ,NULL ,NULL , }, + {"class=" ,NULL ,NULL , }, + {"driver=" ,NULL ,NULL , }, + }; +struct rte_kvargs_pair *kv =NULL ; +struct rte_class *cls =NULL ; +struct rte_bus *bus =NULL ; +const char *s = devstr; +size_t nblayer; +size_t i =0 ; +int ret =0 ; + +/* Split each sub-lists. */ + nblayer =devargs_layer_count (devstr); +if (nblayer >RTE_DIM (layers)) { +RTE_LOG (ERR ,EAL ,"Invalid format: too many layers (%zu)\n" , + nblayer); + ret = -E2BIG ; + goto get_out; + } + +/* If the devargs points the devstr +* as source data, then it should not allocate +* anything and keep referring only to it. +*/ +if (da->data != devstr) { + da->data =strdup (devstr); +if (da->data ==NULL ) { +RTE_LOG (ERR ,EAL ,"OOM\n" ); + ret = -ENOMEM ; + goto get_out; + } + s = da->data; + } + +while (s !=NULL ) { +if (strncmp (layers[i].key, s, +strlen (layers[i].key)) && +/* The last layer is free-form. +* The "driver" key is not required (but accepted). +*/ + i !=RTE_DIM (layers) -1 ) + goto next_layer; + layers[i].str = s; + layers[i].kvlist =rte_kvargs_parse2 (s,NULL ,"/" ); +if (layers[i].kvlist ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not parse %s\n" , s); + ret = -EINVAL ; + goto get_out; + } + s =strchr (s,'/' ); +if (s !=NULL ) + s++; +next_layer: +if (i >=RTE_DIM (layers)) { +RTE_LOG (ERR ,EAL ,"Unrecognized layer %s\n" , s); + ret = -EINVAL ; + goto get_out; + } + i++; + } + +/* Parse each sub-list. */ +for (i =0 ; i <RTE_DIM (layers); i++) { +if (layers[i].kvlist ==NULL ) +continue ; + kv = &layers[i].kvlist->pairs[0 ]; +if (strcmp (kv->key,"bus" ) ==0 ) { + bus =rte_bus_find_by_name (kv->value); +if (bus ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not find bus \"%s\"\n" , + kv->value); + ret = -EFAULT ; + goto get_out; + } + }else if (strcmp (kv->key,"class" ) ==0 ) { + cls =rte_class_find_by_name (kv->value); +if (cls ==NULL ) { +RTE_LOG (ERR ,EAL ,"Could not find class \"%s\"\n" , + kv->value); + ret = -EFAULT ; + goto get_out; + } + }else if (strcmp (kv->key,"driver" ) ==0 ) { +/* Ignore */ +continue ; + } + } + +/* Fill devargs fields. */ + da->busstr = layers[0 ].str; + da->clsstr = layers[1 ].str; + da->drvstr = layers[2 ].str; + da->bus = bus; + da->cls = cls; + +/* If we own the data, clean up a bit +* the several layers string, to ease +* their parsing afterward. +*/ +if (da->data != devstr) { +char *s = (void *)(intptr_t )(da->data); + +while ((s =strchr (s,'/' ))) { + *s ='\0' ; + s++; + } + } + +get_out: +for (i =0 ; i <RTE_DIM (layers); i++) { +if (layers[i].kvlist) +rte_kvargs_free (layers[i].kvlist); + } +if (ret !=0 ) + rte_errno = -ret; +return ret; +} +static int bus_name_cmp (const struct rte_bus *bus,const void *name) {
lib/librte_eal/common/eal_private.h +27 -0
@@ -258,4 +258,31 @@ int rte_mp_channel_init(void);*/ void dev_callback_process (char *device_name,enum rte_dev_event_type event); +/** +* @internal +* Parse a device string and store its information in an +* rte_devargs structure. +* +* Note: if the "data" field of da points to devstr, +* then no dynamic allocation is performed and the rte_devargs +* can be safely discarded. +* +* Otherwise ``data`` will hold a workable copy of devstr, that will be +* used by layers descriptors within rte_devargs. In this case, +* any rte_devargs should be cleaned-up before being freed. +* +* @param da +* rte_devargs structure to fill. +* +* @param devstr +* Device string. +* +* @return +* 0 on success. +* Negative errno values on error (rte_errno is set). +*/ +int +rte_devargs_layers_parse (struct rte_devargs *da, +const char *devstr); +#endif /* _EAL_PRIVATE_H_ */
lib/librte_eal/common/include/rte_devargs.h +10 -3
@@ -51,12 +51,19 @@ struct rte_devargs {enum rte_devtype type;/** Device policy. */ enum rte_dev_policy policy; -/** Bus handle for the device. */ -struct rte_bus *bus;/** Name of the device. */ char name[RTE_DEV_NAME_MAX_LEN ]; +RTE_STD_C11 + union {/** Arguments string as given by user or "" for no argument. */ -char *args; +char *args; +const char *drvstr; + }; +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< bus-related part of device string. */ +const char *data;/**< Device string storage. */ };/**
Signature · 1 line
2.11.0
PATCH v9 9/27 eal/dev: add device iterator interface
In reply to Gaetan RivetA device iterator allows iterating over a set of devices. This set is defined by the two descriptions offered,
* rte_bus
* rte_class
Only one description can be provided, or both. It is not allowed to provide no description at all.
Each layer of abstraction then performs a filter based on the description provided. This filtering allows iterating on their internal set of devices, stopping when a match is valid and returning the current iteration context.
This context allows starting the next iteration from the same point and going forward.
--- lib/librte_eal/common/include/rte_dev.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
lib/librte_eal/common/include/rte_dev.h +47 -0
@@ -285,6 +285,53 @@ __attribute__((used)) = str static const char DRV_EXP_TAG(name, kmod_dep_export)[] \ __attribute__((used)) = str +/** +* Iteration context. +* +* This context carries over the current iteration state. +*/ +struct rte_dev_iterator { +const char *devstr;/**< device string. */ +const char *busstr;/**< bus-related part of device string. */ +const char *clsstr;/**< class-related part of device string. */ +struct rte_bus *bus;/**< bus handle. */ +struct rte_class *cls;/**< class handle. */ +struct rte_device *device;/**< current position. */ +void *class_device;/**< additional specialized context. */ +}; + +/** +* Device iteration function. +* +* Find the next device matching properties passed in parameters. +* The function takes an additional ``start`` parameter, that is +* used as starting context when relevant. +* +* The function returns the current element in the iteration. +* This return value will potentially be used as a start parameter +* in subsequent calls to the function. +* +* The additional iterator parameter is only there if a specific +* implementation needs additional context. It must not be modified by +* the iteration function itself. +* +* @param start +* Starting iteration context. +* +* @param devstr +* Device description string. +* +* @param it +* Device iterator. +* +* @return +* The address of the current element matching the device description +* string. +*/ +typedef void *(*rte_dev_iterate_t )(const void *start, +const char *devstr, +const struct rte_dev_iterator *it); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v9 10/27 eal/class: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_class.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_class.h +1 -0
@@ -30,6 +30,7 @@ TAILQ_HEAD(rte_class_list, rte_class);struct rte_class {TAILQ_ENTRY (rte_class) next;/**< Next device class in linked list */ const char *name;/**< Name of the class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v9 11/27 eal/bus: add device iteration
In reply to Gaetan Rivet--- lib/librte_eal/common/include/rte_bus.h | 1 + 1 file changed, 1 insertion(+)
lib/librte_eal/common/include/rte_bus.h +1 -0
@@ -211,6 +211,7 @@ struct rte_bus {rte_bus_parse_t parse;/**< Parse a device name */ struct rte_bus_conf conf;/**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class;/**< Get iommu class */ +rte_dev_iterate_t dev_iterate;/**< Device iterator. */ };/**
Signature · 1 line
2.11.0
PATCH v9 12/27 eal/dev: implement device iteration initialization
In reply to Gaetan RivetParse a device description.
Split this description in their relevant part for each layers. No dynamic allocation is performed.
--- lib/Makefile | 1 + lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_dev.c | 55 +++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 24 ++++++++++++++ lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 1 + 6 files changed, 83 insertions(+)
lib/Makefile +1 -0
@@ -7,6 +7,7 @@ DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DEPDIRS-librte_kvargs := librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal +DEPDIRS-librte_eal := librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci DEPDIRS-librte_pci := librte_eal DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -18,6 +18,7 @@ CFLAGS += $(WERROR_FLAGS) -O3 LDLIBS += -lexecinfo LDLIBS += -lpthread LDLIBS += -lgcc_s +LDLIBS += -lrte_kvargs EXPORT_MAP := ../../rte_eal_version.map
lib/librte_eal/common/eal_common_dev.c +55 -0
67 lines not on this page · raw message
lib/librte_eal/common/include/rte_dev.h +24 -0
@@ -332,6 +332,30 @@ typedef void *(*rte_dev_iterate_t)(const void *start,const char *devstr, const struct rte_dev_iterator *it); +/** +* Initializes a device iterator. +* +* This iterator allows accessing a list of devices matching a criteria. +* The device matching is made among all buses and classes currently registered, +* filtered by the device description given as parameter. +* +* This function will not allocate any memory. It is safe to stop the +* iteration at any moment and let the iterator go out of context. +* +* @param it +* Device iterator handle. +* +* @param str +* Device description string. +* +* @return +* 0 on successful initialization. +* <0 on error. +*/ +__rte_experimental +int +rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -27,6 +27,7 @@ LDLIBS += -lrt ifeq ($(CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES),y) LDLIBS += -lnuma endif +LDLIBS += -lrte_kvargs # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
lib/librte_eal/rte_eal_version.map +1 -0
@@ -251,6 +251,7 @@ EXPERIMENTAL { rte_dev_event_callback_unregister; rte_dev_event_monitor_start; rte_dev_event_monitor_stop; + rte_dev_iterator_init; rte_devargs_add; rte_devargs_dump; rte_devargs_insert;
Signature · 1 line
2.11.0
PATCH v9 13/27 eal/dev: implement device iteration
In reply to Gaetan RivetUse the iteration hooks in the abstraction layers to perform the requested filtering on the internal device lists.
--- lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_dev.h | 26 +++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 195 insertions(+)
lib/librte_eal/common/eal_common_dev.c +168 -0
@@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs;/* spinlock for device callbacks */ static rte_spinlock_t dev_event_lock =RTE_SPINLOCK_INITIALIZER ; +struct dev_next_ctx { +struct rte_dev_iterator *it; +const char *busstr; +const char *clsstr; +}; + +#define CTX (it, busstr, clsstr) \ + (&(const struct dev_next_ctx){ \ + .it = it, \ + .busstr = busstr, \ + .clsstr = clsstr, \ + }) + +#define ITCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->it) + +#define BUSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->busstr) + +#define CLSCTX (ptr) \ + (((struct dev_next_ctx *)(intptr_t)ptr)->clsstr) +static int cmp_detached_dev_name (const struct rte_device *dev,const void *_name) {
@@ -398,3 +420,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, get_out:return -rte_errno; } + +static char * +dev_str_sane_copy (const char *str) +{ +size_t end; +char *copy; + + end =strcspn (str,",/" ); +if (str[end] ==',' ) { + copy =strdup (&str[end +1 ]); + }else { +/* '/' or '\0' */ + copy =strdup ("" ); + } +if (copy ==NULL ) { + rte_errno =ENOMEM ; + }else { +char *slash; + + slash =strchr (copy,'/' ); +if (slash !=NULL ) + slash[0 ] ='\0' ; + } +return copy; +} + +static int +class_next_dev_cmp (const struct rte_class *cls, +const void *ctx) +{ +struct rte_dev_iterator *it; +const char *clsstr =NULL ; +void *dev; + +if (cls->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + clsstr =CLSCTX (ctx); + dev = it->class_device; +/* it->clsstr != NULL means a class +* was specified in the devstr. +*/ +if (it->clsstr !=NULL && cls != it->cls) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; + dev = cls->dev_iterate (dev, clsstr, it); + it->class_device = dev; +return dev ==NULL ; +} + +static int +bus_next_dev_cmp (const struct rte_bus *bus, +const void *ctx) +{ +struct rte_device *dev =NULL ; +struct rte_class *cls =NULL ; +struct rte_dev_iterator *it; +const char *busstr =NULL ; + +if (bus->dev_iterate ==NULL ) +return 1 ; + it =ITCTX (ctx); + busstr =BUSCTX (ctx); + dev = it->device; +/* it->busstr != NULL means a bus +* was specified in the devstr. +*/ +if (it->busstr !=NULL && bus != it->bus) +return 1 ; +/* If an error occurred previously, +* no need to test further. +*/ +if (rte_errno !=0 ) +return -1 ; +if (it->clsstr ==NULL ) { + dev = bus->dev_iterate (dev, busstr, it); + goto end; + } +/* clsstr != NULL */ +if (dev ==NULL ) { +next_dev_on_bus: + dev = bus->dev_iterate (dev, busstr, it); + it->device = dev; + } +if (dev ==NULL ) +return 1 ; +if (it->cls !=NULL ) + cls =TAILQ_PREV (it->cls, rte_class_list, next); + cls =rte_class_find (cls, class_next_dev_cmp, ctx); +if (cls !=NULL ) { + it->cls = cls; + goto end; + } + goto next_dev_on_bus; +end: + it->device = dev; +return dev ==NULL ; +} +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it) +{ +struct rte_bus *bus =NULL ; +int old_errno = rte_errno; +char *busstr =NULL ; +char *clsstr =NULL ; + + rte_errno =0 ; +if (it->busstr ==NULL && it->clsstr ==NULL ) { +/* Invalid iterator. */ + rte_errno =EINVAL ; +return NULL ; + } +if (it->bus !=NULL ) + bus =TAILQ_PREV (it->bus, rte_bus_list, next); +if (it->busstr !=NULL ) { + busstr =dev_str_sane_copy (it->busstr); +if (busstr ==NULL ) + goto out; + } +if (it->clsstr !=NULL ) { + clsstr =dev_str_sane_copy (it->clsstr); +if (clsstr ==NULL ) + goto out; + } +while ((bus =rte_bus_find (bus, bus_next_dev_cmp, +CTX (it, busstr, clsstr)))) { +if (it->device !=NULL ) { + it->bus = bus; + goto out; + } +if (it->busstr !=NULL || + rte_errno !=0 ) +break ; + } +if (rte_errno ==0 ) + rte_errno = old_errno; +out: +free (busstr); +free (clsstr); +return it->device; +}
lib/librte_eal/common/include/rte_dev.h +26 -0
@@ -356,6 +356,32 @@ __rte_experimentalint rte_dev_iterator_init (struct rte_dev_iterator *it,const char *str); +/** +* Iterates on a device iterator. +* +* Generates a new rte_device handle corresponding to the next element +* in the list described in comprehension by the iterator. +* +* The next object is returned, and the iterator is updated. +* +* @param it +* Device iterator handle. +* +* @return +* An rte_device handle if found. +* NULL if an error occurred (rte_errno is set). +* NULL if no device could be found (rte_errno is not set). +*/ +__rte_experimental +struct rte_device * +rte_dev_iterator_next (struct rte_dev_iterator *it); + +#define RTE_DEV_FOREACH (dev, devstr, it) \ + for (rte_dev_iterator_init(it, devstr), \ + dev = rte_dev_iterator_next(it); \ + dev != NULL; \ + dev = rte_dev_iterator_next(it)) + #ifdef __cplusplus }#endif
lib/librte_eal/rte_eal_version.map +1 -0
@@ -252,6 +252,7 @@ EXPERIMENTAL { rte_dev_event_monitor_start; rte_dev_event_monitor_stop; rte_dev_iterator_init; + rte_dev_iterator_next; rte_devargs_add; rte_devargs_dump; rte_devargs_insert;
Signature · 1 line
2.11.0
PATCH v9 14/27 kvargs: add generic string matching callback
In reply to Gaetan RivetThis function can be used as a callback torte_kvargs_process.
This should reduce code duplication.
--- lib/librte_kvargs/rte_kvargs.c | 10 ++++++++++ lib/librte_kvargs/rte_kvargs.h | 28 ++++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs_version.map | 1 + 3 files changed, 39 insertions(+)
lib/librte_kvargs/rte_kvargs.c +10 -0
@@ -193,3 +193,13 @@ rte_kvargs_parse2(const char *args, const char * const valid_keys[],free (copy);return kvlist; } + +__rte_experimental +int +rte_kvargs_strcmp(const char *key __rte_unused, +const char *value,void *opaque) +{ +const char *str = opaque; + +return -abs (strcmp (str, value)); +}
lib/librte_kvargs/rte_kvargs.h +28 -0
@@ -25,6 +25,8 @@extern "C" {#endif +#include <rte_compat.h> +/** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32
@@ -151,6 +153,32 @@ int rte_kvargs_process(const struct rte_kvargs *kvlist,unsigned rte_kvargs_count (const struct rte_kvargs *kvlist,const char *key_match); +/** +* Generic kvarg handler for string comparison. +* +* This function can be used for a generic string comparison processing +* on a list of kvargs. +* +* @param key +* kvarg pair key. +* +* @param value +* kvarg pair value. +* +* @param opaque +* Opaque pointer to a string. +* +* @return +* 0 if the strings match. +* !0 otherwise or on error. +* +* Unless strcmp, comparison ordering is not kept. +* In order for rte_kvargs_process to stop processing on match error, +* a negative value is returned even if strcmp had returned a positive one. +*/ +__rte_experimental +int rte_kvargs_strcmp(const char *key, const char *value, void *opaque); + #ifdef __cplusplus }#endif
lib/librte_kvargs/rte_kvargs_version.map +1 -0
@@ -13,5 +13,6 @@ EXPERIMENTAL { global: rte_kvargs_parse2; + rte_kvargs_strcmp; } DPDK_2.0;
Signature · 1 line
2.11.0
PATCH v9 15/27 bus/pci: implement device iteration and comparison
In reply to Gaetan Rivet--- drivers/bus/pci/Makefile | 3 ++- drivers/bus/pci/pci_common.c | 1 + drivers/bus/pci/pci_params.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ drivers/bus/pci/private.h | 25 +++++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/pci/pci_params.c
drivers/bus/pci/Makefile +2 -1
@@ -26,10 +26,11 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal CFLAGS += -DALLOW_EXPERIMENTAL_API LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring -LDLIBS += -lrte_ethdev -lrte_pci +LDLIBS += -lrte_ethdev -lrte_pci -lrte_kvargs include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS)) +SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_params.c SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_common.c SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci_common_uio.c
drivers/bus/pci/pci_common.c +1 -0
@@ -437,6 +437,7 @@ struct rte_pci_bus rte_pci_bus = { .unplug = pci_unplug, .parse = pci_parse, .get_iommu_class = rte_pci_get_iommu_class, + .dev_iterate = rte_pci_dev_iterate, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
drivers/bus/pci/pci_params.c new file +53 -0
53 lines not on this page · raw message
drivers/bus/pci/private.h +25 -0
@@ -10,6 +10,8 @@#include <rte_pci.h> #include <rte_bus_pci.h> +extern struct rte_pci_bus rte_pci_bus; +struct rte_pci_driver ;struct rte_pci_device ;
@@ -166,4 +168,27 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,enum rte_iova_mode rte_pci_get_iommu_class (void ); +/* +* Iterate over internal devices, +* matching any device against the provided +* string. +* +* @param start +* Iteration starting point. +* +* @param str +* Device string to match against. +* +* @param it +* (unused) iterator structure. +* +* @return +* A pointer to the next matching device if any. +* NULL otherwise. +*/ +void * +rte_pci_dev_iterate (const void *start, +const char *str, +const struct rte_dev_iterator *it); +#endif /* _PCI_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v9 16/27 bus/pci: add device matching field id
In reply to Gaetan RivetThe PCI bus can now parse a matching field "id" as follows:
"bus=pci,id=0000:00:00.0"
or
"bus=pci,id=00:00.0"
--- drivers/bus/pci/pci_params.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
drivers/bus/pci/pci_params.c +27 -2
@@ -3,6 +3,7 @@*/ #include <rte_bus.h> +#include <rte_bus_pci.h> #include <rte_dev.h> #include <rte_errno.h> #include <rte_kvargs.h>
@@ -11,21 +12,45 @@#include "private.h" enum pci_params { +RTE_PCI_PARAMS_ID ,RTE_PCI_PARAMS_MAX , };static const char *const pci_params_keys[] = { + [RTE_PCI_PARAMS_ID ] ="id" , [RTE_PCI_PARAMS_MAX ] =NULL , };static int +pci_addr_kv_cmp(const char *key __rte_unused, +const char *value, +void *_addr2) +{ +struct rte_pci_addr _addr1; +struct rte_pci_addr *addr1 = &_addr1; +struct rte_pci_addr *addr2 = _addr2; + +if (rte_pci_addr_parse (value, addr1)) +return -1 ; +return -abs (rte_pci_addr_cmp (addr1, addr2)); +} + +static int pci_dev_match (const struct rte_device *dev,const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_pci_device *pdev; - (void ) dev; - (void ) kvlist; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + pdev =RTE_DEV_TO_PCI_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"id" , + &pci_addr_kv_cmp, + (void *)(intptr_t )&pdev->addr)) +return 1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v9 17/27 bus/vdev: implement device iteration
In reply to Gaetan Rivet--- drivers/bus/vdev/Makefile | 3 ++- drivers/bus/vdev/vdev.c | 10 ++++---- drivers/bus/vdev/vdev_params.c | 51 +++++++++++++++++++++++++++++++++++++++++ drivers/bus/vdev/vdev_private.h | 26 +++++++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 drivers/bus/vdev/vdev_params.c create mode 100644 drivers/bus/vdev/vdev_private.h
drivers/bus/vdev/Makefile +2 -1
@@ -19,8 +19,9 @@ EXPORT_MAP := rte_bus_vdev_version.map LIBABIVER := 1 SRCS-y += vdev.c +SRCS-y += vdev_params.c -LDLIBS += -lrte_eal +LDLIBS += -lrte_eal -lrte_kvargs # # Export include files
drivers/bus/vdev/vdev.c +6 -4
@@ -23,6 +23,7 @@#include "rte_bus_vdev.h" #include "vdev_logs.h" +#include "vdev_private.h" #define VDEV_MP_KEY "bus_vdev_mp"
@@ -493,9 +494,9 @@ vdev_probe(void)return ret; } -static struct rte_device * -vdev_find_device (const struct rte_device *start,rte_dev_cmp_t cmp, -const void *data) +struct rte_device * +rte_vdev_find_device (const struct rte_device *start,rte_dev_cmp_t cmp, +const void *data) {const struct rte_vdev_device *vstart;struct rte_vdev_device *dev;
@@ -532,10 +533,11 @@ vdev_unplug(struct rte_device *dev)static struct rte_bus rte_vdev_bus = { .scan = vdev_scan, .probe = vdev_probe, - .find_device = vdev_find_device, + .find_device = rte_vdev_find_device, .plug = vdev_plug, .unplug = vdev_unplug, .parse = vdev_parse, + .dev_iterate = rte_vdev_dev_iterate, };RTE_REGISTER_BUS (vdev, rte_vdev_bus);
drivers/bus/vdev/vdev_params.c new file +51 -0
51 lines not on this page · raw message
drivers/bus/vdev/vdev_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright 2018 Gaëtan Rivet +*/ + +#ifndef _VDEV_PRIVATE_H_ +#define _VDEV_PRIVATE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct rte_device * +rte_vdev_find_device (const struct rte_device *start, +rte_dev_cmp_t cmp, +const void *data); + +void * +rte_vdev_dev_iterate (const void *start, +const char *str, +const struct rte_dev_iterator *it); + +#ifdef __cplusplus +} +#endif + +#endif /* _VDEV_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v9 18/27 bus/vdev: add device matching field driver
In reply to Gaetan RivetThe vdev bus parses a field "driver", matching
a vdev driver name with one passed as follows:
"bus=vdev,driver=xxxx"
--- drivers/bus/vdev/vdev_params.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/bus/vdev/vdev_params.c +13 -2
@@ -4,6 +4,7 @@#include <rte_dev.h> #include <rte_bus.h> +#include <rte_bus_vdev.h> #include <rte_kvargs.h> #include <rte_errno.h>
@@ -11,10 +12,12 @@#include "vdev_private.h" enum vdev_params { +RTE_VDEV_PARAMS_DRIVER ,RTE_VDEV_PARAMS_MAX , };static const char *const vdev_params_keys[] = { + [RTE_VDEV_PARAMS_DRIVER ] ="driver" , [RTE_VDEV_PARAMS_MAX ] =NULL , };
@@ -23,9 +26,17 @@ vdev_dev_match(const struct rte_device *dev, const void *_kvlist) {const struct rte_kvargs *kvlist = _kvlist; +const struct rte_vdev_device *vdev; - (void ) kvlist; - (void ) dev; +if (kvlist ==NULL ) +/* Empty string matches everything. */ +return 0 ; + vdev =RTE_DEV_TO_VDEV_CONST (dev); +/* if any field does not match. */ +if (rte_kvargs_process (kvlist,"driver" , + rte_kvargs_strcmp, + (void *)(intptr_t )vdev->device.driver->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v9 19/27 ethdev: add private generic device iterator
In reply to Gaetan RivetThis iterator can be customized with a comparison function that will trigger a stopping condition.
It can be leveraged to write several different iterators that have similar but non-identical purposes.
It is private to librte_ethdev.
--- lib/librte_ethdev/Makefile | 1 + lib/librte_ethdev/eth_private.c | 31 +++++++++++++++++++++++++++++++ lib/librte_ethdev/eth_private.h | 26 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 lib/librte_ethdev/eth_private.c create mode 100644 lib/librte_ethdev/eth_private.h
lib/librte_ethdev/Makefile +1 -0
@@ -18,6 +18,7 @@ EXPORT_MAP := rte_ethdev_version.map LIBABIVER := 9 +SRCS-y += eth_private.c SRCS-y += rte_ethdev.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c
lib/librte_ethdev/eth_private.c new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#include "rte_ethdev.h" +#include "eth_private.h" + +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *start,rte_eth_cmp_t cmp, +const void *data) +{ +struct rte_eth_dev *edev; +ptrdiff_t idx; + +/* Avoid Undefined Behaviour */ +if (start !=NULL && + (start < &rte_eth_devices[0 ] || + start > &rte_eth_devices[RTE_MAX_ETHPORTS ])) +return NULL ; +if (start !=NULL ) + idx = start - &rte_eth_devices[0 ] +1 ; +else + idx =0 ; +for (; idx <RTE_MAX_ETHPORTS ; idx++) { + edev = &rte_eth_devices[idx]; +if (cmp (edev, data) ==0 ) +return edev; + } +return NULL ; +} +
lib/librte_ethdev/eth_private.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2018 Gaëtan Rivet +*/ + +#ifndef _RTE_ETH_PRIVATE_H_ +#define _RTE_ETH_PRIVATE_H_ + +#include "rte_ethdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic rte_eth_dev comparison function. */ +typedef int (*rte_eth_cmp_t )(const struct rte_eth_dev *,const void *); + +/* Generic rte_eth_dev iterator. */ +struct rte_eth_dev * +eth_find_device (const struct rte_eth_dev *_start,rte_eth_cmp_t cmp, +const void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ETH_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v9 20/27 ethdev: register ether layer as a class
In reply to Gaetan Rivet--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 lib/librte_ethdev/rte_class_eth.c
lib/librte_ethdev/Makefile +2 -1
@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
lib/librte_ethdev/rte_class_eth.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH v9 20/27] ethdev: register ether layer as a class
Quoted 21 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-)create mode 100644
lib/librte_ethdev/rte_class_eth.clib/librte_ethdev/Makefile +1
-1@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map
lib/librte_ethdev/Makefile LIBABIVER := 9 · line 26
Quoted 7 lines
lib/librte_ethdev/Makefile +1
-0@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.c
meson.build files should be updated as well.
Re: [PATCH v9 20/27] ethdev: register ether layer as a class
Hi Andrew,
Quoted 20 lines · Andrew Rybchenko
Quoted 19 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-)create mode 100644
lib/librte_ethdev/rte_class_eth.clib/librte_ethdev/Makefile +1
-1@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map@@ -20,6 +20,7 @@ LIBABIVER := 9
Quoted 8 lines
lib/librte_ethdev/Makefile LIBABIVER := 9 · line 26
Quoted 6 lines
lib/librte_ethdev/Makefile +1
-0SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.cmeson.build files should be updated as well.
The meson version required by DPDK is not available in my distribution.
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v9 20/27] ethdev: register ether layer as a class
Quoted 32 lines · Gaëtan Rivet
Hi Andrew,
Quoted 20 lines · Andrew Rybchenko
Quoted 19 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-)create mode 100644
lib/librte_ethdev/rte_class_eth.clib/librte_ethdev/Makefile +1
-1@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.map@@ -20,6 +20,7 @@ LIBABIVER := 9Quoted 8 lines
lib/librte_ethdev/Makefile LIBABIVER := 9 · line 26
Quoted 6 lines
lib/librte_ethdev/Makefile +1
-0SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.cmeson.build files should be updated as well.
Quoted 2 lines
The meson version required by DPDK is not available in my distribution.
"pip3 install meson" works in just about all distros. I'd recommend using meson from pip generally, since it tends to be very up to date. The latest versions configure DPDK a lot faster than the older ones!
/Bruce
Re: [PATCH v9 20/27] ethdev: register ether layer as a class
Quoted 33 lines · Bruce Richardson
Quoted 32 lines · Gaëtan Rivet
Hi Andrew,
Quoted 28 lines · Andrew Rybchenko
Quoted 19 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>--- lib/librte_ethdev/Makefile | 3 +- lib/librte_ethdev/rte_class_eth.c | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-)create mode 100644
lib/librte_ethdev/rte_class_eth.clib/librte_ethdev/Makefile +1
-1@@ -12,7 +12,7 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_net -lrte_eal -lrte_mempool -lrte_ring -LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mbuf -lrte_kvargs EXPORT_MAP := rte_ethdev_version.maplib/librte_ethdev/Makefile LIBABIVER := 9 · line 25
Quoted 6 lines
lib/librte_ethdev/Makefile +1
-0@@ -20,6 +20,7 @@ LIBABIVER := 9 SRCS-y += eth_private.c SRCS-y += rte_ethdev.c +SRCS-y += rte_class_eth.c SRCS-y += rte_flow.c SRCS-y += rte_tm.c SRCS-y += rte_mtr.cmeson.build files should be updated as well.
Quoted 7 lines
Quoted 2 lines
The meson version required by DPDK is not available in my distribution.
"pip3 install meson" works in just about all distros. I'd recommend using meson from pip generally, since it tends to be very up to date. The latest versions configure DPDK a lot faster than the older ones!
/Bruce
Thanks,
The v10 now supports meson.
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v9 21/27 ethdev: add device matching field name
In reply to Gaetan RivetThe eth device class can now parse a field name,
matching the eth_dev name with one passed as
"class=eth,name=xxxxxx"
--- lib/librte_ethdev/rte_class_eth.c | 7 +++++++ 1 file changed, 7 insertions(+)
lib/librte_ethdev/rte_class_eth.c +7 -0
@@ -15,10 +15,12 @@#include "eth_private.h" enum eth_params { +RTE_ETH_PARAMS_NAME ,RTE_ETH_PARAMS_MAX , };static const char *const eth_params_keys[] = { + [RTE_ETH_PARAMS_NAME ] ="name" , [RTE_ETH_PARAMS_MAX ] =NULL , };
@@ -39,6 +41,7 @@ eth_dev_match(const struct rte_eth_dev *edev, {const struct eth_dev_match_arg *arg = _arg;const struct rte_kvargs *kvlist = arg->kvlist; +struct rte_eth_dev_data *data;if (edev->state ==RTE_ETH_DEV_UNUSED )return -1 ;
@@ -47,6 +50,10 @@ eth_dev_match(const struct rte_eth_dev *edev,if (kvlist ==NULL )/* Empty string matches everything. */ return 0 ; + data = edev->data; +if (rte_kvargs_process (kvlist,"name" , + rte_kvargs_strcmp, data->name)) +return -1 ;return 0 ; }
Signature · 1 line
2.11.0
PATCH v9 22/27 app/testpmd: add show device command
In reply to Gaetan RivetA new interactive command is offered:
show device <device description>
This commands lists all rte_device element matching the device description. e.g.:
show device bus=pci
show device bus=vdev
show device bus=vdev/class=eth
show device bus=vdev,driver=net_ring/class=eth
show device bus=vdev/class=eth,name=net_ring0
These devices may not be otherwise useful, some buses will spawn devices to keep track of their assets without having a driver to use them.
--- app/test-pmd/cmdline.c | 54 +++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 +++++++++++++ 2 files changed, 78 insertions(+)
app/test-pmd/cmdline.c +54 -0
@@ -228,6 +228,9 @@ static void cmd_help_long_parsed(void *parsed_result,"show port tm node stats (port_id) (node_id) (clear)\n" " Display the port TM node stats.\n\n" +"show device (device_string)\n" +" Display devices matching the device string.\n\n" + ); }
@@ -7083,6 +7086,56 @@ cmdline_parse_inst_t cmd_showportall = { }, }; +/* *** SHOW DEVICE INFO *** */ +struct cmd_showdevice_result { +cmdline_fixed_string_t show; +cmdline_fixed_string_t device; +cmdline_fixed_string_t filter; +}; + +static void +cmd_showdevice_dump_device (const struct rte_device *dev) +{ +const struct rte_driver *drv = dev->driver; + +printf ("0x%p: %s:%s\n" , (const void *)dev, dev->name, + drv ? drv->name :"<nil>" ); +} + +static void cmd_showdevice_parsed (void *parsed_result, + __attribute__((unused))struct cmdline *cl, + __attribute__((unused))void *data) +{ +struct cmd_showdevice_result *res = parsed_result; +struct rte_dev_iterator it; +const struct rte_device *dev; + + RTE_DEV_FOREACH(dev, res->filter, &it) +cmd_showdevice_dump_device (dev); +} + +cmdline_parse_token_string_t cmd_showdevice_show = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + show,"show" ); +cmdline_parse_token_string_t cmd_showdevice_device = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + device,"device" ); +cmdline_parse_token_string_t cmd_showdevice_filter = + TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, + filter,NULL ); + +cmdline_parse_inst_t cmd_showdevice = { + .f = cmd_showdevice_parsed, + .data =NULL , + .help_str ="show device <device string>" , + .tokens = { + (void *)&cmd_showdevice_show, + (void *)&cmd_showdevice_device, + (void *)&cmd_showdevice_filter, +NULL , + }, +}; +/* *** SHOW PORT INFO *** */ struct cmd_showport_result {cmdline_fixed_string_t show;
@@ -17262,6 +17315,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_load_from_file, + (cmdline_parse_inst_t *)&cmd_showdevice, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall,
doc/guides/testpmd_app_ug/testpmd_funcs.rst +24 -0
@@ -2628,6 +2628,30 @@ set the traffic management default hierarchy on the port:: testpmd> set port tm hierarchy default (port_id) +Device functions +---------------- + +Show devices +~~~~~~~~~~~~ + +Display any registered devices:: + + testpmd> show device <device_string> + +where: + +* ``device_string``: Device description string, of the format + + layer[/layer[/layer]] + + where one layer is in the form + + layer_key=layer_name[,key1=value1[,...]] + + Valid layer keys are ``bus`` and ``class``. + Their respective values is defined by registered ``bus`` and ``class`` + drivers. + Filter Functions ----------------
Signature · 1 line
2.11.0
PATCH v9 23/27 bus/pci: pre-process declarative PCI devargs
In reply to Gaetan RivetThe new devargs format does not recognize a particular device name. Each bus uses its specific format.
Instead of introducing a new bus API, process those devargs privately for the moment. Prepare them for matching during scan against the bus devices.
--- drivers/bus/pci/bsd/pci.c | 5 ++++ drivers/bus/pci/linux/pci.c | 5 ++++ drivers/bus/pci/pci_params.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ drivers/bus/pci/private.h | 16 +++++++++++++ 4 files changed, 81 insertions(+)
drivers/bus/pci/bsd/pci.c +5 -0
@@ -327,6 +327,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)int rte_pci_scan (void ) { +struct rte_devargs *devargs;int fd;unsigned dev_count =0 ;struct pci_conf matches[16 ];
@@ -342,6 +343,10 @@ rte_pci_scan(void)if (!rte_eal_has_pci ())return 0 ; + RTE_EAL_DEVARGS_FOREACH("pci", devargs) +if (rte_pci_devargs_prepare (devargs)) +continue ; + fd =open ("/dev/pci" ,O_RDONLY );if (fd <0 ) {RTE_LOG (ERR ,EAL ,"%s(): error opening /dev/pci\n" , __func__);
drivers/bus/pci/linux/pci.c +5 -0
@@ -430,6 +430,7 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)int rte_pci_scan (void ) { +struct rte_devargs *devargs;struct dirent *e;DIR *dir;char dirname[PATH_MAX ];
@@ -439,6 +440,10 @@ rte_pci_scan(void)if (!rte_eal_has_pci ())return 0 ; + RTE_EAL_DEVARGS_FOREACH("pci", devargs) +if (rte_pci_devargs_prepare (devargs)) +continue ; +#ifdef VFIO_PRESENT if (!pci_vfio_is_enabled ())RTE_LOG (DEBUG ,EAL ,"VFIO PCI modules not loaded\n" );
drivers/bus/pci/pci_params.c +55 -0
67 lines not on this page · raw message
drivers/bus/pci/private.h +16 -0
@@ -191,4 +191,20 @@ rte_pci_dev_iterate(const void *start,const char *str, const struct rte_dev_iterator *it); +/* +* Prepare a devargs meant for this bus. +* This function is only used for a transitory period, +* to translate the new devargs format in one +* compatible with the old form. +* +* @param da +* Devargs to process. +* +* @return +* 0 on success. +* <0 on error. +*/ +int +rte_pci_devargs_prepare (struct rte_devargs *da); +#endif /* _PCI_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v9 24/27 bus/vdev: pre-process declarative vdev devargs
In reply to Gaetan RivetThe new devargs format does not recognize a particular device name. Each bus uses its specific format.
Process each devargs privately prior to attempting a bus scan. Prepare them if they are using the new devargs format.
--- drivers/bus/vdev/vdev.c | 10 +++++---- drivers/bus/vdev/vdev_params.c | 50 +++++++++++++++++++++++++++++++++++++++++ drivers/bus/vdev/vdev_private.h | 6 +++++ 3 files changed, 62 insertions(+), 4 deletions(-)
drivers/bus/vdev/vdev.c +6 -4
@@ -115,8 +115,8 @@ rte_vdev_remove_custom_scan(rte_vdev_scan_callback callback, void *user_arg)return 0 ; } -static int -vdev_parse (const char *name,void *addr) +int +rte_vdev_parse (const char *name,void *addr) {struct rte_vdev_driver **out = addr;struct rte_vdev_driver *driver =NULL ;
@@ -148,7 +148,7 @@ vdev_probe_all_drivers(struct rte_vdev_device *dev)VDEV_LOG (DEBUG ,"Search driver %s to probe device %s" , name,rte_vdev_device_name (dev)); -if (vdev_parse (name, &driver)) +if (rte_vdev_parse (name, &driver))return -1 ; dev->device.driver = &driver->driver; ret = driver->probe (dev);
@@ -443,6 +443,8 @@ vdev_scan(void)/* for virtual devices we scan the devargs_list populated via cmdline */ RTE_EAL_DEVARGS_FOREACH("vdev", devargs) { +if (rte_vdev_devargs_prepare (devargs)) +continue ; dev =calloc (1 ,sizeof (*dev));if (!dev)
@@ -536,7 +538,7 @@ static struct rte_bus rte_vdev_bus = { .find_device = rte_vdev_find_device, .plug = vdev_plug, .unplug = vdev_unplug, - .parse = vdev_parse, + .parse = rte_vdev_parse, .dev_iterate = rte_vdev_dev_iterate, };
drivers/bus/vdev/vdev_params.c +50 -0
64 lines not on this page · raw message
drivers/bus/vdev/vdev_private.h +6 -0
@@ -19,6 +19,12 @@ rte_vdev_dev_iterate(const void *start,const char *str, const struct rte_dev_iterator *it); +int +rte_vdev_parse (const char *name,void *addr); + +int +rte_vdev_devargs_prepare (struct rte_devargs *da); + #ifdef __cplusplus }#endif
Signature · 1 line
2.11.0
PATCH v9 25/27 bus/pci: process declarative PCI devargs
In reply to Gaetan RivetIntroduce the facility to process future PCI parameters.
Once the matching between PCI devices and devargs has been done, it is possible to process each devargs. New parameters would have the PCI device handle to work with when parsing the device (bus specific) parameters.
--- drivers/bus/pci/pci_common.c | 3 +++ drivers/bus/pci/pci_params.c | 10 ++++++++++ drivers/bus/pci/private.h | 13 +++++++++++++ 3 files changed, 26 insertions(+)
drivers/bus/pci/pci_common.c +3 -0
@@ -251,6 +251,9 @@ pci_probe_all_drivers(struct rte_pci_device *dev)if (dev->driver !=NULL )return 0 ; +if (rte_pci_devargs_process (dev) <0 ) +return -1 ; +FOREACH_DRIVER_ON_PCIBUS (dr) { rc =rte_pci_probe_one_driver (dr, dev);if (rc <0 )
drivers/bus/pci/pci_params.c +10 -0
@@ -131,3 +131,13 @@ rte_pci_devargs_prepare(struct rte_devargs *da)rte_kvargs_free (kvargs);return ret; } + +int +rte_pci_devargs_process (struct rte_pci_device *pdev) +{ +/* For the moment, no PCI param +* needs to be processed. +*/ + (void ) pdev; +return 0 ; +}
drivers/bus/pci/private.h +13 -0
@@ -207,4 +207,17 @@ rte_pci_dev_iterate(const void *start,int rte_pci_devargs_prepare (struct rte_devargs *da); +/* +* Process the device devargs, if any. +* +* @param pdev +* PCI device +* +* @return +* 0 on success. +* <0 on error. +*/ +int +rte_pci_devargs_process (struct rte_pci_device *pdev); +#endif /* _PCI_PRIVATE_H_ */
Signature · 1 line
2.11.0
PATCH v9 26/27 ethdev: process declarative eth devargs
In reply to Gaetan RivetProcess the class-specific arguments in a devargs.
This processing takes the form of setting the proper eth_dev fields when relevant.
--- lib/librte_ethdev/eth_private.h | 5 ++++ lib/librte_ethdev/rte_class_eth.c | 61 +++++++++++++++++++++++++++++++++++++++ lib/librte_ethdev/rte_ethdev.c | 7 +++++ 3 files changed, 73 insertions(+)
lib/librte_ethdev/eth_private.h +5 -0
@@ -19,6 +19,11 @@ struct rte_eth_dev * eth_find_device(const struct rte_eth_dev *_start, rte_eth_cmp_t cmp, const void *data); +/* Generic rte_eth_dev parameters processor. */ +int +rte_eth_dev_args_parse (struct rte_eth_dev *eth_dev, +struct rte_devargs *da); + #ifdef __cplusplus }#endif
lib/librte_ethdev/rte_class_eth.c +61 -0
73 lines not on this page · raw message
lib/librte_ethdev/rte_ethdev.c +7 -0
@@ -41,6 +41,7 @@#include "rte_ethdev.h" #include "rte_ethdev_driver.h" #include "ethdev_profile.h" +#include "eth_private.h" static int ethdev_logtype;
@@ -3594,6 +3595,12 @@ rte_eth_dev_create(struct rte_device *device, const char *name, } } + retval =rte_eth_dev_args_parse (ethdev, device->devargs); +if (retval) { +RTE_LOG (ERR ,EAL ,"ethdev parsing failed" ); + goto probe_failed; + } + retval =ethdev_init (ethdev, init_params);if (retval) {RTE_LOG (ERR ,EAL ,"ethdev initialisation failed" );
Signature · 1 line
2.11.0
PATCH v9 27/27 eal: add generic dev parameter
In reply to Gaetan RivetAdd the --dev parameter to the EAL.
This new parameter takes a generic device declaration as argument.
It uses the new devargs parsing API.
--- lib/librte_eal/common/eal_common_devargs.c | 4 ++++ lib/librte_eal/common/eal_common_options.c | 36 +++++++++++++++++++++++++----- lib/librte_eal/common/eal_options.h | 2 ++ 3 files changed, 37 insertions(+), 5 deletions(-)
lib/librte_eal/common/eal_common_devargs.c +4 -0
@@ -218,6 +218,10 @@ rte_devargs_parse(struct rte_devargs *da, const char *dev)if (da ==NULL )return -EINVAL ; +if (strncmp (dev,"bus=" ,4 ) ==0 || +strncmp (dev,"class=" ,6 ) ==0 ) +return rte_devargs_layers_parse (da, dev); +/* Retrieve eventual bus info */ do { devname = dev;
lib/librte_eal/common/eal_common_options.c +31 -5
@@ -54,6 +54,7 @@ const struct option eal_long_options[] = { {OPT_BASE_VIRTADDR, 1, NULL, OPT_BASE_VIRTADDR_NUM }, {OPT_CREATE_UIO_DEV, 0, NULL, OPT_CREATE_UIO_DEV_NUM }, + {OPT_DEV, 1, NULL, OPT_DEV_NUM }, {OPT_FILE_PREFIX, 1, NULL, OPT_FILE_PREFIX_NUM }, {OPT_HELP, 0, NULL, OPT_HELP_NUM }, {OPT_HUGE_DIR, 1, NULL, OPT_HUGE_DIR_NUM },
@@ -109,6 +110,7 @@ TAILQ_HEAD(device_option_list, device_option);struct device_option {TAILQ_ENTRY (device_option) next; +int new;enum rte_devtype type;char arg[]; };
@@ -121,7 +123,8 @@ static int mem_parsed;static int core_parsed;static int -eal_option_device_add (enum rte_devtype type,const char *optarg) +eal_option_device_add (enum rte_devtype type,const char *optarg, +int new) {struct device_option *devopt;size_t optlen;
@@ -135,6 +138,7 @@ eal_option_device_add(enum rte_devtype type, const char *optarg) } devopt->type = type; + devopt->new = new; ret =snprintf (devopt->arg, optlen,"%s" , optarg);if (ret <0 ) {RTE_LOG (ERR ,EAL ,"Unable to copy device option\n" );
@@ -154,7 +158,22 @@ eal_option_device_parse(void) TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {if (ret ==0 ) { - ret =rte_devargs_add (devopt->type, devopt->arg); +if (devopt->new) { +struct rte_devargs *da; + + da =calloc (1 ,sizeof (*da)); + ret =rte_devargs_parse (da, devopt->arg); +if (ret) { +free (da); + }else { + ret =rte_devargs_insert (da); +if (ret) +free (da); + } + }else { + ret =rte_devargs_add (devopt->type, + devopt->arg); + }if (ret)RTE_LOG (ERR ,EAL ,"Unable to parse device '%s'\n" , devopt->arg);
@@ -1038,7 +1057,7 @@ eal_parse_common_option(int opt, const char *optarg,if (w_used) goto bw_used;if (eal_option_device_add (RTE_DEVTYPE_BLACKLISTED_PCI , - optarg) <0 ) { + optarg,0 ) <0 ) {return -1 ; } b_used =1 ;
@@ -1048,7 +1067,7 @@ eal_parse_common_option(int opt, const char *optarg,if (b_used) goto bw_used;if (eal_option_device_add (RTE_DEVTYPE_WHITELISTED_PCI , - optarg) <0 ) { + optarg,0 ) <0 ) {return -1 ; } w_used =1 ;
@@ -1177,9 +1196,16 @@ eal_parse_common_option(int opt, const char *optarg, }break ; +case OPT_DEV_NUM : +if (eal_option_device_add (RTE_DEVTYPE_VIRTUAL , + optarg,1 ) <0 ) { +return -1 ; + } +break ; +case OPT_VDEV_NUM :if (eal_option_device_add (RTE_DEVTYPE_VIRTUAL , - optarg) <0 ) { + optarg,0 ) <0 ) {return -1 ; }break ;
lib/librte_eal/common/eal_options.h +2 -0
@@ -21,6 +21,8 @@ enum {OPT_BASE_VIRTADDR_NUM , #define OPT_CREATE_UIO_DEV "create-uio-dev"OPT_CREATE_UIO_DEV_NUM , +#define OPT_DEV "dev" +OPT_DEV_NUM , #define OPT_FILE_PREFIX "file-prefix"OPT_FILE_PREFIX_NUM , #define OPT_HUGE_DIR "huge-dir"
Signature · 1 line
2.11.0
v10 cover Device querying
In reply to Gaetan RivetThis patchset introduces a new EAL API for querying devices, filtered by arbitrary properties.
The following elements are introduced to this end:
* A new object, "rte_class", is used to describe the device class abstraction layer (eth, crypto, ...).
* Both rte_bus and rte_class now offer a way to
list their devices and filter the result
using locally defined properties.
* The rte_dev API now has an rte_dev_iterator, which is the way for the user to define the device filter and iterate upon the resulting set.
As an example, the "eth" device class is implemented.
Additionally, the device filters for
+ rte_bus_pci
+ rte_bus_vdev
+ rte_class_eth
are implemented and can be used with some
properties each, to show how to extend those.
Some example of filters:
"bus=pci/class=eth"
"bus=pci"
"class=eth"
"class=eth,name=net_ring0"
"bus=pci,id=00:00.0"
"bus=vdev,driver=net_ring"
---
v2:
* Reworked the dev_iterate callback to simplify
its implementation.
Now dev_iterate implementation do not need to learn about the intricacies of the rte_dev_iterator. The rte_dev_iterator is managed purely by the rte_dev_iterator_next function. Buses and classes then do not have to care about settings things right.
Additionally, dev_iterate implementations do not have to sanitize their dev string anymore, they are prepared by the rte_dev layer prior, which also reduces the number of dynamic allocations.
v3:
* Introduced central constructor priority list.
* Removed lightweight kvarg parsing utility,
using librte_kvargs instead.
* Reversed dependencies of librte_kvargs and
librte_eal.
* Fixed a few bugs.
* @Bruce: I have noted the request for meson support.
I will install it and attempt it once the bulk of the work is done.
v4:
* Fixed a few bugs, added relevant acks,
fixed some typos.
* Made each matching functions actually check for a proper list of accepted properties.
* rte_kvargs now includes rte_eal directly and keeps rte_log.
* added generic string comparison function to rte_kvargs, as some kind of comparison should probably be shared by many layers.
v5:
* Rebased on master
* Use strcspn instead of custom function.
* Introduce private generic rte_eth_dev iterator. This could be generalized to other iterators (port_next, owner_id-aware, etc).
* Attempted to support meson.build.
Got lost in the implicit variables declared when inversing dependencies between kvargs and EAL. Removed anything related to meson.
* Postponed genericization of work from device query to device declaration.
Much bigger than anticipated, will let this part get in first and iterate over it.
v6:
* Rebased on master
* Introduce RTE_PRIORITY_LAST, to explicitly set the lowest constructor priority.
* Fix copyright notice for eth_privage.* files.
v7:
* Rebased on master
* Fix rte_kvargs_strcmp return value.
* Fix layer parsing error
devstr "bus=pci/onemorelayer" now tells
that the additional layer is not recognized.
v8:
* Rebased on master
* Cleaned kvargs use: introduced
a new parser function, that simplifies using the library for DPDK devargs.
* Refactored devargs parsing in a single function within rte_devargs.
This function is useful both for rte_dev parsing its iterator, and for rte_devargs parsing --dev parameters (not yet implemented).
* A few small bugfixes.
v9:
* Rebased on master
* Fixed cyclic dependency kvargs <-> eal
* Fixed a few checkpatch issues
* Added dynamic help to testpmd for new "show device" command
* Added devargs processing stubs to
primary buses / classes
* Added new --dev generic device declaration option
v10:
* Support meson build
Gaetan Rivet (27):
devargs: add non-variadic parsing function
kvargs: remove error logs
kvargs: build before EAL
kvargs: introduce a more flexible parsing function
eal: introduce dtor macros
eal: introduce device class abstraction eal/class: register destructor
devargs: add function to parse device layers eal/dev: add device iterator interface eal/class: add device iteration
eal/bus: add device iteration
eal/dev: implement device iteration initialization eal/dev: implement device iteration
kvargs: add generic string matching callback bus/pci: implement device iteration and comparison bus/pci: add device matching field id bus/vdev: implement device iteration bus/vdev: add device matching field driver
ethdev: add private generic device iterator
ethdev: register ether layer as a class
ethdev: add device matching field name app/testpmd: add show device command bus/pci: pre-process declarative PCI devargs bus/vdev: pre-process declarative vdev devargs bus/pci: process declarative PCI devargs
ethdev: process declarative eth devargs
eal: add generic dev parameter
app/test-pmd/cmdline.c | 54 +++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 24 +++ drivers/bus/pci/Makefile | 3 +- drivers/bus/pci/bsd/pci.c | 5 + drivers/bus/pci/linux/pci.c | 5 + drivers/bus/pci/meson.build | 6 +- drivers/bus/pci/pci_common.c | 6 +- drivers/bus/pci/pci_params.c | 139 ++++++++++++ drivers/bus/pci/private.h | 54 +++++ drivers/bus/vdev/Makefile | 3 +- drivers/bus/vdev/meson.build | 5 +- drivers/bus/vdev/vdev.c | 20 +- drivers/bus/vdev/vdev_params.c | 112 ++++++++++ drivers/bus/vdev/vdev_private.h | 32 +++ drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/Makefile | 5 +- lib/librte_eal/bsdapp/eal/Makefile | 2 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_class.c | 62 ++++++ lib/librte_eal/common/eal_common_dev.c | 227 +++++++++++++++++++- lib/librte_eal/common/eal_common_devargs.c | 190 +++++++++++++++- lib/librte_eal/common/eal_common_options.c | 36 +++- lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/common/eal_private.h | 27 +++ lib/librte_eal/common/include/rte_bus.h | 1 + lib/librte_eal/common/include/rte_class.h | 127 +++++++++++ lib/librte_eal/common/include/rte_common.h | 24 +++ lib/librte_eal/common/include/rte_dev.h | 97 +++++++++ lib/librte_eal/common/include/rte_devargs.h | 53 ++++- lib/librte_eal/common/meson.build | 2 + lib/librte_eal/linuxapp/eal/Makefile | 2 + lib/librte_eal/meson.build | 1 + lib/librte_eal/rte_eal_version.map | 5 + lib/librte_ethdev/Makefile | 4 +- lib/librte_ethdev/eth_private.c | 31 +++ lib/librte_ethdev/eth_private.h | 31 +++ lib/librte_ethdev/meson.build | 4 +- lib/librte_ethdev/rte_class_eth.c | 147 +++++++++++++ lib/librte_ethdev/rte_ethdev.c | 9 +- lib/librte_kvargs/Makefile | 2 +- lib/librte_kvargs/meson.build | 5 + lib/librte_kvargs/rte_kvargs.c | 57 +++-- lib/librte_kvargs/rte_kvargs.h | 58 +++++ lib/librte_kvargs/rte_kvargs_version.map | 8 + lib/meson.build | 8 +- 46 files changed, 1637 insertions(+), 64 deletions(-) create mode 100644 drivers/bus/pci/pci_params.c create mode 100644 drivers/bus/vdev/vdev_params.c create mode 100644 drivers/bus/vdev/vdev_private.h create mode 100644 lib/librte_eal/common/eal_common_class.c create mode 100644 lib/librte_eal/common/include/rte_class.h create mode 100644 lib/librte_ethdev/eth_private.c create mode 100644 lib/librte_ethdev/eth_private.h create mode 100644 lib/librte_ethdev/rte_class_eth.c
Signature · 1 line
2.18.0
PATCH v10 1/27 devargs: add non-variadic parsing function
rte_devargs_parse becomes non-variadic,rte_devargs_parsef becomes the variadic version, to be used to compose device strings.
--- drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 4 +- lib/librte_eal/common/eal_common_devargs.c | 42 ++++++++++++++++----- lib/librte_eal/common/include/rte_devargs.h | 40 +++++++++++++++++++- lib/librte_eal/rte_eal_version.map | 1 + lib/librte_ethdev/rte_ethdev.c | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)
drivers/net/failsafe/failsafe_args.c +1 -1
@@ -63,7 +63,7 @@ fs_parse_device(struct sub_device *sdev, char *args) d = &sdev->devargs;DEBUG ("%s" , args); - ret =rte_devargs_parse (d,"%s" , args); + ret =rte_devargs_parse (d, args);if (ret) {DEBUG ("devargs parsing failed with code %d" , ret);return ret;
drivers/net/failsafe/failsafe_eal.c +1 -1
@@ -86,7 +86,7 @@ fs_bus_init(struct rte_eth_dev *dev)else snprintf (devstr,sizeof (devstr),"%s" , rte_eth_devices[pid].device->name); - ret =rte_devargs_parse (da,"%s" , devstr); + ret =rte_devargs_parse (da, devstr);if (ret) {ERROR ("Probed devargs parsing failed with code" " %d" , ret);
lib/librte_eal/common/eal_common_dev.c +2 -2
@@ -138,8 +138,8 @@ int __rte_experimental rte_eal_hotplug_add(const char *busname, const char *devnif (da ==NULL )return -ENOMEM ; - ret =rte_devargs_parse (da,"%s:%s,%s" , - busname, devname, devargs); + ret =rte_devargs_parsef (da,"%s:%s,%s" , + busname, devname, devargs);if (ret) goto err_devarg;
lib/librte_eal/common/eal_common_devargs.c +32 -10
69 lines not on this page · raw message
lib/librte_eal/common/include/rte_devargs.h +38 -2
@@ -89,6 +89,42 @@ __rte_deprecatedint rte_eal_parse_devargs_str (const char *devargs_str,char **drvname,char **drvargs); +/** +* Parse a device string. +* +* Verify that a bus is capable of handling the device passed +* in argument. Store which bus will handle the device, its name +* and the eventual device parameters. +* +* The syntax is: +* +* bus:device_identifier,arg1=val1,arg2=val2 +* +* where "bus:" is the bus name followed by any character separator. +* The bus name is optional. If no bus name is specified, each bus +* will attempt to recognize the device identifier. The first one +* to succeed will be used. +* +* Examples: +* +* pci:0000:05.00.0,arg=val +* 05.00.0,arg=val +* vdev:net_ring0 +* +* @param da +* The devargs structure holding the device information. +* +* @param dev +* String describing a device. +* +* @return +* - 0 on success. +* - Negative errno on error. +*/ +__rte_experimental +int +rte_devargs_parse (struct rte_devargs *da,const char *dev); +/** * Parse a device string. *
@@ -124,8 +160,8 @@ int rte_eal_parse_devargs_str(const char *devargs_str,*/ __rte_experimental int -rte_devargs_parse (struct rte_devargs *da, -const char *format, ...) +rte_devargs_parsef (struct rte_devargs *da, +const char *format, ...) __attribute__((format (printf,2 ,0 )));/**
lib/librte_eal/rte_eal_version.map +1 -0
@@ -254,6 +254,7 @@ EXPERIMENTAL { rte_devargs_insert; rte_devargs_next; rte_devargs_parse; + rte_devargs_parsef; rte_devargs_remove; rte_devargs_type_count; rte_eal_cleanup;
lib/librte_ethdev/rte_ethdev.c +1 -1
@@ -654,7 +654,7 @@ rte_eth_dev_attach(const char *devargs, uint16_t *port_id) }/* parse devargs */ -if (rte_devargs_parse (&da,"%s" , devargs)) +if (rte_devargs_parse (&da, devargs)) goto err; ret =rte_eal_hotplug_add (da.bus->name, da.name, da.args);
Signature · 1 line
2.18.0
Re: [PATCH v10 01/27] devargs: add non-variadic parsing function
05/07/2018 13:48, Gaetan Rivet:
Quoted 5 lines
rte_devargs_parsebecomes non-variadic,rte_devargs_parsefbecomes the variadic version, to be used to compose device strings.Signed-off-by Gaetan Rivet <[email protected]>
Re: [PATCH v10 01/27] devargs: add non-variadic parsing function
In reply to Gaetan RivetQuoted 15 lines · Gaetan Rivet
rte_devargs_parsebecomes non-variadic,rte_devargs_parsefbecomes the variadic version, to be used to compose device strings.Signed-off-by Gaetan Rivet <[email protected]>--- drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 4 +- lib/librte_eal/common/eal_common_devargs.c | 42 ++++++++++++++++----- lib/librte_eal/common/include/rte_devargs.h | 40 +++++++++++++++++++- lib/librte_eal/rte_eal_version.map | 1 + lib/librte_ethdev/rte_ethdev.c | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)
[...]
Quoted 8 lines
lib/librte_eal/common/eal_common_devargs.c +8
-0+__rte_experimental +int +rte_devargs_parsef (struct rte_devargs *da,const char *format, ...) +{ +va_list ap; +size_t len; +char *dev; +
lib/librte_eal/common/eal_common_devargs.c rte_devargs_parse(struct rte_devargs *da, const char *format, ...) · line 138
Quoted 10 lines
lib/librte_eal/common/eal_common_devargs.c +10
-0+if (da ==NULL ) +return -EINVAL ; + +va_start (ap, format); + len =vsnprintf (NULL ,0 , format, ap); +va_end (ap); + + dev =calloc (1 , len +1 ); +if (dev ==NULL ) { +fprintf (stderr,"ERROR: not enough memory to parse device\n" );
Should RTE_LOG be used here?
lib/librte_eal/common/eal_common_devargs.c rte_devargs_parse(struct rte_devargs *da, const char *format, ...) · line 151
Quoted 13 lines
lib/librte_eal/common/eal_common_devargs.c +10
-0+return -ENOMEM ; + } + +va_start (ap, format); +vsnprintf (dev, len, format, ap); +va_end (ap); + +return rte_devargs_parse (da, dev); +} + int __rte_experimentalrte_devargs_insert (struct rte_devargs *da) {
[...]
Except the comment above:
Re: [PATCH v10 01/27] devargs: add non-variadic parsing function
Quoted 31 lines · Shreyansh Jain
Quoted 15 lines · Gaetan Rivet
rte_devargs_parsebecomes non-variadic,rte_devargs_parsefbecomes the variadic version, to be used to compose device strings.Signed-off-by Gaetan Rivet <[email protected]>--- drivers/net/failsafe/failsafe_args.c | 2 +- drivers/net/failsafe/failsafe_eal.c | 2 +- lib/librte_eal/common/eal_common_dev.c | 4 +- lib/librte_eal/common/eal_common_devargs.c | 42 ++++++++++++++++----- lib/librte_eal/common/include/rte_devargs.h | 40 +++++++++++++++++++- lib/librte_eal/rte_eal_version.map | 1 + lib/librte_ethdev/rte_ethdev.c | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)[...]
Quoted 12 lines
lib/librte_eal/common/eal_common_devargs.c +12
-0+__rte_experimental +int +rte_devargs_parsef (struct rte_devargs *da,const char *format, ...) +{ +va_list ap; +size_t len; +char *dev; + +if (da ==NULL ) +return -EINVAL ; + +va_start (ap, format);
Quoted 9 lines
lib/librte_eal/common/eal_common_devargs.c rte_devargs_parse(struct rte_devargs *da, const char *format, ...) · line 138
Quoted 6 lines
lib/librte_eal/common/eal_common_devargs.c +6
-0+ len =vsnprintf (NULL ,0 , format, ap); +va_end (ap); + + dev =calloc (1 , len +1 ); +if (dev ==NULL ) { +fprintf (stderr,"ERROR: not enough memory to parse device\n" );Should
RTE_LOGbe used here?
Yes, actually, I think the whole rte_devargs should be changed to RTE_LOG.
Quoted 19 lines
lib/librte_eal/common/eal_common_devargs.c rte_devargs_parse(struct rte_devargs *da, const char *format, ...) · line 151
Quoted 13 lines
lib/librte_eal/common/eal_common_devargs.c +10
-0+return -ENOMEM ; + } + +va_start (ap, format); +vsnprintf (dev, len, format, ap); +va_end (ap); + +return rte_devargs_parse (da, dev); +} + int __rte_experimentalrte_devargs_insert (struct rte_devargs *da) {[...]
Except the comment above:
Acked-by Shreyansh Jain <[email protected]>
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v10 2/27 kvargs: remove error logs
In reply to Gaetan RivetError logs in kvargs parsing should be better handled in components calling the library.
This library must be as lean as possible.
--- lib/librte_kvargs/rte_kvargs.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-)
lib/librte_kvargs/rte_kvargs.c +5 -17
@@ -6,7 +6,6 @@#include <string.h> #include <stdlib.h> -#include <rte_log.h> #include <rte_string_fns.h> #include "rte_kvargs.h"
@@ -28,29 +27,22 @@ rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params)* to pass to rte_strsplit */ kvlist->str =strdup (params); -if (kvlist->str ==NULL ) { -RTE_LOG (ERR ,PMD ,"Cannot parse arguments: not enough memory\n" ); +if (kvlist->str ==NULL )return -1 ; - }/* browse each key/value pair and add it in kvlist */ str = kvlist->str;while ((str =strtok_r (str,RTE_KVARGS_PAIRS_DELIM , &ctx1)) !=NULL ) { i = kvlist->count; -if (i >=RTE_KVARGS_MAX ) { -RTE_LOG (ERR ,PMD ,"Cannot parse arguments: list full\n" ); +if (i >=RTE_KVARGS_MAX )return -1 ; - } kvlist->pairs[i].key =strtok_r (str,RTE_KVARGS_KV_DELIM , &ctx2); kvlist->pairs[i].value =strtok_r (NULL ,RTE_KVARGS_KV_DELIM , &ctx2); -if (kvlist->pairs[i].key ==NULL || kvlist->pairs[i].value ==NULL ) { -RTE_LOG (ERR ,PMD , -"Cannot parse arguments: wrong key or value\n" -"params=<%s>\n" , params); +if (kvlist->pairs[i].key ==NULL || + kvlist->pairs[i].value ==NULL )return -1 ; - } kvlist->count++; str =NULL ;
@@ -89,12 +81,8 @@ check_for_valid_keys(struct rte_kvargs *kvlist,for (i =0 ; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; ret =is_valid_key (valid, pair->key); -if (!ret) { -RTE_LOG (ERR ,PMD , -"Error parsing device, invalid key <%s>\n" , - pair->key); +if (!ret)return -1 ; - } }return 0 ; }
Signature · 1 line
2.18.0