]> The Tcpdump Group git mirrors - libpcap/blobdiff - pcap-dpdk.c
On Linux, return error on interface going away, not just going down.
[libpcap] / pcap-dpdk.c
index 2116ef44a989de887b751723617f49495163640b..6c2f21fca5f052caee17b8e81f4f884198d36836 100644 (file)
@@ -79,7 +79,6 @@ env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so
 #include <config.h>
 #endif
 
-#include <ctype.h>
 #include <errno.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -91,7 +90,9 @@ env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so
 #include <sys/time.h>
 
 //header for calling dpdk
+#include <rte_config.h>
 #include <rte_common.h>
+#include <rte_errno.h>
 #include <rte_log.h>
 #include <rte_malloc.h>
 #include <rte_memory.h>
@@ -115,6 +116,12 @@ env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so
 #include "pcap-dpdk.h"
 
 #define DPDK_DEF_LOG_LEV RTE_LOG_ERR
+//
+// This is set to 0 if we haven't initialized DPDK yet, 1 if we've
+// successfully initialized it, a negative value, which is the negative
+// of the rte_errno from rte_eal_init(), if we tried to initialize it
+// and got an error.
+//
 static int is_dpdk_pre_inited=0;
 #define DPDK_LIB_NAME "libpcap_dpdk"
 #define DPDK_DESC "Data Plane Development Kit (DPDK) Interface"
@@ -184,6 +191,53 @@ static struct rte_eth_conf port_conf = {
        },
 };
 
