[dpdk-dev] [PATCH] RFC: Introduce host_ifname field to struct rte_eth_dev_info

Mats Liljegren liljegren.mats2 at gmail.com
Wed Dec 4 16:39:05 CET 2013


I played around with pcap to compare it against "pure" DPDK user-space
driver. I realized that interrupt affinity suddenly becomes important,
since it uses interrupts. So I needed a way to set it.

The only place where I know which core will handle which pcap
interface, is within my DPDK application. But DPDK did not save the
host interface name anywhere, so it was nowhere to be found.

I created a patch for this, found below. Is this something that could
be upstreamed?

Best regards
  Mats Liljegren

-- >8 --

>From 1b126c7f74680afae8a6426a197d77eab0f2b75e Mon Sep 17 00:00:00 2001
From: Mats Liljegren <mats.liljegren at enea.com>
Date: Wed, 4 Dec 2013 16:31:59 +0100
Subject: [PATCH] Introduce host_ifname field to struct rte_eth_dev_info

This field is intended for pcap to describe the name of the interface
as known to Linux, e.g. eth2. When using pcap interrupt affinity
becomes important, and this field gives the application a chance
to ensure that interrupt affinity is set to to the lcore handling the
device.

An example how to use it:

static void
ensure_irq_affinity(unsigned port)
{
    char path[255];
    struct dirent *dirent;
    DIR *dir;
    const unsigned lcore = rte_lcore_id();
    struct rte_eth_dev_info dev_info;

    rte_eth_dev_info_get(port, &dev_info);

    if (dev_info.host_ifname[0] == '\0')
        /* No host interface name */
        return;

    snprintf(path, sizeof (path), "/sys/class/net/%s/device/msi_irqs",
         dev_info.host_ifname);
    dir = opendir(path);
    if (dir == NULL)
        /* Can't do anything for this interface */
        return;

    for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
        FILE *file;

        if ((dirent->d_name[0] < '0') || (dirent->d_name[0] > '9'))
            continue;
        snprintf(path, sizeof (path), "/proc/irq/%s/smp_affinity",
             dirent->d_name);
        file = fopen(path, "w");
        if (file == NULL)
            rte_exit(EXIT_FAILURE,
                 "%s: Could not open file for writing: %s\n",
                 path, strerror(errno));
        fprintf(file, "%x", 1 << lcore);
        TRY(fclose(file));

        printf("%s: Affinity set to 0x%x\n", dev_info.host_ifname, 1 << lcore);
    }

    closedir(dir);
}

Signed-off-by: Mats Liljegren <mats.liljegren at enea.com>
---
 lib/librte_ether/rte_ethdev.c      |  1 +
 lib/librte_ether/rte_ethdev.h      |  1 +
 lib/librte_pmd_pcap/rte_eth_pcap.c | 42 ++++++++++++++++++++++++++++++--------
 lib/librte_pmd_pcap/rte_eth_pcap.h |  7 +++++--
 4 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 675f247..bf126cf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1037,6 +1037,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct
rte_eth_dev_info *dev_info)
     /* Default device offload capabilities to zero */
     dev_info->rx_offload_capa = 0;
     dev_info->tx_offload_capa = 0;
