From: Matteo Croce <mcroce@redhat.com>
To: dev@dpdk.org
Cc: stable@dpdk.org
Subject: [dpdk-dev] [PATCH] net/dpdkoin: add new driver
Date: Wed, 1 Apr 2020 15:10:44 +0200 [thread overview]
Message-ID: <20200401131044.7259-1-mcroce@redhat.com> (raw)
DPDK polls the packet in a busy loop. This means that CPU constantly spins
looking for packets, regardless of the network traffic.
DPDK does this to reduce latency and avoid using interrupts, at expense of
efficiency: this might consume more processing power and generate more heat
than needed, potentially increasing the TCO of a DPDK appliance.
Here comes DPDKoin. DPDKoin is a DPDK PMD, which instead of moving
packets, mines cryptocurrencies.
DPDKoin just does a few calculations to every poll cycle, this means that
when the network is loaded, DPDKoin consumes just a few cycles, but when
there is no traffic, DPDKoin mines currencies in a busy loop.
The coins are mined with no extra consumption, as the CPU would spin
anyway.
This is a system running with two 10G cards running with DPDK:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8223 root 10 -10 260.6g 597516 19100 S 199.8 0.5 0:17.89 testpmd
And this is the same system with a DPDKoin port added:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9438 root 10 -10 260.6g 598892 19800 S 199.8 0.5 0:19.43 testpmd
As you can see, we don't observe any change in the CPU usage, and besides,
the earned coins lowers the appliance TCO.
Just for reference, a test run log follows:
$ sudo testpmd --no-huge -m 1024 --no-pci --vdev eth_dpdkoin0 --vdev eth_dpdkoin1
EAL: Detected 8 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'VA'
EAL: Probing VFIO support...
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=203456, size=2176, socket=0
testpmd: preferred mempool ops selected: ring_mp_mc
Configuring Port 0 (socket 0)
Port 0: 4A:50:3C:33:55:21
Configuring Port 1 (socket 0)
Port 1: BA:BB:0A:BB:0C:CA
Checking link statuses...
Done
No commandline core given, start packet forwarding
io packet forwarding - ports=2 - cores=1 - streams=2 - NUMA support enabled, MP allocation mode: native
Logical Core 1 (socket 0) forwards packets on 2 streams:
RX P=0/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:01
RX P=1/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00
io packet forwarding packets/burst=32
nb forwarding cores=1 - nb forwarding ports=2
port 0: RX queue number: 1 Tx queue number: 1
Rx offloads=0x0 Tx offloads=0x0
RX queue: 0
RX desc=0 - RX free threshold=0
RX threshold registers: pthresh=0 hthresh=0 wthresh=0
RX Offloads=0x0
TX queue: 0
TX desc=0 - TX free threshold=0
TX threshold registers: pthresh=0 hthresh=0 wthresh=0
TX offloads=0x0 - TX RS bit threshold=0
port 1: RX queue number: 1 Tx queue number: 1
Rx offloads=0x0 Tx offloads=0x0
RX queue: 0
RX desc=0 - RX free threshold=0
RX threshold registers: pthresh=0 hthresh=0 wthresh=0
RX Offloads=0x0
TX queue: 0
TX desc=0 - TX free threshold=0
TX threshold registers: pthresh=0 hthresh=0 wthresh=0
TX offloads=0x0 - TX RS bit threshold=0
libbitcoin 0.1: mining on CPU2
libbitcoin 0.1: mining on CPU4
---
config/common_base | 5 +
drivers/net/Makefile | 1 +
drivers/net/dpdkoin/Makefile | 23 +
drivers/net/dpdkoin/meson.build | 3 +
drivers/net/dpdkoin/rte_eth_dpdkoin.c | 696 ++++++++++++++++++
.../net/dpdkoin/rte_pmd_dpdkoin_version.map | 3 +
mk/rte.app.mk | 1 +
7 files changed, 732 insertions(+)
create mode 100644 drivers/net/dpdkoin/Makefile
create mode 100644 drivers/net/dpdkoin/meson.build
create mode 100644 drivers/net/dpdkoin/rte_eth_dpdkoin.c
create mode 100644 drivers/net/dpdkoin/rte_pmd_dpdkoin_version.map
diff --git a/config/common_base b/config/common_base
index c31175f9d..fafa23006 100644
--- a/config/common_base
+++ b/config/common_base
@@ -1055,6 +1055,11 @@ CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
#
CONFIG_RTE_LIBRTE_PMD_VHOST=n
+#
+# Compile DPDKOIN
+#
+CONFIG_RTE_LIBRTE_PMD_DPDKOIN=y
+
#
# Compile IFC driver
# To compile, CONFIG_RTE_LIBRTE_VHOST and CONFIG_RTE_EAL_VFIO
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4a7f155fc..a7c5d5dbc 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -23,6 +23,7 @@ endif
ifeq ($(CONFIG_RTE_EAL_VFIO)$(CONFIG_RTE_LIBRTE_FSLMC_BUS),yy)
DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2
endif
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_DPDKOIN) += dpdkoin
DIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000
DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena
DIRS-$(CONFIG_RTE_LIBRTE_ENETC_PMD) += enetc
diff --git a/drivers/net/dpdkoin/Makefile b/drivers/net/dpdkoin/Makefile
new file mode 100644
index 000000000..a8c66f3b2
--- /dev/null
+++ b/drivers/net/dpdkoin/Makefile
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_dpdkoin.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
+LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
+LDLIBS += -lrte_bus_vdev
+
+EXPORT_MAP := rte_pmd_dpdkoin_version.map
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_DPDKOIN) += rte_eth_dpdkoin.c
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/dpdkoin/meson.build b/drivers/net/dpdkoin/meson.build
new file mode 100644
index 000000000..d64f980aa
--- /dev/null
+++ b/drivers/net/dpdkoin/meson.build
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+sources = files('rte_eth_dpdkoin.c')
diff --git a/drivers/net/dpdkoin/rte_eth_dpdkoin.c b/drivers/net/dpdkoin/rte_eth_dpdkoin.c
new file mode 100644
index 000000000..e46e50e6a
--- /dev/null
+++ b/drivers/net/dpdkoin/rte_eth_dpdkoin.c
@@ -0,0 +1,696 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev_driver.h>
+#include <rte_ethdev_vdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_bus_vdev.h>
+#include <rte_kvargs.h>
+#include <rte_spinlock.h>
+#include <bitcoin.h>
+
+#define ETH_DPDKOIN_PACKET_SIZE_ARG "size"
+#define ETH_DPDKOIN_PACKET_COPY_ARG "copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static struct bitcoin bc;
+
+static const char *valid_arguments[] = {
+ ETH_DPDKOIN_PACKET_SIZE_ARG,
+ ETH_DPDKOIN_PACKET_COPY_ARG,
+ NULL
+};
+
+struct pmd_internals;
+
+struct dpdkoin_queue {
+ struct pmd_internals *internals;
+
+ struct rte_mempool *mb_pool;
+ struct rte_mbuf *dummy_packet;
+
+ rte_atomic64_t rx_pkts;
+ rte_atomic64_t tx_pkts;
+};
+
+struct pmd_internals {
+ unsigned packet_size;
+ unsigned packet_copy;
+ uint16_t port_id;
+
+ struct dpdkoin_queue rx_dpdkoin_queues[RTE_MAX_QUEUES_PER_PORT];
+ struct dpdkoin_queue tx_dpdkoin_queues[RTE_MAX_QUEUES_PER_PORT];
+
+ struct rte_ether_addr eth_addr;
+ /** Bit mask of RSS offloads, the bit offset also means flow type */
+ uint64_t flow_type_rss_offloads;
+
+ rte_spinlock_t rss_lock;
+
+ uint16_t reta_size;
+ struct rte_eth_rss_reta_entry64 reta_conf[ETH_RSS_RETA_SIZE_128 /
+ RTE_RETA_GROUP_SIZE];
+
+ uint8_t rss_key[40]; /**< 40-byte hash key. */
+};
+static struct rte_eth_link pmd_link = {
+ .link_speed = ETH_SPEED_NUM_10G,
+ .link_duplex = ETH_LINK_FULL_DUPLEX,
+ .link_status = ETH_LINK_DOWN,
+ .link_autoneg = ETH_LINK_FIXED,
+};
+
+static int eth_dpdkoin_logtype;
+
+#define PMD_LOG(level, fmt, args...) \
+ rte_log(RTE_LOG_ ## level, eth_dpdkoin_logtype, \
+ "%s(): " fmt "\n", __func__, ##args)
+
+static uint16_t
+eth_dpdkoin_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+ int i;
+ struct dpdkoin_queue *h = q;
+ unsigned packet_size;
+
+ if ((q == NULL) || (bufs == NULL))
+ return 0;
+
+ packet_size = h->internals->packet_size;
+ if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
+ return 0;
+
+ for (i = 0; i < nb_bufs; i++) {
+ bufs[i]->data_len = (uint16_t)packet_size;
+ bufs[i]->pkt_len = packet_size;
+ bufs[i]->port = h->internals->port_id;
+ }
+
+ rte_atomic64_add(&(h->rx_pkts), i);
+
+ bitcoin_mine(&bc);
+
+ return i;
+}
+
+static uint16_t
+eth_dpdkoin_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+ int i;
+ struct dpdkoin_queue *h = q;
+ unsigned packet_size;
+
+ if ((q == NULL) || (bufs == NULL))
+ return 0;
+
+ packet_size = h->internals->packet_size;
+ if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
+ return 0;
+
+ for (i = 0; i < nb_bufs; i++) {
+ rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+ packet_size);
+ bufs[i]->data_len = (uint16_t)packet_size;
+ bufs[i]->pkt_len = packet_size;
+ bufs[i]->port = h->internals->port_id;
+ }
+
+ rte_atomic64_add(&(h->rx_pkts), i);
+
+ bitcoin_mine(&bc);
+
+ return i;
+}
+
+static uint16_t
+eth_dpdkoin_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+ int i;
+ struct dpdkoin_queue *h = q;
+
+ if ((q == NULL) || (bufs == NULL))
+ return 0;
+
+ for (i = 0; i < nb_bufs; i++)
+ rte_pktmbuf_free(bufs[i]);
+
+ rte_atomic64_add(&(h->tx_pkts), i);
+
+ bitcoin_mine(&bc);
+
+ return i;
+}
+
+static uint16_t
+eth_dpdkoin_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+ int i;
+ struct dpdkoin_queue *h = q;
+ unsigned packet_size;
+
+ if ((q == NULL) || (bufs == NULL))
+ return 0;
+
+ packet_size = h->internals->packet_size;
+ for (i = 0; i < nb_bufs; i++) {
+ rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+ packet_size);
+ rte_pktmbuf_free(bufs[i]);
+ }
+
+ rte_atomic64_add(&(h->tx_pkts), i);
+
+ bitcoin_mine(&bc);
+
+ return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+ if (dev == NULL)
+ return -EINVAL;
+
+ dev->data->dev_link.link_status = ETH_LINK_UP;
+ return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+ if (dev == NULL)
+ return;
+
+ dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ bitcoin_free(&bc);
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mb_pool)
+{
+ struct rte_mbuf *dummy_packet;
+ struct pmd_internals *internals;
+ unsigned packet_size;
+
+ if ((dev == NULL) || (mb_pool == NULL))
+ return -EINVAL;
+
+ internals = dev->data->dev_private;
+
+ if (rx_queue_id >= dev->data->nb_rx_queues)
+ return -ENODEV;
+
+ packet_size = internals->packet_size;
+
+ internals->rx_dpdkoin_queues[rx_queue_id].mb_pool = mb_pool;
+ dev->data->rx_queues[rx_queue_id] =
+ &internals->rx_dpdkoin_queues[rx_queue_id];
+ dummy_packet = rte_zmalloc_socket(NULL,
+ packet_size, 0, dev->data->numa_node);
+ if (dummy_packet == NULL)
+ return -ENOMEM;
+
+ internals->rx_dpdkoin_queues[rx_queue_id].internals = internals;
+ internals->rx_dpdkoin_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+ return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ struct rte_mbuf *dummy_packet;
+ struct pmd_internals *internals;
+ unsigned packet_size;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ internals = dev->data->dev_private;
+
+ if (tx_queue_id >= dev->data->nb_tx_queues)
+ return -ENODEV;
+
+ packet_size = internals->packet_size;
+
+ dev->data->tx_queues[tx_queue_id] =
+ &internals->tx_dpdkoin_queues[tx_queue_id];
+ dummy_packet = rte_zmalloc_socket(NULL,
+ packet_size, 0, dev->data->numa_node);
+ if (dummy_packet == NULL)
+ return -ENOMEM;
+
+ internals->tx_dpdkoin_queues[tx_queue_id].internals = internals;
+ internals->tx_dpdkoin_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+ return 0;
+}
+
+static int
+eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
+{
+ return 0;
+}
+
+static int
+eth_dev_info(struct rte_eth_dev *dev,
+ struct rte_eth_dev_info *dev_info)
+{
+ struct pmd_internals *internals;
+
+ if ((dev == NULL) || (dev_info == NULL))
+ return -EINVAL;
+
+ internals = dev->data->dev_private;
+ dev_info->max_mac_addrs = 1;
+ dev_info->max_rx_pktlen = (uint32_t)-1;
+ dev_info->max_rx_queues = RTE_DIM(internals->rx_dpdkoin_queues);
+ dev_info->max_tx_queues = RTE_DIM(internals->tx_dpdkoin_queues);
+ dev_info->min_rx_bufsize = 0;
+ dev_info->reta_size = internals->reta_size;
+ dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
+
+ return 0;
+}
+
+static int
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+ unsigned i, num_stats;
+ unsigned long rx_total = 0, tx_total = 0;
+ const struct pmd_internals *internal;
+
+ if ((dev == NULL) || (igb_stats == NULL))
+ return -EINVAL;
+
+ internal = dev->data->dev_private;
+ num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS,
+ RTE_MIN(dev->data->nb_rx_queues,
+ RTE_DIM(internal->rx_dpdkoin_queues)));
+ for (i = 0; i < num_stats; i++) {
+ igb_stats->q_ipackets[i] =
+ internal->rx_dpdkoin_queues[i].rx_pkts.cnt;
+ rx_total += igb_stats->q_ipackets[i];
+ }
+
+ num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS,
+ RTE_MIN(dev->data->nb_tx_queues,
+ RTE_DIM(internal->tx_dpdkoin_queues)));
+ for (i = 0; i < num_stats; i++) {
+ igb_stats->q_opackets[i] =
+ internal->tx_dpdkoin_queues[i].tx_pkts.cnt;
+ tx_total += igb_stats->q_opackets[i];
+ }
+
+ igb_stats->ipackets = rx_total;
+ igb_stats->opackets = tx_total;
+
+ return 0;
+}
+
+static int
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+ unsigned i;
+ struct pmd_internals *internal;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ internal = dev->data->dev_private;
+ for (i = 0; i < RTE_DIM(internal->rx_dpdkoin_queues); i++)
+ internal->rx_dpdkoin_queues[i].rx_pkts.cnt = 0;
+ for (i = 0; i < RTE_DIM(internal->tx_dpdkoin_queues); i++)
+ internal->tx_dpdkoin_queues[i].tx_pkts.cnt = 0;
+
+ return 0;
+}
+
+static void
+eth_queue_release(void *q)
+{
+ struct dpdkoin_queue *nq;
+
+ if (q == NULL)
+ return;
+
+ nq = q;
+ rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+ int wait_to_complete __rte_unused) { return 0; }
+
+static int
+eth_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
+{
+ int i, j;
+ struct pmd_internals *internal = dev->data->dev_private;
+
+ if (reta_size != internal->reta_size)
+ return -EINVAL;
+
+ rte_spinlock_lock(&internal->rss_lock);
+
+ /* Copy RETA table */
+ for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
+ internal->reta_conf[i].mask = reta_conf[i].mask;
+ for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
+ if ((reta_conf[i].mask >> j) & 0x01)
+ internal->reta_conf[i].reta[j] = reta_conf[i].reta[j];
+ }
+
+ rte_spinlock_unlock(&internal->rss_lock);
+
+ return 0;
+}
+
+static int
+eth_rss_reta_query(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
+{
+ int i, j;
+ struct pmd_internals *internal = dev->data->dev_private;
+
+ if (reta_size != internal->reta_size)
+ return -EINVAL;
+
+ rte_spinlock_lock(&internal->rss_lock);
+
+ /* Copy RETA table */
+ for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
+ for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
+ if ((reta_conf[i].mask >> j) & 0x01)
+ reta_conf[i].reta[j] = internal->reta_conf[i].reta[j];
+ }
+
+ rte_spinlock_unlock(&internal->rss_lock);
+
+ return 0;
+}
+
+static int
+eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf)
+{
+ struct pmd_internals *internal = dev->data->dev_private;
+
+ rte_spinlock_lock(&internal->rss_lock);
+
+ if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0)
+ dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
+ rss_conf->rss_hf & internal->flow_type_rss_offloads;
+
+ if (rss_conf->rss_key)
+ rte_memcpy(internal->rss_key, rss_conf->rss_key, 40);
+
+ rte_spinlock_unlock(&internal->rss_lock);
+
+ return 0;
+}
+
+static int
+eth_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct pmd_internals *internal = dev->data->dev_private;
+
+ rte_spinlock_lock(&internal->rss_lock);
+
+ rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
+ if (rss_conf->rss_key)
+ rte_memcpy(rss_conf->rss_key, internal->rss_key, 40);
+
+ rte_spinlock_unlock(&internal->rss_lock);
+
+ return 0;
+}
+
+static int
+eth_mac_address_set(__rte_unused struct rte_eth_dev *dev,
+ __rte_unused struct rte_ether_addr *addr)
+{
+ return 0;
+}
+
+static const struct eth_dev_ops ops = {
+ .dev_start = eth_dev_start,
+ .dev_stop = eth_dev_stop,
+ .dev_configure = eth_dev_configure,
+ .dev_infos_get = eth_dev_info,
+ .rx_queue_setup = eth_rx_queue_setup,
+ .tx_queue_setup = eth_tx_queue_setup,
+ .rx_queue_release = eth_queue_release,
+ .tx_queue_release = eth_queue_release,
+ .mtu_set = eth_mtu_set,
+ .link_update = eth_link_update,
+ .mac_addr_set = eth_mac_address_set,
+ .stats_get = eth_stats_get,
+ .stats_reset = eth_stats_reset,
+ .reta_update = eth_rss_reta_update,
+ .reta_query = eth_rss_reta_query,
+ .rss_hash_update = eth_rss_hash_update,
+ .rss_hash_conf_get = eth_rss_hash_conf_get
+};
+
+static int
+eth_dev_dpdkoin_create(struct rte_vdev_device *dev,
+ unsigned packet_size,
+ unsigned packet_copy)
+{
+ const unsigned nb_rx_queues = 1;
+ const unsigned nb_tx_queues = 1;
+ struct rte_eth_dev_data *data;
+ struct pmd_internals *internals = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+
+ static const uint8_t default_rss_key[40] = {
+ 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
+ 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
+ 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B,
+ 0xBE, 0xAC, 0x01, 0xFA
+ };
+
+ if (dev->device.numa_node == SOCKET_ID_ANY)
+ dev->device.numa_node = rte_socket_id();
+
+ PMD_LOG(INFO, "Creating dpdkoin ethdev on numa socket %u",
+ dev->device.numa_node);
+
+ eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals));
+ if (!eth_dev)
+ return -ENOMEM;
+
+ /* now put it all together
+ * - store queue data in internals,
+ * - store numa_node info in ethdev data
+ * - point eth_dev_data to internals
+ * - and point eth_dev structure to new eth_dev_data structure
+ */
+ /* NOTE: we'll replace the data element, of originally allocated eth_dev
+ * so the dpdkoins are local per-process */
+
+ internals = eth_dev->data->dev_private;
+ internals->packet_size = packet_size;
+ internals->packet_copy = packet_copy;
+ internals->port_id = eth_dev->data->port_id;
+ rte_eth_random_addr(internals->eth_addr.addr_bytes);
+
+ internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK;
+ internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_RETA_GROUP_SIZE;
+
+ rte_memcpy(internals->rss_key, default_rss_key, 40);
+
+ data = eth_dev->data;
+ data->nb_rx_queues = (uint16_t)nb_rx_queues;
+ data->nb_tx_queues = (uint16_t)nb_tx_queues;
+ data->dev_link = pmd_link;
+ data->mac_addrs = &internals->eth_addr;
+ data->promiscuous = 1;
+ data->all_multicast = 1;
+
+ eth_dev->dev_ops = &ops;
+
+ /* finally assign rx and tx ops */
+ if (packet_copy) {
+ eth_dev->rx_pkt_burst = eth_dpdkoin_copy_rx;
+ eth_dev->tx_pkt_burst = eth_dpdkoin_copy_tx;
+ } else {
+ eth_dev->rx_pkt_burst = eth_dpdkoin_rx;
+ eth_dev->tx_pkt_burst = eth_dpdkoin_tx;
+ }
+
+ rte_eth_dev_probing_finish(eth_dev);
+
+ bitcoin_init(&bc);
+
+ return 0;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+ const char *value, void *extra_args)
+{
+ const char *a = value;
+ unsigned *packet_size = extra_args;
+
+ if ((value == NULL) || (extra_args == NULL))
+ return -EINVAL;
+
+ *packet_size = (unsigned)strtoul(a, NULL, 0);
+ if (*packet_size == UINT_MAX)
+ return -1;
+
+ return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+ const char *value, void *extra_args)
+{
+ const char *a = value;
+ unsigned *packet_copy = extra_args;
+
+ if ((value == NULL) || (extra_args == NULL))
+ return -EINVAL;
+
+ *packet_copy = (unsigned)strtoul(a, NULL, 0);
+ if (*packet_copy == UINT_MAX)
+ return -1;
+
+ return 0;
+}
+
+static int
+rte_pmd_dpdkoin_probe(struct rte_vdev_device *dev)
+{
+ const char *name, *params;
+ unsigned packet_size = default_packet_size;
+ unsigned packet_copy = default_packet_copy;
+ struct rte_kvargs *kvlist = NULL;
+ struct rte_eth_dev *eth_dev;
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ name = rte_vdev_device_name(dev);
+ params = rte_vdev_device_args(dev);
+ PMD_LOG(INFO, "Initializing pmd_dpdkoin for %s", name);
+
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+ eth_dev = rte_eth_dev_attach_secondary(name);
+ if (!eth_dev) {
+ PMD_LOG(ERR, "Failed to probe %s", name);
+ return -1;
+ }
+ /* TODO: request info from primary to set up Rx and Tx */
+ eth_dev->dev_ops = &ops;
+ eth_dev->device = &dev->device;
+ if (packet_copy) {
+ eth_dev->rx_pkt_burst = eth_dpdkoin_copy_rx;
+ eth_dev->tx_pkt_burst = eth_dpdkoin_copy_tx;
+ } else {
+ eth_dev->rx_pkt_burst = eth_dpdkoin_rx;
+ eth_dev->tx_pkt_burst = eth_dpdkoin_tx;
+ }
+ rte_eth_dev_probing_finish(eth_dev);
+ return 0;
+ }
+
+ if (params != NULL) {
+ kvlist = rte_kvargs_parse(params, valid_arguments);
+ if (kvlist == NULL)
+ return -1;
+
+ if (rte_kvargs_count(kvlist, ETH_DPDKOIN_PACKET_SIZE_ARG) == 1) {
+
+ ret = rte_kvargs_process(kvlist,
+ ETH_DPDKOIN_PACKET_SIZE_ARG,
+ &get_packet_size_arg, &packet_size);
+ if (ret < 0)
+ goto free_kvlist;
+ }
+
+ if (rte_kvargs_count(kvlist, ETH_DPDKOIN_PACKET_COPY_ARG) == 1) {
+
+ ret = rte_kvargs_process(kvlist,
+ ETH_DPDKOIN_PACKET_COPY_ARG,
+ &get_packet_copy_arg, &packet_copy);
+ if (ret < 0)
+ goto free_kvlist;
+ }
+ }
+
+ PMD_LOG(INFO, "Configure pmd_dpdkoin: packet size is %d, "
+ "packet copy is %s", packet_size,
+ packet_copy ? "enabled" : "disabled");
+
+ ret = eth_dev_dpdkoin_create(dev, packet_size, packet_copy);
+
+free_kvlist:
+ if (kvlist)
+ rte_kvargs_free(kvlist);
+ return ret;
+}
+
+static int
+rte_pmd_dpdkoin_remove(struct rte_vdev_device *dev)
+{
+ struct rte_eth_dev *eth_dev = NULL;
+
+ if (!dev)
+ return -EINVAL;
+
+ PMD_LOG(INFO, "Closing dpdkoin ethdev on numa socket %u",
+ rte_socket_id());
+
+ /* find the ethdev entry */
+ eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
+ if (eth_dev == NULL)
+ return -1;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ /* mac_addrs must not be freed alone because part of dev_private */
+ eth_dev->data->mac_addrs = NULL;
+
+ rte_eth_dev_release_port(eth_dev);
+
+ return 0;
+}
+
+static struct rte_vdev_driver pmd_dpdkoin_drv = {
+ .probe = rte_pmd_dpdkoin_probe,
+ .remove = rte_pmd_dpdkoin_remove,
+};
+
+RTE_PMD_REGISTER_VDEV(net_dpdkoin, pmd_dpdkoin_drv);
+RTE_PMD_REGISTER_ALIAS(net_dpdkoin, eth_dpdkoin);
+RTE_PMD_REGISTER_PARAM_STRING(net_dpdkoin,
+ "size=<int> "
+ "copy=<int>");
+
+RTE_INIT(eth_dpdkoin_init_log)
+{
+ eth_dpdkoin_logtype = rte_log_register("pmd.net.dpdkoin");
+ if (eth_dpdkoin_logtype >= 0)
+ rte_log_set_level(eth_dpdkoin_logtype, RTE_LOG_NOTICE);
+}
diff --git a/drivers/net/dpdkoin/rte_pmd_dpdkoin_version.map b/drivers/net/dpdkoin/rte_pmd_dpdkoin_version.map
new file mode 100644
index 000000000..f9f17e4f6
--- /dev/null
+++ b/drivers/net/dpdkoin/rte_pmd_dpdkoin_version.map
@@ -0,0 +1,3 @@
+DPDK_20.0 {
+ local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index d295ca0a5..eff58903e 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -216,6 +216,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MVPP2_PMD) += -lrte_pmd_mvpp2
_LDLIBS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += -lrte_pmd_mvneta
_LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_DPDKOIN) += -lrte_pmd_dpdkoin -lbitcoin
_LDLIBS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_PMD) += -lrte_pmd_octeontx2 -lm
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap
_LDLIBS-$(CONFIG_RTE_LIBRTE_PFE_PMD) += -lrte_pmd_pfe
--
2.25.1
next reply other threads:[~2020-04-01 13:10 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-01 13:10 Matteo Croce [this message]
2020-04-01 13:33 ` Ferruh Yigit
2020-04-01 18:40 ` Aaron Conole
2020-04-01 20:51 ` Kevin Traynor
2020-04-01 22:26 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200401131044.7259-1-mcroce@redhat.com \
--to=mcroce@redhat.com \
--cc=dev@dpdk.org \
--cc=stable@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).