diff mbox

[API-NEXT,RFC,17/31] linux-generic: nic pktio

Message ID 1452285014-60320-18-git-send-email-christophe.milard@linaro.org
State New
Headers show

Commit Message

Christophe Milard Jan. 8, 2016, 8:30 p.m. UTC
A new pktio is created for nic cards. At this stage, only pci-vfio is
supported. The interface name format must have the form:
pmd:<root>:<bus>:<device>:<function>, for instance "pmd:0000:23:00.0"
A linux generic pci_vfio driver must be running on the interface,
of course.

Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
---
 platform/linux-generic/Makefile.am                 |  2 +
 platform/linux-generic/include/odp_nic_internal.h  | 59 ++++++++++++++++++
 .../linux-generic/include/odp_packet_io_internal.h |  1 +
 platform/linux-generic/odp_nic.c                   | 58 ++++++++++++++++++
 platform/linux-generic/pktio/io_ops.c              |  3 +
 platform/linux-generic/pktio/nic.c                 | 71 ++++++++++++++++++++++
 6 files changed, 194 insertions(+)
 create mode 100644 platform/linux-generic/include/odp_nic_internal.h
 create mode 100644 platform/linux-generic/pktio/nic.c
diff mbox

Patch

diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index c47bf52..1e323d4 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -107,6 +107,7 @@  noinst_HEADERS = \
 		  ${srcdir}/include/odp_forward_typedefs_internal.h \
 		  ${srcdir}/include/odp_internal.h \
 		  ${srcdir}/include/odp_name_table_internal.h \
+		  ${srcdir}/include/odp_nic_internal.h \
 		  ${srcdir}/include/odp_packet_internal.h \
 		  ${srcdir}/include/odp_packet_io_internal.h \
 		  ${srcdir}/include/odp_packet_io_queue.h \
@@ -155,6 +156,7 @@  __LIB__libodp_la_SOURCES = \
 			   pktio/pktio_common.c \
 			   pktio/loop.c \
 			   pktio/netmap.c \
+			   pktio/nic.c \
 			   pktio/socket.c \
 			   pktio/socket_mmap.c \
 			   pktio/tap.c \
diff --git a/platform/linux-generic/include/odp_nic_internal.h b/platform/linux-generic/include/odp_nic_internal.h
new file mode 100644
index 0000000..4f0f137
--- /dev/null
+++ b/platform/linux-generic/include/odp_nic_internal.h
@@ -0,0 +1,59 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP nic driver interface - implementation internal
+ */
+
+#ifndef ODP_NIC_INTERNAL_H_
+#define ODP_NIC_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/std_types.h>
+#include <odp/pci.h>
+#include <odp/nic.h>
+#include <odp/packet_io.h>
+
+/** @addtogroup odp_nic
+ *  @{
+ */
+
+/* the entries for each nic pktio */
+typedef struct _odp_nic_pktio_tbl_t {
+	odp_pci_dev_t	    pci_dev;
+	odp_nic_dev_t	    *nic_dev;
+	odp_nic_sgmt_pool_t tx_sgmt_pool;
+	odp_nic_sgmt_pool_t rx_sgmt_pool;
+} _odp_nic_pktio_tbl_t;
+
+extern _odp_nic_pktio_tbl_t _odp_nic_pktio_tbl[ODP_CONFIG_PKTIO_ENTRIES];
+
+/*
+* probe all drivers for the given pci address. stop at the first that
+* can handle the NIC
+*/
+int driver_probe(odp_pktio_t pktio, const char *pci_address, odp_pool_t pool);
+
+/*
+ * unprobe a driver (i.e. release all resources allocated by a successful
+ * probe)
+ */
+void driver_unprobe(pktio_entry_t *pktio_entry);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index 4fd3c87..96e08e0 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -210,6 +210,7 @@  int single_send_queue(pktio_entry_t *entry, int index, odp_packet_t packets[],
 		      int num);
 
 extern const pktio_if_ops_t netmap_pktio_ops;
+extern const pktio_if_ops_t nic_pktio_ops;
 extern const pktio_if_ops_t sock_mmsg_pktio_ops;
 extern const pktio_if_ops_t sock_mmap_pktio_ops;
 extern const pktio_if_ops_t loopback_pktio_ops;
diff --git a/platform/linux-generic/odp_nic.c b/platform/linux-generic/odp_nic.c
index 5faf642..e28d98c 100644
--- a/platform/linux-generic/odp_nic.c
+++ b/platform/linux-generic/odp_nic.c
@@ -7,6 +7,8 @@ 
 #include <odp/nic.h>
 #include <odp/pool.h>
 #include <odp_packet_io_internal.h>
+#include <odp_nic_internal.h>
+#include <odp_pci_internal.h>
 #include <odp/spinlock.h>
 
 #ifdef WITH_DRIVERS
@@ -15,6 +17,8 @@ 
 
 odp_spinlock_t		drv_registration_mutex;
 