+    dev_info->host_ifname = "";
     FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
     (*dev->dev_ops->dev_infos_get)(dev, dev_info);
     dev_info->pci_dev = dev->pci_dev;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 41268e1..8542911 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -786,6 +786,7 @@ struct rte_eth_conf {
 struct rte_eth_dev_info {
     struct rte_pci_device *pci_dev; /**< Device PCI information. */
     const char *driver_name; /**< Device Driver name. */
+    const char *host_ifname; /**< Name of interface as known to
Linux, or empty string. */
     uint32_t min_rx_bufsize; /**< Minimum size of RX buffer. */
     uint32_t max_rx_pktlen; /**< Maximum configurable length of RX pkt. */
     uint16_t max_rx_queues; /**< Maximum number of RX queues. */
diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c
b/lib/librte_pmd_pcap/rte_eth_pcap.c
index 08a944c..30bdd0c 100644
--- a/lib/librte_pmd_pcap/rte_eth_pcap.c
+++ b/lib/librte_pmd_pcap/rte_eth_pcap.c
@@ -87,6 +87,8 @@ struct pmd_internals {
     unsigned nb_rx_queues;
     unsigned nb_tx_queues;

+    char *iface_name;
+
     struct pcap_rx_queue rx_queue[RTE_PMD_RING_MAX_RX_RINGS];
     struct pcap_tx_queue tx_queue[RTE_PMD_RING_MAX_TX_RINGS];
 };
@@ -284,6 +286,7 @@ eth_dev_info(struct rte_eth_dev *dev,
 {
     struct pmd_internals *internals = dev->data->dev_private;
     dev_info->driver_name = drivername;
+    dev_info->host_ifname = internals->iface_name;
     dev_info->max_mac_addrs = 1;
     dev_info->max_rx_pktlen = (uint32_t) -1;
     dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
@@ -527,10 +530,22 @@ rte_pmd_init_internals(const unsigned nb_rx_queues,
         const unsigned nb_tx_queues,
         const unsigned numa_node,
         struct pmd_internals **internals,
-        struct rte_eth_dev **eth_dev)
+        struct rte_eth_dev **eth_dev,
+        struct args_dict *dict)
 {
     struct rte_eth_dev_data *data = NULL;
     struct rte_pci_device *pci_dev = NULL;
+    unsigned k_idx;
+    struct key_value *pair;
+
+    for (k_idx = 0; k_idx < dict->index; k_idx++) {
+        pair = &dict->pairs[k_idx];
+        if (strstr(pair->key, ETH_PCAP_IFACE_ARG) != NULL)
+            break;
+    }
+
+    if (k_idx == dict->index)
+        goto error;

     RTE_LOG(INFO, PMD,
             "Creating pcap-backed ethdev on numa socket %u\n", numa_node);
@@ -550,6 +565,12 @@ rte_pmd_init_internals(const unsigned nb_rx_queues,
     if (*internals == NULL)
         goto error;

+    (*internals)->iface_name = rte_zmalloc_socket(
+        NULL, strlen(pair->value) + 1, 0, numa_node);
+    if ((*internals)->iface_name == NULL)
+        goto error;
+    strcpy((*internals)->iface_name, pair->value);
+
     /* reserve an ethdev entry */
     *eth_dev = rte_eth_dev_allocate();
     if (*eth_dev == NULL)
@@ -588,6 +609,8 @@ rte_pmd_init_internals(const unsigned nb_rx_queues,
         rte_free(pci_dev);
     if (*internals)
         rte_free(*internals);
+    if ((*internals)->iface_name)
+        rte_free((*internals)->iface_name);
     return -1;
 }

@@ -596,7 +619,8 @@ rte_eth_from_pcaps_n_dumpers(pcap_t * const rx_queues[],
         const unsigned nb_rx_queues,
         pcap_dumper_t * const tx_queues[],
         const unsigned nb_tx_queues,
-        const unsigned numa_node)
+        const unsigned numa_node,
+        struct args_dict *dict)
 {
     struct pmd_internals *internals = NULL;
     struct rte_eth_dev *eth_dev = NULL;
@@ -609,7 +633,7 @@ rte_eth_from_pcaps_n_dumpers(pcap_t * const rx_queues[],
         return -1;

     if (rte_pmd_init_internals(nb_rx_queues, nb_tx_queues, numa_node,
-            &internals, &eth_dev) < 0)
+           &internals, &eth_dev, dict) < 0)
         return -1;

     for (i = 0; i < nb_rx_queues; i++) {
@@ -630,7 +654,8 @@ rte_eth_from_pcaps(pcap_t * const rx_queues[],
         const unsigned nb_rx_queues,
         pcap_t * const tx_queues[],
         const unsigned nb_tx_queues,
-        const unsigned numa_node)
+        const unsigned numa_node,
+        struct args_dict *dict)
 {
     struct pmd_internals *internals = NULL;
     struct rte_eth_dev *eth_dev = NULL;
@@ -643,7 +668,7 @@ rte_eth_from_pcaps(pcap_t * const rx_queues[],
         return -1;

     if (rte_pmd_init_internals(nb_rx_queues, nb_tx_queues, numa_node,
-            &internals, &eth_dev) < 0)
+           &internals, &eth_dev, dict) < 0)
         return -1;

     for (i = 0; i < nb_rx_queues; i++) {
@@ -691,7 +716,8 @@ rte_pmd_pcap_init(const char *name, const char *params)
         if (ret < 0)
             return -1;

-        return rte_eth_from_pcaps(pcaps.pcaps, 1, pcaps.pcaps, 1, numa_node);
+        return rte_eth_from_pcaps(pcaps.pcaps, 1, pcaps.pcaps, 1, numa_node,
+                      &dict);
     }

     /*
@@ -732,10 +758,10 @@ rte_pmd_pcap_init(const char *name, const char *params)

     if (using_dumpers)
         return rte_eth_from_pcaps_n_dumpers(pcaps.pcaps, pcaps.num_of_rx,
-                dumpers.dumpers, dumpers.num_of_tx, numa_node);
+                dumpers.dumpers, dumpers.num_of_tx, numa_node, &dict);

     return rte_eth_from_pcaps(pcaps.pcaps, pcaps.num_of_rx, dumpers.pcaps,
-            dumpers.num_of_tx, numa_node);
+                  dumpers.num_of_tx, numa_node, &dict);

 }

diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.h
b/lib/librte_pmd_pcap/rte_eth_pcap.h
index 368ed88..4a237a4 100644
--- a/lib/librte_pmd_pcap/rte_eth_pcap.h
+++ b/lib/librte_pmd_pcap/rte_eth_pcap.h
@@ -38,6 +38,7 @@
 extern "C" {
 #endif
 #include <pcap.h>
+#include "rte_eth_pcap_arg_parser.h"

 #ifdef pcap_sendpacket
 #define PCAP_CAN_SEND
@@ -51,13 +52,15 @@ int rte_eth_from_pcaps(pcap_t * const rx_queues[],
         const unsigned nb_rx_queues,
         pcap_t * const tx_queues[],
         const unsigned nb_tx_queues,
-        const unsigned numa_node);
+        const unsigned numa_node,
+        struct args_dict *dict);

 int rte_eth_from_pcaps_n_dumpers(pcap_t * const rx_queues[],
         const unsigned nb_rx_queues,
         pcap_dumper_t * const tx_queues[],
         const unsigned nb_tx_queues,
-        const unsigned numa_node);
+        const unsigned numa_node,
+        struct args_dict *dict);

 /**
  * For use by the EAL only. Called as part of EAL init to set up any dummy NICs
-- 
1.8.3.2


More information about the dev mailing list