[dpdk-dev] [RFC PATCH 4/6] bifurc: add driver to scan bifurcated netdev

Cunming Liang cunming.liang at intel.com
Tue Nov 25 15:11:20 CET 2014


Signed-off-by: Cunming Liang <cunming.liang at intel.com>
---
 config/common_linuxapp         |   5 +
 lib/Makefile                   |   1 +
 lib/librte_bifurc/Makefile     |  58 +++++++++
 lib/librte_bifurc/rte_bifurc.c | 284 +++++++++++++++++++++++++++++++++++++++++
 lib/librte_bifurc/rte_bifurc.h |  90 +++++++++++++
 mk/rte.app.mk                  |   6 +
 6 files changed, 444 insertions(+)
 create mode 100644 lib/librte_bifurc/Makefile
 create mode 100644 lib/librte_bifurc/rte_bifurc.c
 create mode 100644 lib/librte_bifurc/rte_bifurc.h

diff --git a/config/common_linuxapp b/config/common_linuxapp
index 86a0d15..72fe0b1 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -163,6 +163,11 @@ CONFIG_RTE_LIBRTE_IEEE1588=n
 CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16
 
 #
+# Compile bifurcate driver backed by AF_PACKET sockets (Linux only)
+#
+CONFIG_RTE_LIBRTE_BIFURC=y
+
+#
 # Support NIC bypass logic
 #
 CONFIG_RTE_NIC_BYPASS=n
diff --git a/lib/Makefile b/lib/Makefile
index 204ef11..c59ae5b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -69,6 +69,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
 DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += librte_ivshmem
+DIRS-$(CONFIG_RTE_LIBRTE_BIFURC) += librte_bifurc
 endif
 
 include $(RTE_SDK)/mk/rte.sharelib.mk
