@@ -253,6 +253,12 @@ F: lib/librte_eventdev/
F: drivers/event/skeleton/
F: test/test/test_eventdev.c
+Bus Drivers
+-----------
+
+Net
+M: Gaetan Rivet <gaetan.rivet@6wind.com>
+F: drivers/bus/net/
Networking Drivers
------------------
@@ -48,3 +48,5 @@ CONFIG_RTE_LIBRTE_AVP_PMD=y
CONFIG_RTE_LIBRTE_NFP_PMD=y
CONFIG_RTE_LIBRTE_POWER=y
CONFIG_RTE_VIRTIO_USER=y
+CONFIG_RTE_LIBRTE_NET_BUS=y
+CONFIG_RTE_LIBRTE_NET_BUS_DEBUG=n
@@ -37,5 +37,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc
DEPDIRS-fslmc = $(core-libs)
DIRS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci
DEPDIRS-pci = $(core-libs)
+DIRS-$(CONFIG_RTE_LIBRTE_NET_BUS) += net
+DEPDIRS-net = $(core-libs) pci
include $(RTE_SDK)/mk/rte.subdir.mk
new file mode 100644
@@ -0,0 +1,66 @@
+# BSD LICENSE
+#
+# Copyright(c) 2017 6WIND S.A.
+# Author: Gaetan Rivet
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of 6WIND nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+LIB = librte_bus_net.a
+LIBABIVER := 1
+
+CFLAGS += $(WERROR_FLAGS)
+ifeq ($(DEBUG),1)
+CONFIG_RTE_LIBRTE_NET_BUS_DEBUG := y
+endif
+ifeq ($(CONFIG_RTE_LIBRTE_NET_BUS_DEBUG),y)
+CFLAGS += -UNDEBUG -g -O0
+else
+CFLAGS += -DNDEBUG -O3
+endif
+CFLAGS += -I$(RTE_SDK)/drivers/bus/net
+CFLAGS += -I$(RTE_SDK)/drivers/bus/net/include
+
+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),)
+SYSTEM := linux
+endif
+ifneq ($(CONFIG_RTE_EXEC_ENV_BDSAPP),)
+SYSTEM := bsd
+endif
+
+EXPORT_MAP := $(SYSTEM)/rte_bus_net_version.map
+CFLAGS += -I$(RTE_SDK)/drivers/bus/net/$(SYSTEM)
+
+include $(RTE_SDK)/drivers/bus/net/$(SYSTEM)/Makefile
+SRCS-$(CONFIG_RTE_LIBRTE_NET_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))
+SRCS-$(CONFIG_RTE_LIBRTE_NET_BUS) += rte_bus_net.c
+
+SYMLINK-$(CONFIG_RTE_LIBRTE_PCI_BUS)-include += include/rte_bus_net.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,33 @@
+# BSD LICENSE
+#
+# Copyright(c) 2017 6WIND S.A.
+# Author: Gaetan Rivet
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of 6WIND nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+$(error Net BUS not supported on BSD yet)
new file mode 100644
@@ -0,0 +1,14 @@
+DPDK_17.08 {
+ global:
+
+ rte_net_register;
+ rte_net_unregister;
+ rte_bus_net_dev_stat;
+ rte_bus_net_driver;
+ rte_bus_net_pci_loc;
+ rte_bus_net_virtual_xfrm;
+ rte_bus_net_pci_xfrm;
+ rte_bus_net_path_read;
+
+ local: *;
+};
new file mode 100644
@@ -0,0 +1,205 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 6WIND S.A.
+ * Author: Gaetan Rivet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_NET_BUS_H_
+#define _RTE_NET_BUS_H_
+
+#include <sys/queue.h>
+#include <stdint.h>
+
+#include <rte_devargs.h>
+#include <rte_dev.h>
+#include <rte_bus.h>
+
+/**
+ * @file
+ *
+ * RTE Net bus.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Name of net bus. */
+#define RTE_BUS_NET_NAME "net"
+
+/**
+ * Structure describing an RTE net device.
+ */
+struct rte_net_device {
+ TAILQ_ENTRY(rte_net_device) next; /**< Next net device. */
+ struct rte_device device; /**< Inherit core device. */
+ struct rte_net_driver *driver; /**< Associated driver. */
+ struct rte_devargs *da; /**< Device parameters. */
+ struct rte_device *sh_dev; /**< Shadow device. */
+ char name[33]; /**< Kernel netdev name. */
+};
+
+/**
+ * Name transform callback.
+ * Transform a netdevice name into its DPDK counterpart.
+ *
+ * @param[in] src
+ * original devargs to transform.
+ *
+ * @param[out] dst
+ * rte_devargs resulting from the transformation.
+ *
+ * @return
+ * 0 for no error.
+ * !0 otherwise.
+ */
+typedef int (*rte_bus_net_xfrm_t)(const struct rte_devargs *src,
+ struct rte_devargs *dst);
+
+/**
+ * Name transform base implementations.
+ */
+int rte_bus_net_virtual_xfrm(const struct rte_devargs *src,
+ struct rte_devargs *dst);
+int rte_bus_net_pci_xfrm(const struct rte_devargs *src,
+ struct rte_devargs *dst);
+
+/**
+ * Structure describing an RTE net driver.
+ */
+struct rte_net_driver {
+ TAILQ_ENTRY(rte_net_driver) next; /**< Next net driver. */
+ struct rte_driver driver; /**< Inherit core driver. */
+ char kmod[33]; /**< Kernel driver name. */
+ rte_bus_net_xfrm_t xfrm; /**< Name transform. */
+};
+
+/**
+ * Register a net driver.
+ *
+ * @param driver
+ * A pointer to an rte_net_driver structure describing the driver
+ * to be registered.
+ */
+void rte_net_register(struct rte_net_driver *driver);
+
+/** Helper for net device registration from driver instance. */
+#define RTE_PMD_REGISTER_NET(nm, net_drv) \
+RTE_INIT(netinitfn_ ##nm); \
+static void netinitfn_ ##nm(void) \
+{ \
+ (net_drv).driver.name = RTE_STR(nm); \
+ rte_net_register(&net_drv); \
+} \
+RTE_PMD_EXPORT_NAME(netdev_ ##nm, __COUNTER__)
+
+/**
+ * Unregister a net driver.
+ *
+ * @param driver
+ * A pointer to an rte_net_driver structure describing the driver
+ * to be unregistered.
+ */
+void rte_net_unregister(struct rte_net_driver *driver);
+
+/**
+ * Get netdevice status.
+ *
+ * @param name
+ * Net device name.
+ *
+ * @return
+ * 0 if device exist as a net device.
+ * !0 otherwise.
+ */
+int rte_bus_net_dev_stat(const char *name);
+
+/**
+ * Get netdevice driver name.
+ *
+ * @param[in] name
+ * Net device name.
+ *
+ * @param[out] out
+ * Buffer to write the driver name to.
+ *
+ * @param[in] size
+ * Buffer length.
+ *
+ * @return
+ * 0 if driver was successfully written.
+ * !0 otherwise.
+ */
+int rte_bus_net_driver(const char *name, char *out, size_t size);
+
+/**
+ * Get netdevice PCI location.
+ *
+ * @param[in] name
+ * Net device name.
+ *
+ * @param[out] out
+ * Buffer to write the PCI address to.
+ *
+ * @param[in] size
+ * Buffer length.
+ *
+ * @return
+ * 0 if PCI address was successfully written.
+ * !0 otherwise.
+ */
+int rte_bus_net_pci_loc(const char *name, char *out, size_t size);
+
+/**
+ * Read the content of a file.
+ *
+ * @param[out] out
+ * Buffer to write the content to.
+ *
+ * @param[in] size
+ * Buffer length.
+ *
+ * @param[in] format
+ * printf-like format string describing the path
+ * of the file to read.
+ *
+ * @return
+ * 0 if all was written successfully.
+ * !0 otherwise. errno is set.
+ */
+int rte_bus_net_path_read(char *out, size_t size,
+ const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_NET_BUS_H_ */
new file mode 100644
@@ -0,0 +1,35 @@
+# BSD LICENSE
+#
+# Copyright(c) 2017 6WIND S.A.
+# Author: Gaetan Rivet
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of 6WIND nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SRCS += rte_bus_net.c
+
+CFLAGS += -D_GNU_SOURCE
new file mode 100644
@@ -0,0 +1,225 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 6WIND S.A.
+ * Author: Gaetan Rivet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <dirent.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rte_bus.h>
+
+#include "rte_bus_net.h"
+#include "private.h"
+
+/* Default path */
+const char SYSFS_NET_DEVICES[] = "/sys/class/net";
+
+int
+rte_bus_net_path_read(char *out, size_t size,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ char path[vsnprintf(NULL, 0, format, ap) + 1];
+ FILE *file;
+ int ret;
+ int err;
+
+ va_end(ap);
+ va_start(ap, format);
+ vsnprintf(path, sizeof(path), format, ap);
+ file = fopen(path, "rb");
+ if (file == NULL) {
+ ERROR("failed to open file %s (%s)",
+ path, strerror(errno));
+ va_end(ap);
+ return -1;
+ }
+ ret = fread(out, size, 1, file);
+ err = errno;
+ if (((size_t)ret < size) && (ferror(file))) {
+ va_end(ap);
+ ret = -1;
+ }
+ fclose(file);
+ errno = err;
+ va_end(ap);
+ return ret;
+}
+
+static int
+parse_u32(const char *val, uint32_t *out)
+{
+ char *end;
+ uint64_t tmp;
+
+ errno = 0;
+ tmp = strtoull(val, &end, 0);
+ if (errno != 0 || val[0] == '\0' || end == NULL)
+ return -EINVAL;
+ if (tmp > UINT32_MAX)
+ return -ERANGE;
+ *out = (uint32_t) tmp;
+ return 0;
+}
+
+static uint32_t
+dev_flags(const char *name)
+{
+ char buf[32] = "";
+ uint32_t val;
+
+ if (rte_bus_net_path_read(buf, sizeof(buf), "%s/%s/flags",
+ net_get_sysfs_path(), name)) {
+ ERROR("failed to read flags on device %s", name);
+ return 0;
+ }
+ if (parse_u32(buf, &val)) {
+ ERROR("failed to parse %s", buf);
+ return 0;
+ }
+ return val;
+}
+
+int
+net_scan(void)
+{
+ struct dirent *e;
+ DIR *dir;
+ const char *path;
+ int ret = 0;
+ int scan_blist = 0;
+
+ path = net_get_sysfs_path();
+ dir = opendir(path);
+ if (dir == NULL) {
+ ret = errno;
+ ERROR("opendir %s failed: %s", path, strerror(errno));
+ return -1;
+ }
+ if (rte_bus_net.conf.scan_mode == RTE_BUS_SCAN_BLACKLIST)
+ scan_blist = 1;
+ while ((e = readdir(dir)) != NULL) {
+ if (e->d_name[0] == '.')
+ continue;
+ if (dev_flags(e->d_name) & 0x8)
+ continue;
+ if (scan_blist ^
+ !net_devargs_lookup(e->d_name))
+ continue;
+ /* Scan errors are ignored in blacklist mode. */
+ if (!net_scan_one(e->d_name) && !scan_blist)
+ goto out;
+ }
+out:
+ closedir(dir);
+ return ret;
+}
+
+int
+rte_bus_net_dev_stat(const char *name)
+{
+ struct stat buf;
+ int err;
+ MKSTR(path, "%s/%s", net_get_sysfs_path(), name);
+
+ if (name[0] == '\0')
+ return -1;
+ snprintf(path, sizeof(path), "%s/%s",
+ net_get_sysfs_path(), name);
+ err = errno;
+ errno = 0;
+ if (stat(path, &buf)) {
+ if (errno != ENOENT)
+ ERROR("stat(%s) failed: %s", path, strerror(errno));
+ errno = err;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+link_read(const char *path, char *out, size_t size)
+{
+ struct stat buf;
+ int err;
+
+ err = errno;
+ errno = 0;
+ if (stat(path, &buf)) {
+ if (errno != ENOENT)
+ ERROR("stat(%s) failed: %s", path, strerror(errno));
+ errno = err;
+ return -1;
+ }
+ if (size > 0) {
+ char buf[PATH_MAX + 1] = "";
+ ssize_t wlen;
+ char *s;
+
+ wlen = readlink(path, buf, sizeof(buf) - 1);
+ if (wlen > 0) {
+ out[wlen] = '\0';
+ } else {
+ ERROR("readlink(%s) failed: %s", path,
+ strerror(errno));
+ errno = err;
+ return -1;
+ }
+ for (s = &buf[wlen]; *s != '/'; s--)
+ ;
+ snprintf(out, size, "%s", &s[1]);
+ }
+ return 0;
+}
+
+int
+rte_bus_net_driver(const char *name, char *out, size_t size)
+{
+ MKSTR(path, "%s/%s/device/driver", net_get_sysfs_path(), name);
+
+ return link_read(path, out, size);
+}
+
+int
+rte_bus_net_pci_loc(const char *name, char *out, size_t size)
+{
+ MKSTR(path, "%s/%s/device", net_get_sysfs_path(), name);
+
+ return link_read(path, out, size);
+}
new file mode 100644
@@ -0,0 +1,14 @@
+DPDK_17.08 {
+ global:
+
+ rte_net_register;
+ rte_net_unregister;
+ rte_bus_net_dev_stat;
+ rte_bus_net_driver;
+ rte_bus_net_pci_loc;
+ rte_bus_net_virtual_xfrm;
+ rte_bus_net_pci_xfrm;
+ rte_bus_net_path_read;
+
+ local: *;
+};
new file mode 100644
@@ -0,0 +1,144 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 6WIND S.A.
+ * Author: Gaetan Rivet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_PRIVATE_H_
+#define _NET_PRIVATE_H_
+
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_tailq.h>
+
+#include "rte_bus_net.h"
+
+/* Double linked list of devices. */
+TAILQ_HEAD(net_device_list, rte_net_device);
+/* Double linked list of drivers. */
+TAILQ_HEAD(net_driver_list, rte_net_driver);
+
+extern struct net_device_list net_device_list;
+extern struct net_driver_list net_driver_list;
+
+/* Bus handle. */
+extern struct rte_bus rte_bus_net;
+
+/** Default net devices path. */
+extern const char SYSFS_NET_DEVICES[];
+
+/* Find the rte_net_driver of a kernel device. */
+struct rte_net_driver *net_drv_find(const char *name);
+
+/* Parse device name. */
+int net_parse(const char *name, void *addr);
+
+/* Scan a single device. */
+struct rte_net_device *net_scan_one(const char *name);
+
+/* Scan sysfs. */
+int net_scan(void);
+
+/* Get sysfs path. */
+const char *net_get_sysfs_path(void);
+
+/* Find devargs of a device. */
+struct rte_devargs *net_devargs_lookup(const char *name);
+
+/* Read file content. */
+int path_read(char *out, size_t size, const char *format, ...)
+ __attribute__((format(printf, 3, 0)));
+
+/* Net Bus iterators. */
+#define FOREACH_NET_DEVICE(p) \
+ TAILQ_FOREACH(p, &(net_device_list), next)
+
+#define FOREACH_NET_DEVICE_SAFE(p, tmp) \
+ TAILQ_FOREACH_SAFE(p, &(net_device_list), next, tmp)
+
+#define FOREACH_NET_DRIVER(p) \
+ TAILQ_FOREACH(p, &(net_driver_list), next)
+
+#define FOREACH_NET_DRIVER_SAFE(p, tmp) \
+ TAILQ_FOREACH_SAFE(p, &(net_driver_list), next, tmp)
+
+/* Net lists operators. */
+#define INSERT_NET_DEVICE(dev) \
+ TAILQ_INSERT_TAIL(&net_device_list, dev, next)
+
+#define REMOVE_NET_DEVICE(dev) \
+ TAILQ_REMOVE(&net_device_list, dev, next)
+
+#define INSERT_NET_DRIVER(drv) \
+ TAILQ_INSERT_TAIL(&net_driver_list, drv, next)
+
+#define REMOVE_NET_DRIVER(drv) \
+ TAILQ_REMOVE(&net_driver_list, drv, next)
+
+/* Debugging */
+#ifndef NDEBUG
+#include <stdio.h>
+#define DEBUG__(m, ...) \
+ (fprintf(stderr, "%s:%d: %s(): " m "%c", \
+ __FILE__, __LINE__, __func__, __VA_ARGS__), \
+ fflush(stderr), \
+ (void)0)
+/*
+ * Save/restore errno around DEBUG__().
+ * XXX somewhat undefined behavior, but works.
+ */
+#define DEBUG_(...) \
+ (errno = ((int []){ \
+ *(volatile int *)&errno, \
+ (DEBUG__(__VA_ARGS__), 0) \
+ })[0])
+#define DEBUG(...) DEBUG_(__VA_ARGS__, '\n')
+#define INFO(...) DEBUG(__VA_ARGS__)
+#define WARN(...) DEBUG(__VA_ARGS__)
+#define ERROR(...) DEBUG(__VA_ARGS__)
+#else /* NDEBUG */
+#define LOG__(level, m, ...) \
+ RTE_LOG(level, EAL, "NET: " m "%c", __VA_ARGS__)
+#define LOG_(level, ...) LOG__(level, __VA_ARGS__, '\n')
+#define DEBUG(...) (void)0
+#define INFO(...) LOG_(INFO, __VA_ARGS__)
+#define WARN(...) LOG_(WARNING, "WARNING: " __VA_ARGS__)
+#define ERROR(...) LOG_(ERR, "ERROR: " __VA_ARGS__)
+#endif /* NDEBUG */
+
+/* Allocate a buffer on the stack and fill it with a printf format string. */
+#define MKSTR(name, ...) \
+ char name[snprintf(NULL, 0, __VA_ARGS__) + 1]; \
+ \
+ snprintf(name, sizeof(name), __VA_ARGS__)
+
+#endif /* _NET_PRIVATE_H_ */
new file mode 100644
@@ -0,0 +1,265 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 6WIND S.A.
+ * Author: Gaetan Rivet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include <rte_devargs.h>
+#include <rte_dev.h>
+#include <rte_bus.h>
+#include <rte_errno.h>
+
+#include "rte_bus_net.h"
+#include "private.h"
+
+struct net_device_list net_device_list =
+ TAILQ_HEAD_INITIALIZER(net_device_list);
+struct net_driver_list net_driver_list =
+ TAILQ_HEAD_INITIALIZER(net_driver_list);
+
+struct rte_devargs *
+net_devargs_lookup(const char *name)
+{
+ struct rte_devargs *da;
+
+ TAILQ_FOREACH(da, &devargs_list, next) {
+ if (da->bus != &rte_bus_net)
+ continue;
+ if (!strcmp(da->name, name))
+ return da;
+ }
+ return NULL;
+}
+
+struct rte_net_driver *
+net_drv_find(const char *name)
+{
+ struct rte_net_driver *drv = NULL;
+ char drv_kmod[32] = "";
+
+ if (rte_bus_net_driver(name, drv_kmod, sizeof(drv_kmod)))
+ return NULL;
+ FOREACH_NET_DRIVER(drv)
+ if (!strcmp(drv->kmod, drv_kmod))
+ break;
+ return drv;
+}
+
+/*
+ * typeof(addr): struct rte_net_device *
+ */
+int
+net_parse(const char *name, void *addr)
+{
+ struct rte_net_device *dev = addr;
+ struct rte_net_driver *drv = NULL;
+ struct rte_devargs devargs;
+ struct rte_devargs *da;
+ struct rte_devargs *sub;
+
+ if (rte_bus_net_dev_stat(name))
+ return 1;
+ if (addr == NULL)
+ return 0;
+ drv = net_drv_find(name);
+ if (drv == NULL) {
+ DEBUG("unable to find driver");
+ rte_errno = EFAULT;
+ return -1;
+ }
+ dev->driver = drv;
+ da = dev->device.devargs;
+ if (!da) {
+ da = &devargs;
+ snprintf(da->name, sizeof(da->name), "%s", name);
+ da->args = NULL;
+ sub = calloc(1, sizeof(*sub));
+ dev->device.name = sub->name;
+ } else {
+ sub = rte_eal_devargs_clone(da);
+ dev->device.name = da->name;
+ }
+ if (sub == NULL) {
+ DEBUG("unable to clone devargs");
+ rte_errno = ENOMEM;
+ return -1;
+ }
+ dev->da = sub;
+ if (drv->xfrm(da, sub)) {
+ DEBUG("unable to parse device name");
+ rte_errno = ENODEV;
+ return -1;
+ }
+ sub->bus = rte_bus_from_dev(sub->name);
+ return !sub->bus;
+}
+
+struct rte_net_device *
+net_scan_one(const char *name)
+{
+ struct rte_net_device *dev;
+
+ dev = calloc(1, sizeof(*dev));
+ if (dev == NULL) {
+ ERROR("failed to allocate memory");
+ return NULL;
+ }
+ snprintf(dev->name, sizeof(dev->name), "%s", name);
+ dev->device.devargs = net_devargs_lookup(dev->name);
+ if (!net_parse(dev->name, dev)) {
+ INSERT_NET_DEVICE(dev);
+ return dev;
+ }
+ free(dev);
+ return NULL;
+}
+
+static int
+net_probe_one(struct rte_net_device *dev)
+{
+ struct rte_devargs *da;
+ struct rte_device *rdev;
+ struct rte_bus *bus;
+ int ret;
+
+ da = dev->da;
+ bus = da->bus;
+ if (bus->plug == NULL) {
+ ERROR("bus %s does not support plugin", bus->name);
+ return -1;
+ }
+ rdev = bus->plug(da);
+ ret = rdev ? 0 : -rte_errno;
+ if (rdev)
+ dev->sh_dev = rdev;
+ return ret;
+}
+
+static int
+net_probe(void)
+{
+ struct rte_net_device *dev;
+ int ret;
+
+ FOREACH_NET_DEVICE(dev) {
+ ret = net_probe_one(dev);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+static struct rte_device *
+net_find_device(int (*match)(const struct rte_device *dev, const void *data),
+ const void *data)
+{
+ struct rte_net_device *dev;
+
+ FOREACH_NET_DEVICE(dev)
+ if (match(&dev->device, data))
+ return &dev->device;
+ return NULL;
+}
+
+void
+rte_net_register(struct rte_net_driver *driver)
+{
+ if (driver->xfrm == NULL)
+ driver->xfrm = rte_bus_net_pci_xfrm;
+ INSERT_NET_DRIVER(driver);
+}
+
+void
+rte_net_unregister(struct rte_net_driver *driver)
+{
+ REMOVE_NET_DRIVER(driver);
+}
+
+const char *
+net_get_sysfs_path(void)
+{
+ const char *path = NULL;
+
+ path = getenv("SYSFS_NET_DEVICES");
+ if (path == NULL)
+ return SYSFS_NET_DEVICES;
+ return path;
+}
+
+int
+rte_bus_net_virtual_xfrm(const struct rte_devargs *src,
+ struct rte_devargs *dst)
+{
+ size_t argslen;
+
+ /* dev name. */
+ snprintf(dst->name, sizeof(dst->name),
+ "net_tap_%s", src->name);
+ /* dev args. */
+ if (dst->args)
+ free(dst->args);
+ argslen = snprintf(NULL, 0, "iface=tap_%s,remote=%s,%s",
+ src->name, src->name, src->args) + 1;
+ dst->args = calloc(1, argslen);
+ if (dst->args == NULL)
+ return -1;
+ snprintf(dst->args, argslen, "iface=tap_%s,remote=%s,%s",
+ src->name, src->name, src->args);
+ return 0;
+}
+
+int
+rte_bus_net_pci_xfrm(const struct rte_devargs *src,
+ struct rte_devargs *dst)
+{
+ char buf[32] = "";
+ int ret;
+
+ ret = rte_bus_net_pci_loc(src->name, buf, sizeof(buf));
+ if (ret)
+ return ret;
+ ret = snprintf(dst->name, sizeof(dst->name), "%s", buf);
+ dst->args = strdup(src->args);
+ return ret < 0 || ret > (int)sizeof(dst->name) || dst->args == NULL;
+}
+
+struct rte_bus rte_bus_net = {
+ .scan = net_scan,
+ .probe = net_probe,
+ .find_device = net_find_device,
+ .parse = net_parse,
+ .conf = {
+ .scan_mode = RTE_BUS_SCAN_UNDEFINED,
+ },
+};
+RTE_REGISTER_BUS(RTE_BUS_NET_NAME, rte_bus_net);
@@ -104,6 +104,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni
endif
_LDLIBS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += -lrte_bus_pci
+_LDLIBS-$(CONFIG_RTE_LIBRTE_NET_BUS) += -lrte_bus_net
ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
# plugins (link only if static libraries)