+_odp_nic_pktio_tbl_t _odp_nic_pktio_tbl[ODP_CONFIG_PKTIO_ENTRIES];
+
 /*
  * registered drivers:
  * Because at registration time, drivers give function pointers (whose
@@ -282,3 +286,57 @@  void odp_nic_dev_free(odp_nic_dev_t *nic_dev)
 	odp_shm_free(nic_dev->data_shm);
 	free(nic_dev);
 }
+
+int driver_probe(odp_pktio_t pktio, const char *pci_address, odp_pool_t pool)
+{
+	int i;
+
+	odp_nic_sgmt_pool_t tx_sgmt_pool;
+	odp_nic_sgmt_pool_t rx_sgmt_pool;
+	odp_nic_dev_t *nic_dev;
+	odp_pci_dev_t pci_dev;
+	_odp_nic_pktio_tbl_t *nic_entry;
+
+	/* init the PCI device: */
+	pci_dev = _odp_pci_init(pci_address);
+	if (pci_dev == ODP_PCI_DEV_INVALID)
+		return -1;
+
+	rx_sgmt_pool = odp_nic_sgmt_pool_create(pool);
+	tx_sgmt_pool = odp_nic_sgmt_pool_create(ODP_POOL_ALL_PKTS);
+	for (i = 0; i < registered_drv.nb_drivers; i++) {
+		nic_dev = registered_drv.drivers[i].probe(pci_dev, pktio,
+							rx_sgmt_pool,
+							tx_sgmt_pool);
+		if (nic_dev) {
+			nic_entry = &_odp_nic_pktio_tbl[_odp_typeval(pktio)];
+			nic_entry->nic_dev = nic_dev;
+			nic_entry->pci_dev = pci_dev;
+			nic_entry->tx_sgmt_pool = tx_sgmt_pool;
+			nic_entry->rx_sgmt_pool = rx_sgmt_pool;
+			return 0;
+		}
+	}
+	odp_nic_sgmt_pool_destroy(tx_sgmt_pool);
+	odp_nic_sgmt_pool_destroy(rx_sgmt_pool);
+	_odp_pci_release(pci_dev);
+	return -1;
+}
+
+void driver_unprobe(pktio_entry_t *pktio_entry)
+{
+	_odp_nic_pktio_tbl_t *nic_entry;
+	odp_nic_dev_t *nic_dev;
+	odp_pci_dev_t pci_dev;
+	odp_pktio_t pktio;
+
+	pktio = pktio_entry->s.handle;
+	nic_entry = &_odp_nic_pktio_tbl[_odp_typeval(pktio)];
+	nic_dev = nic_entry->nic_dev;
+	pci_dev = nic_entry->pci_dev;
+	nic_dev->dev_ops->unprobe(pci_dev, nic_dev);
+
+	odp_nic_sgmt_pool_destroy(nic_entry->tx_sgmt_pool);
+	odp_nic_sgmt_pool_destroy(nic_entry->rx_sgmt_pool);
+	_odp_pci_release(pci_dev);
+}
diff --git a/platform/linux-generic/pktio/io_ops.c b/platform/linux-generic/pktio/io_ops.c
index 1933abc..ffb0251 100644
--- a/platform/linux-generic/pktio/io_ops.c
+++ b/platform/linux-generic/pktio/io_ops.c
@@ -12,6 +12,9 @@ 
  * Array must be NULL terminated */
 const pktio_if_ops_t * const pktio_if_ops[]  = {
 	&loopback_pktio_ops,
+#ifdef WITH_DRIVERS
+	&nic_pktio_ops,
+#endif
 #ifdef ODP_NETMAP
 	&netmap_pktio_ops,
 #endif
diff --git a/platform/linux-generic/pktio/nic.c b/platform/linux-generic/pktio/nic.c
new file mode 100644
index 0000000..1df93e1
--- /dev/null
+++ b/platform/linux-generic/pktio/nic.c
@@ -0,0 +1,71 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015, Nokia Solutions and Networks
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_packet_io_internal.h>
+#include <odp_nic_internal.h>
+#include <stdio.h>
+#include <odp.h>
+
+/*
+ * parse the device name for something like "pmd:<pci_address>"
+ * returns a pointer to the pci address on success or NULL if no match
+ */
+
+static const char *parse_devname(const char *devname)
+{
+	if (strncmp(devname, "pmd:", 4) != 0)
+		return NULL;
+
+	/*FIXME check for complete pci address format */
+	return &devname[4];
+}
+
+static int nic_open(odp_pktio_t pktio,
+		    pktio_entry_t *pktio_entry ODP_UNUSED,
+		    const char *devname, odp_pool_t pool)
+{
+	/* check if devname has the form "pmd:<pci_address>" */
+	const char *pci_address = parse_devname(devname);
+
+	if (!pci_address)
+		return -1;
+
+	if (driver_probe(pktio, pci_address, pool))
+		return -1;
+
+	return 0;
+}
+
+static int nic_close(pktio_entry_t *entry)
+{
+	driver_unprobe(entry);
+	return 0;
+}
+
+const pktio_if_ops_t nic_pktio_ops = {
+	.name = "Nic",
+	.init = NULL,
+	.term = NULL,
+	.open = nic_open,
+	.close = nic_close,
+	.start = NULL,
+	.stop = NULL,
+	.recv = NULL,
+	.send = NULL,
+	.mtu_get = NULL,
+	.promisc_mode_set = NULL,
+	.promisc_mode_get = NULL,
+	.mac_get = NULL,
+	.capability = NULL,
+	.input_queues_config = NULL,
+	.output_queues_config = NULL,
+	.in_queues = NULL,
+	.pktin_queues = NULL,
+	.pktout_queues = NULL,
+	.recv_queue = NULL,
+	.send_queue = NULL
+};