diff --git a/lib/librte_bifurc/Makefile b/lib/librte_bifurc/Makefile
new file mode 100644
index 0000000..c5c1894
--- /dev/null
+++ b/lib/librte_bifurc/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_bifurc.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_BIFURC) += rte_bifurc.c
+
+#
+# Export include files
+#
+SYMLINK-$(CONFIG_RTE_LIBRTE_BIFURC)-include += rte_bifurc.h
+
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BIFURC) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BIFURC) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BIFURC) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bifurc/rte_bifurc.c b/lib/librte_bifurc/rte_bifurc.c
new file mode 100644
index 0000000..8cb29e3
--- /dev/null
+++ b/lib/librte_bifurc/rte_bifurc.c
@@ -0,0 +1,284 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+
+#include <rte_eal.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_mempool.h>
+#include <rte_dev.h>
+#include <rte_pci.h>
+#include <rte_ethdev.h>
+#include <rte_kvargs.h>
+#include <rte_pci_bifurc.h>
+#include "rte_bifurc.h"
+
+void
+rte_bifurc_ethdev_get_info(struct rte_eth_dev *dev,
+			   struct rte_eth_dev_info *dev_info)
+{
+	struct bifurc_device *bif_dev = (struct bifurc_device *)dev->pci_dev;
+
+	dev_info->if_index = bif_dev->if_index;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)bif_dev->mtu;
+	dev_info->max_rx_queues = (uint32_t)bif_dev->nb_queues;
+	dev_info->max_tx_queues = (uint32_t)bif_dev->nb_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static const char *valid_arguments[] = {
+	RTE_BIFURC_IFACE_ARG,
+	RTE_BIFURC_NUM_QPAIRS_ARG,
+	NULL,
+};
+
+static int
+bif_get_ifname(const char *key __rte_unused,
+	       const char *iface,
+	       void *extra_args)
+{
+	char *ifname = (char *)extra_args;
+	uint16_t ifnamelen;
+
+	ifnamelen = strlen(iface);
+	if (ifnamelen >= IFNAMSIZ) {
+		RTE_LOG(ERR, EAL,
+			"I/F name too long (%s)\n", iface);
+		return -1;
+	}
+
+	/* request for ifindex */
+	memcpy(ifname, iface, ifnamelen);
+	ifname[ifnamelen] = '\0';
+
+	return 0;
+}
+
+static int
+bif_get_qp(const char *key __rte_unused,
+	   const char *value,
+	   void *extra_args)
+{
+	uint32_t qpairs = RTE_BIFURC_PMD_MAX_QPAIRS;
+	uint32_t *nb_qp = (uint32_t *)extra_args;
+
+	qpairs = atoi(value);
+	if (qpairs < 1 ||
+	    qpairs > RTE_BIFURC_PMD_MAX_QPAIRS) {
+		RTE_LOG(ERR, EAL, "invalid qpairs value\n");
+		return -1;
+	}
+
+	*nb_qp = qpairs;
+
+	return 0;
+}
+
+static struct bifurc_device *
+rte_bifurc_alloc_dev(char *iface, struct rte_devargs *devargs)
+{
+	struct bifurc_device *dev = NULL;
+	uint16_t ifnamelen;
+	int sockfd = -1;
+
+	if (iface == NULL || devargs == NULL)
+		goto error;
+
+	if (rte_eal_bifurc_open(&sockfd))
+		goto error;
+
+	ifnamelen = strlen(iface);
+	if (ifnamelen >= IFNAMSIZ) {
+		RTE_LOG(ERR, EAL,
+			"I/F name too long (%s)\n", iface);
+		goto error;
+	}
+
+	/* alloc dev and bind to af_packet socket */
+	dev = calloc(sizeof(*dev), 1);
+	if (dev == NULL)
+		goto error;
+
+	memcpy(dev->iface_name, iface, ifnamelen);
+	dev->iface_name[ifnamelen] = '\0';
+
+	if (rte_eal_bifurc_get_ifinfo(sockfd, dev->iface_name, &dev->if_index,
+				      dev->hwaddr, &dev->mtu) != 0)
+		goto error;
+
+	if (rte_eal_bifurc_bind(sockfd, dev->if_index) != 0)
+		goto error;
+
+	/* update dev after bind success */
+	dev->fd = sockfd;
+
+	if (rte_eal_bifurc_set_pci(sockfd, &dev->pci_dev) != 0)
+		goto error;
+
+	/* use iface name as pci_dev name */
+	snprintf(dev->pci_dev.name, RTE_PCI_DEV_NAME_SIZE, "%s",
+		 dev->iface_name);
+
+	dev->pci_dev.devargs = devargs;
+
+	TAILQ_INSERT_TAIL(&pci_device_list, &dev->pci_dev, next);
+
+	return dev;
+
+error:
+	if (sockfd >= 0)
+		close(sockfd);
+	if (dev)
+		free(dev);
+
+	return NULL;
+}
+
+static void
+rte_bifurc_free_dev(struct bifurc_device *dev)
+{
+	struct rte_pci_device *pci_dev = NULL;
+
+	if (!dev)
+		return;
+
+	pci_dev = &dev->pci_dev;
+
+	/* unmap the mapped device memory */
+	rte_eal_bifurc_unmap(dev->fd, pci_dev->mem_resource[0].addr);
+
+	/* return queues to kernel driver */
+	rte_eal_bifurc_retire(dev->fd, dev->nb_queues, dev->qp_lower);
+
+	/* free the rest */
+	if (pci_dev->devargs != NULL)
+		free(pci_dev->devargs);
+
+	close(dev->fd);
+	free(dev);
+}
+
+void
+rte_bifurc_ethdev_free(struct rte_eth_dev *dev)
+{
+	rte_bifurc_free_dev((struct bifurc_device *)dev->pci_dev);
+}
+
+static int
+rte_bifurc_dev_init(const char *name, const char *params)
+{
+	struct rte_devargs *devargs = NULL;
+	struct rte_kvargs *kvlist;
+	struct bifurc_device *dev = NULL;
+	unsigned nb_qp;
+	int ret = 0;
+	char iface[IFNAMSIZ];
+
+	RTE_LOG(INFO, PMD, "Initializing %s vdev\n", name);
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	/*
+	 * If iface argument is passed we open the NICs and use them for
+	 * reading / writing
+	 */
+	/* prepare dev info from kvlist  */
+	if (rte_kvargs_count(kvlist, RTE_BIFURC_NUM_QPAIRS_ARG))
+		ret |= rte_kvargs_process(kvlist,
+					  RTE_BIFURC_NUM_QPAIRS_ARG,
+					  &bif_get_qp, &nb_qp);
+
+	if (rte_kvargs_count(kvlist, RTE_BIFURC_IFACE_ARG))
+		ret |= rte_kvargs_process(kvlist, RTE_BIFURC_IFACE_ARG,
+					  &bif_get_ifname, &iface);
+	if (ret)
+		goto exit;
+
+	devargs = rte_eal_bifurc_get_devargs(name, params);
+	if (devargs == NULL) {
+		ret = -1;
+		goto exit;
+	}
+
+	dev = rte_bifurc_alloc_dev(iface, devargs);
+	if (dev == NULL) {
+		printf("no dev attach\n");
+		ret = -1;
+		goto exit;
+	}
+
+	dev->nb_queues = nb_qp;
+	ret = rte_eal_bifurc_split(dev->fd, &dev->nb_queues, &dev->qp_lower);
+	if (ret != 0)
+		goto exit;
+
+	if (rte_eal_bifurc_map(dev->fd,
+			       &(dev->pci_dev.mem_resource[0].addr),
+			       (uint32_t *)
+			       &(dev->pci_dev.mem_resource[0].len)))
+		goto exit;
+
+	return 0;
+exit:
+	if (devargs)
+		rte_eal_bifurc_put_devargs(devargs);
+
+	if (dev)
+		rte_bifurc_free_dev(dev);
+
+	rte_kvargs_free(kvlist);
+	return ret;
+}
+
+static struct rte_driver bifurc_bus_drv = {
+	.name = RTE_BIFURC_DRV_NAME,
+	.type = PMD_VDEV,
+	.init = rte_bifurc_dev_init,
+};
+
+PMD_REGISTER_DRIVER(bifurc_bus_drv);
diff --git a/lib/librte_bifurc/rte_bifurc.h b/lib/librte_bifurc/rte_bifurc.h
new file mode 100644
index 0000000..c0951a5
--- /dev/null
+++ b/lib/librte_bifurc/rte_bifurc.h
@@ -0,0 +1,90 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BIFURC_H_
+#define _RTE_BIFURC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_pci_bifurc.h>
+#include <rte_ethdev.h>
+
+#define RTE_BIFURC_DRV_NAME             "rte_bifurc"
+#define RTE_BIFURC_IFACE_ARG		"iface"
+#define RTE_BIFURC_NUM_QPAIRS_ARG	"qpairs"
+#define RTE_BIFURC_PMD_MAX_QPAIRS       2
+
+#define RTE_BIFURC_IFNAMESIZ            16
+#define RTE_BIFURC_HWADDR_LEN           6
+
+struct bifurc_device {
+	struct rte_pci_device pci_dev;
+	char iface_name[RTE_BIFURC_IFNAMESIZ];
+	int fd;
+	int if_index;
+	uint8_t hwaddr[RTE_BIFURC_HWADDR_LEN];
+	int mtu;
+	unsigned qp_lower;
+	unsigned nb_queues;
+};
+
+void
+rte_bifurc_ethdev_get_info(struct rte_eth_dev *dev,
+			   struct rte_eth_dev_info *dev_info);
+
+void
+rte_bifurc_ethdev_free(struct rte_eth_dev *dev);
+
+static inline uint32_t
+rte_bifurc_qp_base(struct rte_eth_dev *dev)
+{
+	struct bifurc_device *bif_dev =
+		(struct bifurc_device *)dev->pci_dev;
+	return bif_dev->qp_lower;
+}
+
+static inline void
+rte_bifurc_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
+{
+	struct bifurc_device *bif_dev =
+		(struct bifurc_device *)dev->pci_dev;
+	ether_addr_copy((struct ether_addr *)bif_dev->hwaddr, mac_addr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BIFURC_H_ */
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 59468b0..ea074ab 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -219,6 +219,12 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_AF_PACKET),y)
 LDLIBS += -lrte_pmd_af_packet
 endif
 
+ifeq ($(CONFIG_RTE_LIBRTE_BIFURC),y)
+ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
+LDLIBS += -lrte_bifurc
+endif
+endif
+
 endif # plugins
 
 LDLIBS += $(EXECENV_LDLIBS)
-- 
1.8.1.4



More information about the dev mailing list