+static void    dpdk_fmt_errmsg_for_rte_errno(char *, size_t, int,
+    PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+
+/*
+ * Generate an error message based on a format, arguments, and an
+ * rte_errno, with a message for the rte_errno after the formatted output.
+ */
+static void dpdk_fmt_errmsg_for_rte_errno(char *errbuf, size_t errbuflen,
+    int errnum, const char *fmt, ...)
+{
+       va_list ap;
+       size_t msglen;
+       char *p;
+       size_t errbuflen_remaining;
+
+       va_start(ap, fmt);
+       vsnprintf(errbuf, errbuflen, fmt, ap);
+       va_end(ap);
+       msglen = strlen(errbuf);
+
+       /*
+        * Do we have enough space to append ": "?
+        * Including the terminating '\0', that's 3 bytes.
+        */
+       if (msglen + 3 > errbuflen) {
+               /* No - just give them what we've produced. */
+               return;
+       }
+       p = errbuf + msglen;
+       errbuflen_remaining = errbuflen - msglen;
+       *p++ = ':';
+       *p++ = ' ';
+       *p = '\0';
+       msglen += 2;
+       errbuflen_remaining -= 2;
+
+       /*
+        * Now append the string for the error code.
+        * rte_strerror() is thread-safe, at least as of dpdk 18.11,
+        * unlike strerror() - it uses strerror_r() rather than strerror()
+        * for UN*X errno values, and prints to what I assume is a per-thread
+        * buffer (based on the "PER_LCORE" in "RTE_DEFINE_PER_LCORE" used
+        * to declare the buffers statically) for DPDK errors.
+        */
+       snprintf(p, errbuflen_remaining, "%s", rte_strerror(errnum));
+}
+
 static int dpdk_init_timer(struct pcap_dpdk *pd){
        gettimeofday(&(pd->ts_helper.start_time),NULL);
        pd->ts_helper.start_cycles = rte_get_timer_cycles();
@@ -216,13 +270,13 @@ static uint32_t dpdk_gather_data(unsigned char *data, int len, struct rte_mbuf *
 }
 
 
-static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, uint16_t queueid,struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){
+static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){
        struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
        int nb_rx = 0;
        int timeout_ms = p->opt.timeout;
        int sleep_ms = 0;
        if (pd->nonblock){
-               // In non-blocking mode, just read once, no mater how many packets are captured.
+               // In non-blocking mode, just read once, no matter how many packets are captured.
                nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt);
        }else{
                // In blocking mode, read many times until packets are captured or timeout or break_loop is setted.
@@ -256,12 +310,11 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c
        uint16_t portid = pd->portid;
        // In DPDK, pkt_len is sum of lengths for all segments. And data_len is for one segment
        uint32_t pkt_len = 0;
-       int caplen = 0;
+       uint32_t caplen = 0;
        u_char *bp = NULL;
        int i=0;
        unsigned int gather_len =0;
        int pkt_cnt = 0;
-       int is_accepted=0;
        u_char *large_buffer=NULL;
        int timeout_ms = p->opt.timeout;
 
@@ -278,7 +331,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c
                }
                // read once in non-blocking mode, or try many times waiting for timeout_ms.
                // if timeout_ms == 0, it will be blocked until one packet arrives or break_loop is setted.
-               nb_rx = dpdk_read_with_timeout(p, portid, 0, pkts_burst, burst_cnt);
+               nb_rx = dpdk_read_with_timeout(p, portid, pkts_burst, burst_cnt);
                if (nb_rx == 0){
                        if (pd->nonblock){
                                RTE_LOG(DEBUG, USER1, "dpdk: no packets available in non-blocking mode.\n");
@@ -301,7 +354,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c
                        pkt_len = rte_pktmbuf_pkt_len(m);
                        // caplen = min(pkt_len, p->snapshot);
                        // caplen will not be changed, no matter how long the rte_pktmbuf
-                       caplen = pkt_len < p->snapshot ? pkt_len: p->snapshot;
+                       caplen = pkt_len < (uint32_t)p->snapshot ? pkt_len: (uint32_t)p->snapshot;
                        pcap_header.caplen = caplen;
                        pcap_header.len = pkt_len;
                        // volatile prefetch
@@ -345,8 +398,9 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c
 static int pcap_dpdk_inject(pcap_t *p, const void *buf _U_, int size _U_)
 {
        //not implemented yet
-       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-               errno, "dpdk error: Inject function has not been implemented yet");
+       pcap_strlcpy(p->errbuf,
+           "dpdk error: Inject function has not been implemented yet",
+           PCAP_ERRBUF_SIZE);
        return PCAP_ERROR;
 }
 
@@ -422,7 +476,7 @@ static void eth_addr_str(struct ether_addr *addrp, char* mac_str, int len)
 {
        int offset=0;
        if (addrp == NULL){
-               pcap_snprintf(mac_str, len-1, DPDK_DEF_MAC_ADDR);
+               snprintf(mac_str, len-1, DPDK_DEF_MAC_ADDR);
                return;
        }
        for (int i=0; i<6; i++)
@@ -433,10 +487,10 @@ static void eth_addr_str(struct ether_addr *addrp, char* mac_str, int len)
                }
                if (i==0)
                {
-                       pcap_snprintf(mac_str+offset, len-1-offset, "%02X",addrp->addr_bytes[i]);
+                       snprintf(mac_str+offset, len-1-offset, "%02X",addrp->addr_bytes[i]);
                        offset+=2; // FF
                }else{
-                       pcap_snprintf(mac_str+offset, len-1-offset, ":%02X", addrp->addr_bytes[i]);
+                       snprintf(mac_str+offset, len-1-offset, ":%02X", addrp->addr_bytes[i]);
                        offset+=3; // :FF
                }
        }
@@ -497,27 +551,40 @@ static int parse_dpdk_cfg(char* dpdk_cfg,char** dargv)
 }
 
 // only called once
