[v4,3/4] regexdev: add regexdev core functions
Checks
Commit Message
This commit introduce the API that is needed by the RegEx devices in
order to work with the RegEX lib.
During the probe of a RegEx device, the device should configure itself,
and allocate the resources it requires.
On completion of the device init, it should call the
rte_regex_dev_register in order to register itself as a RegEx device.
Signed-off-by: Ori Kam <orika@mellanox.com>
Signed-off-by: Parav Pandit <parav@mellanox.com>
Acked-by: Guy Kaneti <guyk@marvell.com>
---
v4:
* No changes.
v3:
* Add function to get device by name.
v2:
* Changes resulted from previous patch update.
---
config/common_base | 3 +-
config/meson.build | 1 +
lib/librte_regexdev/Makefile | 1 +
lib/librte_regexdev/meson.build | 5 +-
lib/librte_regexdev/rte_regexdev.c | 139 +++++++++++++++++++++++++++++-
lib/librte_regexdev/rte_regexdev.h | 7 ++
lib/librte_regexdev/rte_regexdev_core.h | 16 +++-
lib/librte_regexdev/rte_regexdev_driver.h | 59 +++++++++++++
meson_options.txt | 2 +
9 files changed, 229 insertions(+), 4 deletions(-)
create mode 100644 lib/librte_regexdev/rte_regexdev_driver.h
Comments
02/07/2020 09:46, Ori Kam:
> --- a/meson_options.txt
> +++ b/meson_options.txt
> @@ -30,6 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
> description: 'maximum number of cores/threads supported by EAL')
> option('max_numa_nodes', type: 'integer', value: 4,
> description: 'maximum number of NUMA nodes supported by EAL')
> +option('max_regexdev_devs', type: 'integer', value: 32,
> + description: 'maximum number of RegEx devices')
Do we really want to add such option in meson?
Some other classes do not expose any option here.
I tend to think it should be hidden.
If the max is really varying, it should be dynamic.
By the way, the maximum number of ethdev ports should be made infinite
with a dynamic array.
Bruce, any opinion please?
> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, July 6, 2020 12:08 AM
> Subject: Re: [dpdk-dev] [PATCH v4 3/4] regexdev: add regexdev core functions
>
> 02/07/2020 09:46, Ori Kam:
> > --- a/meson_options.txt
> > +++ b/meson_options.txt
> > @@ -30,6 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
> > description: 'maximum number of cores/threads supported by EAL')
> > option('max_numa_nodes', type: 'integer', value: 4,
> > description: 'maximum number of NUMA nodes supported by EAL')
> > +option('max_regexdev_devs', type: 'integer', value: 32,
> > + description: 'maximum number of RegEx devices')
>
> Do we really want to add such option in meson?
> Some other classes do not expose any option here.
> I tend to think it should be hidden.
> If the max is really varying, it should be dynamic.
> By the way, the maximum number of ethdev ports should be made infinite
> with a dynamic array.
>
> Bruce, any opinion please?
>
Why this is just like ethdev:
option('max_ethports', type: 'integer', value: 32,
description: 'maximum number of Ethernet devices')
Best,
Ori
06/07/2020 08:07, Ori Kam:
> From: Thomas Monjalon <thomas@monjalon.net>
> > 02/07/2020 09:46, Ori Kam:
> > > --- a/meson_options.txt
> > > +++ b/meson_options.txt
> > > @@ -30,6 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
> > > description: 'maximum number of cores/threads supported by EAL')
> > > option('max_numa_nodes', type: 'integer', value: 4,
> > > description: 'maximum number of NUMA nodes supported by EAL')
> > > +option('max_regexdev_devs', type: 'integer', value: 32,
> > > + description: 'maximum number of RegEx devices')
> >
> > Do we really want to add such option in meson?
> > Some other classes do not expose any option here.
> > I tend to think it should be hidden.
> > If the max is really varying, it should be dynamic.
> > By the way, the maximum number of ethdev ports should be made infinite
> > with a dynamic array.
> >
> > Bruce, any opinion please?
> >
> Why this is just like ethdev:
> option('max_ethports', type: 'integer', value: 32,
> description: 'maximum number of Ethernet devices')
Ethdev is the only class exposing such option.
And we already have some requests to replace it with
on-demand runtime dynamic size.
That's why it's better not exposing such bad config.
Anyway we are probably not going to need more than 32 regex engines
in the near future. It gives us time to switch to a dynamic model.
On Mon, Jul 06, 2020 at 09:03:49AM +0200, Thomas Monjalon wrote:
> 06/07/2020 08:07, Ori Kam:
> > From: Thomas Monjalon <thomas@monjalon.net>
> > > 02/07/2020 09:46, Ori Kam:
> > > > --- a/meson_options.txt
> > > > +++ b/meson_options.txt
> > > > @@ -30,6 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
> > > > description: 'maximum number of cores/threads supported by EAL')
> > > > option('max_numa_nodes', type: 'integer', value: 4,
> > > > description: 'maximum number of NUMA nodes supported by EAL')
> > > > +option('max_regexdev_devs', type: 'integer', value: 32,
> > > > + description: 'maximum number of RegEx devices')
> > >
> > > Do we really want to add such option in meson?
> > > Some other classes do not expose any option here.
> > > I tend to think it should be hidden.
> > > If the max is really varying, it should be dynamic.
> > > By the way, the maximum number of ethdev ports should be made infinite
> > > with a dynamic array.
> > >
> > > Bruce, any opinion please?
> > >
> > Why this is just like ethdev:
> > option('max_ethports', type: 'integer', value: 32,
> > description: 'maximum number of Ethernet devices')
>
> Ethdev is the only class exposing such option.
> And we already have some requests to replace it with
> on-demand runtime dynamic size.
> That's why it's better not exposing such bad config.
> Anyway we are probably not going to need more than 32 regex engines
> in the near future. It gives us time to switch to a dynamic model.
>
I would tend to agree. In general I do not like adding new config options
so I'd prefer this not be exposed unless necessary. For ethdev, since it is
by far the mostly widely used, and since we know that people have some
varying port requirements, we have exposed this, while other classes have
not, indicating that it's probably not necessary for most device
categories.
/Bruce
@@ -832,9 +832,10 @@ CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV=y
CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV=y
#
-# Compile regex device support
+# Compile RexEx device support
#
CONFIG_RTE_LIBRTE_REGEXDEV=y
+CONFIG_RTE_MAX_REGEXDEV_DEVS=32
#
# Compile librte_ring
@@ -232,6 +232,7 @@ endforeach
dpdk_conf.set('RTE_MAX_LCORE', get_option('max_lcores'))
dpdk_conf.set('RTE_MAX_NUMA_NODES', get_option('max_numa_nodes'))
dpdk_conf.set('RTE_MAX_ETHPORTS', get_option('max_ethports'))
+dpdk_conf.set('RTE_MAX_REGEXDEV_DEVS', get_option('max_regexdev_devs'))
dpdk_conf.set('RTE_LIBEAL_USE_HPET', get_option('use_hpet'))
dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp'))
# values which have defaults which may be overridden
@@ -25,6 +25,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_REGEXDEV) := rte_regexdev.c
# export include files
SYMLINK-$(CONFIG_RTE_LIBRTE_REGEXDEV)-include += rte_regexdev.h
SYMLINK-$(CONFIG_RTE_LIBRTE_REGEXDEV)-include += rte_regexdev_core.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_REGEXDEV)-include += rte_regexdev_driver.h
# versioning export map
EXPORT_MAP := rte_regexdev_version.map
@@ -1,7 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2020 Mellanox Corporation
+name = 'regexdev'
allow_experimental_apis = true
sources = files('rte_regexdev.c')
-headers = files('rte_regexdev.h', 'rte_regexdev_core.h')
+headers = files('rte_regexdev.h',
+ 'rte_regexdev_core.h',
+ 'rte_regexdev_driver.h')
deps += ['mbuf']
@@ -3,4 +3,141 @@
* Copyright(C) 2020 Mellanox International Ltd.
*/
-#include <rte_regexdev.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_string_fns.h>
+
+#include "rte_regexdev.h"
+#include "rte_regexdev_core.h"
+#include "rte_regexdev_driver.h"
+
+static const char *MZ_RTE_REGEXDEV_DATA = "rte_regexdev_data";
+static struct rte_regexdev regex_devices[RTE_MAX_REGEXDEV_DEVS];
+/* Shared memory between primary and secondary processes. */
+static struct {
+ struct rte_regexdev_data data[RTE_MAX_REGEXDEV_DEVS];
+} *rte_regexdev_shared_data;
+
+int rte_regexdev_logtype;
+
+static uint16_t
+regexdev_find_free_dev(void)
+{
+ uint16_t i;
+
+ for (i = 0; i < RTE_MAX_REGEXDEV_DEVS; i++) {
+ if (regex_devices[i].state == RTE_REGEXDEV_UNUSED)
+ return i;
+ }
+ return RTE_MAX_REGEXDEV_DEVS;
+}
+
+static struct rte_regexdev*
+regexdev_allocated(const char *name)
+{
+ uint16_t i;
+
+ for (i = 0; i < RTE_MAX_REGEXDEV_DEVS; i++) {
+ if (regex_devices[i].state != RTE_REGEXDEV_UNUSED)
+ if (!strcmp(name, regex_devices[i].data->dev_name))
+ return ®ex_devices[i];
+ }
+ return NULL;
+}
+
+static int
+regexdev_shared_data_prepare(void)
+{
+ const unsigned int flags = 0;
+ const struct rte_memzone *mz;
+
+ if (rte_regexdev_shared_data == NULL) {
+ /* Allocate port data and ownership shared memory. */
+ mz = rte_memzone_reserve(MZ_RTE_REGEXDEV_DATA,
+ sizeof(*rte_regexdev_shared_data),
+ rte_socket_id(), flags);
+ if (mz == NULL)
+ return -ENOMEM;
+
+ rte_regexdev_shared_data = mz->addr;
+ memset(rte_regexdev_shared_data->data, 0,
+ sizeof(rte_regexdev_shared_data->data));
+ }
+ return 0;
+}
+
+static int
+regexdev_check_name(const char *name)
+{
+ size_t name_len;
+
+ if (name == NULL) {
+ RTE_REGEXDEV_LOG(ERR, "Name can't be NULL\n");
+ return -EINVAL;
+ }
+ name_len = strnlen(name, RTE_REGEXDEV_NAME_MAX_LEN);
+ if (name_len == 0) {
+ RTE_REGEXDEV_LOG(ERR, "Zero length RegEx device name\n");
+ return -EINVAL;
+ }
+ if (name_len >= RTE_REGEXDEV_NAME_MAX_LEN) {
+ RTE_REGEXDEV_LOG(ERR, "RegEx device name is too long\n");
+ return -EINVAL;
+ }
+ return (int)name_len;
+
+}
+
+struct rte_regexdev *
+rte_regexdev_register(const char *name)
+{
+ uint16_t dev_id;
+ int name_len;
+ struct rte_regexdev *dev;
+
+ name_len = regexdev_check_name(name);
+ if (name_len < 0)
+ return NULL;
+ dev = regexdev_allocated(name);
+ if (dev != NULL) {
+ RTE_REGEXDEV_LOG(ERR, "RegEx device already allocated\n");
+ return NULL;
+ }
+ dev_id = regexdev_find_free_dev();
+ if (dev_id == RTE_MAX_REGEXDEV_DEVS) {
+ RTE_REGEXDEV_LOG
+ (ERR, "Reached maximum number of RegEx devices\n");
+ return NULL;
+ }
+ if (regexdev_shared_data_prepare() < 0) {
+ RTE_REGEXDEV_LOG(ERR, "Cannot allocate RegEx shared data\n");
+ return NULL;
+ }
+
+ dev = ®ex_devices[dev_id];
+ dev->state = RTE_REGEXDEV_REGISTERED;
+ if (dev->data == NULL)
+ dev->data = &rte_regexdev_shared_data->data[dev_id];
+ else
+ memset(dev->data, 1, sizeof(*dev->data));
+ dev->data->dev_id = dev_id;
+ strlcpy(dev->data->dev_name, name, sizeof(dev->data->dev_name));
+ return dev;
+}
+
+void
+rte_regexdev_unregister(struct rte_regexdev *dev)
+{
+ dev->state = RTE_REGEXDEV_UNUSED;
+}
+
+struct rte_regexdev *
+rte_regexdev_get_device_by_name(const char *name)
+{
+ if (regexdev_check_name(name) < 0)
+ return NULL;
+ return regexdev_allocated(name);
+}
@@ -206,6 +206,13 @@
#include <rte_mbuf.h>
#include <rte_memory.h>
+#define RTE_REGEXDEV_NAME_MAX_LEN RTE_DEV_NAME_MAX_LEN
+
+extern int rte_regexdev_logtype;
+
+#define RTE_REGEXDEV_LOG(level, ...) \
+ rte_log(RTE_LOG_ ## level, rte_regexdev_logtype, "" __VA_ARGS__)
+
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice.
@@ -127,7 +127,18 @@ struct rte_regexdev_ops {
regexdev_dump_t dev_dump;
};
-#define RTE_REGEXDEV_NAME_MAX_LEN
+/**
+ * @internal
+ * Possible states of a RegEx device.
+ */
+enum rte_regexdev_state {
+ RTE_REGEXDEV_UNUSED = 0, /**< Device is unused. */
+ RTE_REGEXDEV_REGISTERED,
+ /**< Device is registered, but not ready to be used. */
+ RTE_REGEXDEV_READY,
+ /**< Device is ready for use. This is set by the PMD. */
+};
+
/**
* @internal
* The data part, with no function pointers, associated with each RegEx device.
@@ -137,6 +148,8 @@ struct rte_regexdev_ops {
*/
struct rte_regexdev_data {
void *dev_private; /**< PMD-specific private data. */
+ char dev_name[RTE_REGEXDEV_NAME_MAX_LEN]; /**< Unique identifier name */
+ uint16_t dev_id; /**< Device [external] identifier. */
} __rte_cache_aligned;
/**
@@ -155,6 +168,7 @@ struct rte_regexdev {
const struct rte_regexdev_ops *dev_ops;
/**< Functions exported by PMD */
struct rte_device *device; /**< Backing device */
+ enum rte_regexdev_state state; /**< The device state. */
struct rte_regexdev_data *data; /**< Pointer to device data. */
} __rte_cache_aligned;
new file mode 100644
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Mellanox Corporation
+ */
+
+#ifndef _RTE_REGEXDEV_DRIVER_H_
+#define _RTE_REGEXDEV_DRIVER_H_
+
+/**
+ * @file
+ *
+ * RTE RegEx Device PMD API
+ *
+ * APIs that are used by the RegEx drivers, to comunicate with the
+ * RegEx lib.
+ */
+
+#include "rte_regexdev.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @internal
+ * Register a RegEx device slot for a RegEx device and return the
+ * pointer to that slot.
+ *
+ * @param name
+ * RegEx device name.
+ *
+ * @return
+ * A pointer to the RegEx device slot case of success,
+ * NULL otherwise.
+ */
+struct rte_regexdev *rte_regexdev_register(const char *name);
+
+/**
+ * @internal
+ * Unregister the specified regexdev port.
+ *
+ * @param dev
+ * Device to be released.
+ */
+void rte_regexdev_unregister(struct rte_regexdev *dev);
+
+/**
+ * @internal
+ * Return the RegEx device based on the device name.
+ *
+ * @param name
+ * The device name.
+ */
+struct rte_regexdev *rte_regexdev_get_device_by_name(const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_REGEXDEV_DRIVER_H_ */
@@ -30,6 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
description: 'maximum number of cores/threads supported by EAL')
option('max_numa_nodes', type: 'integer', value: 4,
description: 'maximum number of NUMA nodes supported by EAL')
+option('max_regexdev_devs', type: 'integer', value: 32,
+ description: 'maximum number of RegEx devices')
option('enable_trace_fp', type: 'boolean', value: false,
description: 'enable fast path trace points.')
option('tests', type: 'boolean', value: true,