-static int dpdk_pre_init(char * ebuf)
+// Returns:
+//
+//    1 on success;
+//
+//    0 if "the EAL cannot initialize on this system", which we treat as
+//    meaning "DPDK isn't available";
+//
+//    a PCAP_ERROR_ code for other errors.
+//
+// If eaccess_not_fatal is non-zero, treat "a permissions issue" the way
+// we treat "the EAL cannot initialize on this system".  We use that
+// when trying to find DPDK devices, as we don't want to fail to return
+// *any* devices just because we can't support DPDK; when we're trying
+// to open a device, we need to return a permissions error in that case.
+static int dpdk_pre_init(char * ebuf, int eaccess_not_fatal)
 {
        int dargv_cnt=0;
        char *dargv[DPDK_ARGC_MAX];
        char *ptr_dpdk_cfg = NULL;
-       int ret = PCAP_ERROR;
+       int ret;
        // globale var
-       if (is_dpdk_pre_inited)
-       {
-               // already inited
-               return 0;
-       }
-       // check for root permission
-       if( geteuid() != 0)
+       if (is_dpdk_pre_inited != 0)
        {
-               RTE_LOG(ERR, USER1, "%s\n", DPDK_ERR_PERM_MSG);
-               pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: %s",
-                           DPDK_ERR_PERM_MSG);
-               ret = PCAP_ERROR_PERM_DENIED;
-               return ret;
+               // already inited; did that succeed?
+               if (is_dpdk_pre_inited < 0)
+               {
+                       // failed
+                       goto error;
+               }
+               else
+               {
+                       // succeeded
+                       return 1;
+               }
        }
        // init EAL
        ptr_dpdk_cfg = getenv(DPDK_CFG_ENV_NAME);
@@ -532,11 +599,127 @@ static int dpdk_pre_init(char * ebuf)
        snprintf(dpdk_cfg_buf,DPDK_CFG_MAX_LEN-1,"%s %s",DPDK_LIB_NAME,ptr_dpdk_cfg);
        dargv_cnt = parse_dpdk_cfg(dpdk_cfg_buf,dargv);
        ret = rte_eal_init(dargv_cnt,dargv);
-       // if init successed, we do not need to do it again later.
-       if (ret == 0){
-               is_dpdk_pre_inited = 1;
+       if (ret == -1)
+       {
+               // Indicate that we've called rte_eal_init() by setting
+               // is_dpdk_pre_inited to the negative of the error code,
+               // and process the error.
+               is_dpdk_pre_inited = -rte_errno;
+               goto error;
        }
-       return ret;
+       // init succeeded, so we do not need to do it again later.
+       is_dpdk_pre_inited = 1;
+       return 1;
+
+error:
+       switch (-is_dpdk_pre_inited)
+       {
+               case EACCES:
+                       // This "indicates a permissions issue.".
+                       RTE_LOG(ERR, USER1, "%s\n", DPDK_ERR_PERM_MSG);
+                       // If we were told to treat this as just meaning
+                       // DPDK isn't available, do so.
+                       if (eaccess_not_fatal)
+                               return 0;
+                       // Otherwise report a fatal error.
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "DPDK requires that it run as root");
+                       return PCAP_ERROR_PERM_DENIED;
+
+               case EAGAIN:
+                       // This "indicates either a bus or system
+                       // resource was not available, setup may
+                       // be attempted again."
+                       // There's no such error in pcap, so I'm
+                       // not sure what we should do here.
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "Bus or system resource was not available");
+                       break;
+
+               case EALREADY:
+                       // This "indicates that the rte_eal_init
+                       // function has already been called, and
+                       // cannot be called again."
+                       // That's not an error; set the "we've
+                       // been here before" flag and return
+                       // success.
+                       is_dpdk_pre_inited = 1;
+                       return 1;
+
+               case EFAULT:
+                       // This "indicates the tailq configuration
+                       // name was not found in memory configuration."
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "The tailq configuration name was not found in the memory configuration");
+                       return PCAP_ERROR;
+
+               case EINVAL:
+                       // This "indicates invalid parameters were
+                       // passed as argv/argc."  Those came from
+                       // the configuration file.
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "The configuration file has invalid parameters");
+                       break;
+
+               case ENOMEM:
+                       // This "indicates failure likely caused by
+                       // an out-of-memory condition."
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "Out of memory");
+                       break;
+
+               case ENODEV:
+                       // This "indicates memory setup issues."
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "An error occurred setting up memory");
+                       break;
+
+               case ENOTSUP:
+                       // This "indicates that the EAL cannot
+                       // initialize on this system."  We treat
+                       // that as meaning DPDK isn't available
+                       // on this machine, rather than as a
+                       // fatal error, and let our caller decide
+                       // whether that's a fatal error (if trying
+                       // to activate a DPDK device) or not (if
+                       // trying to enumerate devices).
+                       return 0;
+
+               case EPROTO:
+                       // This "indicates that the PCI bus is
+                       // either not present, or is not readable
+                       // by the eal."  Does "the PCI bus is not
+                       // present" mean "this machine has no PCI
+                       // bus", which strikes me as a "not available"
+                       // case?  If so, should "is not readable by
+                       // the EAL" also something we should treat
+                       // as a "not available" case?  If not, we
+                       // can't distinguish between the two, so
+                       // we're stuck.
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "PCI bus is not present or not readable by the EAL");
+                       break;
+
+               case ENOEXEC:
+                       // This "indicates that a service core
+                       // failed to launch successfully."
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "A service core failed to launch successfully");
+                       break;
+
+               default:
+                       //
+                       // That's not in the list of errors in
+                       // the documentation; let it be reported
+                       // as an error.
+                       //
+                       dpdk_fmt_errmsg_for_rte_errno(ebuf,
+                           PCAP_ERRBUF_SIZE, -is_dpdk_pre_inited,
+                           "dpdk error: dpdk_pre_init failed");
+                       break;
+       }
+       // Error.
+       return PCAP_ERROR;
 }
 
 static int pcap_dpdk_activate(pcap_t *p)
@@ -554,21 +737,32 @@ static int pcap_dpdk_activate(pcap_t *p)
        int is_port_up = 0;
        struct rte_eth_link link;
        do{
-               //init EAL
-               ret = dpdk_pre_init(p->errbuf);
+               //init EAL; fail if we have insufficient permission
+               char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
+               ret = dpdk_pre_init(dpdk_pre_init_errbuf, 0);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: Init failed with device %s",
-                           p->opt.device);
-                       ret = PCAP_ERROR;
+                       // This returns a negative value on an error.
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "Can't open device %s: %s",
+                           p->opt.device, dpdk_pre_init_errbuf);
+                       // ret is set to the correct error
                        break;
                }
+               if (ret == 0)
+               {
+                       // This means DPDK isn't available on this machine.
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "Can't open device %s: DPDK is not available on this machine",
+                           p->opt.device);
+                       return PCAP_ERROR_NO_SUCH_DEVICE;
+               }
+
                ret = dpdk_init_timer(pd);
                if (ret<0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                               errno, "dpdk error: Init timer error with device %s",
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                               "dpdk error: Init timer is zero with device %s",
                                p->opt.device);
                        ret = PCAP_ERROR;
                        break;
@@ -577,16 +771,16 @@ static int pcap_dpdk_activate(pcap_t *p)
                nb_ports = rte_eth_dev_count_avail();
                if (nb_ports == 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: No Ethernet ports");
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "dpdk error: No Ethernet ports");
                        ret = PCAP_ERROR;
                        break;
                }
 
                portid = portid_by_device(p->opt.device);
                if (portid == DPDK_PORTID_MAX){
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: portid is invalid. device %s",
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "dpdk error: portid is invalid. device %s",
                            p->opt.device);
                        ret = PCAP_ERROR_NO_SUCH_DEVICE;
                        break;
@@ -604,8 +798,9 @@ static int pcap_dpdk_activate(pcap_t *p)
                        rte_socket_id());
                if (pd->pktmbuf_pool == NULL)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: Cannot init mbuf pool");
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, rte_errno,
+                           "dpdk error: Cannot init mbuf pool");
                        ret = PCAP_ERROR;
                        break;
                }
@@ -619,9 +814,10 @@ static int pcap_dpdk_activate(pcap_t *p)
                ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: Cannot configure device: err=%d, port=%u",
-                           ret, portid);
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, -ret,
+                           "dpdk error: Cannot configure device: port=%u",
+                           portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -629,9 +825,10 @@ static int pcap_dpdk_activate(pcap_t *p)
                ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: Cannot adjust number of descriptors: err=%d, port=%u",
-                           ret, portid);
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, -ret,
+                           "dpdk error: Cannot adjust number of descriptors: port=%u",
+                           portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -648,9 +845,10 @@ static int pcap_dpdk_activate(pcap_t *p)
                                             pd->pktmbuf_pool);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: rte_eth_rx_queue_setup:err=%d, port=%u",
-                           ret, portid);
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, -ret,
+                           "dpdk error: rte_eth_rx_queue_setup:port=%u",
+                           portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -663,9 +861,10 @@ static int pcap_dpdk_activate(pcap_t *p)
                                &txq_conf);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: rte_eth_tx_queue_setup:err=%d, port=%u",
-                           ret, portid);
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, -ret,
+                           "dpdk error: rte_eth_tx_queue_setup:port=%u",
+                           portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -675,8 +874,8 @@ static int pcap_dpdk_activate(pcap_t *p)
                                rte_eth_dev_socket_id(portid));
                if (tx_buffer == NULL)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: Cannot allocate buffer for tx on port %u", portid);
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "dpdk error: Cannot allocate buffer for tx on port %u", portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -685,9 +884,10 @@ static int pcap_dpdk_activate(pcap_t *p)
                ret = rte_eth_dev_start(portid);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: rte_eth_dev_start:err=%d, port=%u",
-                           ret, portid);
+                       dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
+                           PCAP_ERRBUF_SIZE, -ret,
+                           "dpdk error: rte_eth_dev_start:port=%u",
+                           portid);
                        ret = PCAP_ERROR;
                        break;
                }
@@ -699,8 +899,8 @@ static int pcap_dpdk_activate(pcap_t *p)
                // check link status
                is_port_up = check_link_status(portid, &link);
                if (!is_port_up){
-                       pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
-                           errno, "dpdk error: link is down, port=%u",portid);
+                       snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+                           "dpdk error: link is down, port=%u",portid);
                        ret = PCAP_ERROR_IFACE_NOT_UP;
                        break;
                }
@@ -777,31 +977,41 @@ int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf)
        char mac_addr[DPDK_MAC_ADDR_SIZE];
        char pci_addr[DPDK_PCI_ADDR_SIZE];
        do{
-               ret = dpdk_pre_init(ebuf);
+               // init EAL; return "DPDK not available" if we
+               // have insufficient permission
+               char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
+               ret = dpdk_pre_init(dpdk_pre_init_errbuf, 1);
                if (ret < 0)
                {
-                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-                           errno, "error: Init failed with device");
+                       // This returns a negative value on an error.
+                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                           "Can't look for DPDK devices: %s",
+                           dpdk_pre_init_errbuf);
                        ret = PCAP_ERROR;
                        break;
                }
+               if (ret == 0)
+               {
+                       // This means DPDK isn't available on this machine.
+                       // That just means "don't return any devices".
+                       break;
+               }
                nb_ports = rte_eth_dev_count_avail();
                if (nb_ports == 0)
                {
-                       pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
-                           errno, "DPDK error: No Ethernet ports");
-                       ret = PCAP_ERROR;
+                       // That just means "don't return any devices".
+                       ret = 0;
                        break;
                }
                for (unsigned int i=0; i<nb_ports; i++){
-                       pcap_snprintf(dpdk_name, DPDK_DEV_NAME_MAX-1,
+                       snprintf(dpdk_name, DPDK_DEV_NAME_MAX-1,
                            "%s%u", DPDK_PREFIX, i);
                        // mac addr
                        rte_eth_macaddr_get(i, &eth_addr);
                        eth_addr_str(&eth_addr,mac_addr,DPDK_MAC_ADDR_SIZE);
                        // PCI addr
                        rte_eth_dev_get_name_by_port(i,pci_addr);
-                       pcap_snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr);
+                       snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr);
                        if (add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){
                                ret = PCAP_ERROR;
                                break;
@@ -831,7 +1041,7 @@ pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
 pcap_t *
 pcap_create_interface(const char *device, char *errbuf)
 {
-       pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+       snprintf(errbuf, PCAP_ERRBUF_SIZE,
            "This version of libpcap only supports DPDK");
        return NULL;
 }