DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows
@ 2021-02-14  1:20 Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 1/6] eal: add internal API for current time Dmitry Kozlyuk
                   ` (6 more replies)
  0 siblings, 7 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk

Most modern and actively maintained distribution of libpcap for Windows is Npcap
(https://nmap.org/npcap). It is free (as in "free beer") and open-source, but
Npcap redistribution with commercial products may be limited by its license.

Npcap can be installed anywhere, so a new Meson option is provided to find it:

    meson -Dpcap_sdk=C:\Npcap -Dexamples=skeleton build

Example of collecting packets from an interface to a file:

    .\build\examples\dpdk-skeleton.exe `
        --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
        --vdev "eth_pcap1,tx_pcap=capture.pcap"

Implementation in "pcap_osdep_windows.c" does some guesswork to convert
between variants of an interface name. Microsoft experts and interested
users, please take a look and/or give it a try in your environment.

There are no release notes for 21.05 yet, will send update after they appear.

Dmitry Kozlyuk (6):
  eal: add internal API for current time
  net/pcap: fix format string
  net/pcap: move OS-dependent code to separate files
  net/pcap: add libpcap wrappers
  config: discover libpcap on Windows
  net/pcap: build on Windows

 config/meson.build                            |  21 +-
 drivers/net/pcap/meson.build                  |  17 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 251 ++++++------------
 drivers/net/pcap/pcap_osdep.c                 | 122 +++++++++
 drivers/net/pcap/pcap_osdep.h                 |  72 +++++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 ++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++
 drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++
 lib/librte_eal/include/rte_time.h             |  17 ++
 lib/librte_eal/rte_eal_exports.def            |   1 +
 lib/librte_eal/unix/eal_unix_timer.c          |  13 +
 lib/librte_eal/version.map                    |   1 +
 lib/librte_eal/windows/eal_timer.c            |  20 +-
 meson_options.txt                             |   6 +-
 14 files changed, 584 insertions(+), 176 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (88%)
 create mode 100644 drivers/net/pcap/pcap_osdep.c
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 1/6] eal: add internal API for current time
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-03-01 22:31   ` Nick Connolly
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 2/6] net/pcap: fix format string Dmitry Kozlyuk
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev
  Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam,
	Ray Kinsella, Neil Horman

Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
to obtain current time with microsecond precision on all platforms.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 lib/librte_eal/include/rte_time.h    | 17 +++++++++++++++++
 lib/librte_eal/rte_eal_exports.def   |  1 +
 lib/librte_eal/unix/eal_unix_timer.c | 13 +++++++++++++
 lib/librte_eal/version.map           |  1 +
 lib/librte_eal/windows/eal_timer.c   | 20 +++++++++++++++++++-
 5 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/include/rte_time.h b/lib/librte_eal/include/rte_time.h
index 5ad7c8841..50fa4f889 100644
--- a/lib/librte_eal/include/rte_time.h
+++ b/lib/librte_eal/include/rte_time.h
@@ -8,6 +8,8 @@
 #include <stdint.h>
 #include <time.h>
 
+#include <rte_compat.h>
+
 #define NSEC_PER_SEC             1000000000L
 
 /**
@@ -98,4 +100,19 @@ rte_ns_to_timespec(uint64_t nsec)
 	return ts;
 }
 
+/* Point of time with microsecond precision. */
+struct rte_time_us {
+	int64_t sec;  /**< Number of whole seconds. */
+	int64_t usec; /**< Fractional part of second in [0, 999999]. */
+};
+
+/**
+ * Get current system time.
+ *
+ * @param now
+ *  Receives current system time.
+ */
+__rte_internal
+void rte_time_get_us(struct rte_time_us *now);
+
 #endif /* _RTE_TIME_H_ */
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..cb691f7bc 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -334,3 +334,4 @@ EXPORTS
 	rte_mem_map
 	rte_mem_page_size
 	rte_mem_unmap
+	rte_time_get_us
diff --git a/lib/librte_eal/unix/eal_unix_timer.c b/lib/librte_eal/unix/eal_unix_timer.c
index cc5015910..5612fdebe 100644
--- a/lib/librte_eal/unix/eal_unix_timer.c
+++ b/lib/librte_eal/unix/eal_unix_timer.c
@@ -4,7 +4,10 @@
 
 #include <time.h>
 
+#include <sys/time.h>
+
 #include <rte_cycles.h>
+#include <rte_time.h>
 
 void
 rte_delay_us_sleep(unsigned int us)
@@ -27,3 +30,13 @@ rte_delay_us_sleep(unsigned int us)
 		ind = 1 - ind;
 	}
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	struct timeval sys;
+
+	gettimeofday(&sys, NULL);
+	now->sec = sys.tv_sec;
+	now->usec = sys.tv_usec;
+}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index fce90a112..405bed766 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,4 +421,5 @@ INTERNAL {
 	rte_mem_map;
 	rte_mem_page_size;
 	rte_mem_unmap;
+	rte_time_get_us;
 };
diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c
index b070cb775..b5c8eaa73 100644
--- a/lib/librte_eal/windows/eal_timer.c
+++ b/lib/librte_eal/windows/eal_timer.c
@@ -9,6 +9,7 @@
 #include <rte_cycles.h>
 #include <rte_eal.h>
 #include <rte_errno.h>
+#include <rte_time.h>
 #include "eal_private.h"
 
 #define US_PER_SEC 1E6
@@ -85,10 +86,27 @@ get_tsc_freq(void)
 	return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ);
 }
 
-
 int
 rte_eal_timer_init(void)
 {
 	set_tsc_freq();
 	return 0;
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_USEC = 10;
+	static const uint64_t USEC_PER_SEC = 1000000;
+
+	FILETIME ft;
+	uint64_t ticks, sec;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	sec = (ticks - EPOCH) / (TICKS_PER_USEC * USEC_PER_SEC);
+	now->sec = sec;
+	now->usec = (ticks - sec * USEC_PER_SEC) / TICKS_PER_USEC;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 2/6] net/pcap: fix format string
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 1/6] eal: add internal API for current time Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-03-01 22:33   ` Nick Connolly
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, stable, Ferruh Yigit

Use PRIu32 for uint32_t (found by -Wformat with Clang on Windows).

Fixes: a3f5252e5cbd ("net/pcap: enable infinitely Rx a pcap file")
Cc: stable@dpdk.org

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/rte_eth_pcap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 90f5d75ea..176928da3 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -827,7 +827,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 		pcap_pkt_count = count_packets_in_pcap(pcap, pcap_q);
 
-		snprintf(ring_name, sizeof(ring_name), "PCAP_RING%" PRIu16,
+		snprintf(ring_name, sizeof(ring_name), "PCAP_RING%" PRIu32,
 				ring_number);
 
 		pcap_q->pkts = rte_ring_create(ring_name,
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 3/6] net/pcap: move OS-dependent code to separate files
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 1/6] eal: add internal API for current time Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 2/6] net/pcap: fix format string Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

PCAP PMD queries interface information differently for Linux and
FreeBSD, OS-specific code is guarded by #ifdef. In preparation to add
Windows-specific part and libpcap wrapper, extract OS-independent
interface and move implementations to separate files. Rename
rte_eth_pcap.c to pcap_ethdev.c for consistency with the rest of DPDK.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build                  |  5 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 88 ++-----------------
 drivers/net/pcap/pcap_osdep.h                 | 17 ++++
 drivers/net/pcap/pcap_osdep_freebsd.c         | 59 +++++++++++++
 drivers/net/pcap/pcap_osdep_linux.c           | 42 +++++++++
 5 files changed, 130 insertions(+), 81 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index b65d91e70..26b606699 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
-sources = files('rte_eth_pcap.c')
+sources = files(
+	'pcap_ethdev.c',
+	'pcap_osdep_@0@.c'.format(exec_env),
+)
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/pcap_ethdev.c
similarity index 95%
rename from drivers/net/pcap/rte_eth_pcap.c
rename to drivers/net/pcap/pcap_ethdev.c
index 176928da3..a102897e9 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -6,16 +6,6 @@
 
 #include <time.h>
 
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#if defined(RTE_EXEC_ENV_FREEBSD)
-#include <sys/sysctl.h>
-#include <net/if_dl.h>
-#endif
-
 #include <pcap.h>
 
 #include <rte_cycles.h>
@@ -25,7 +15,8 @@
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
 #include <rte_bus_vdev.h>
-#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
@@ -1191,84 +1182,20 @@ static int
 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
 		const unsigned int numa_node)
 {
-#if defined(RTE_EXEC_ENV_LINUX)
 	void *mac_addrs;
-	struct ifreq ifr;
-	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-	if (if_fd == -1)
-		return -1;
+	struct rte_ether_addr mac;
 
-	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
-		close(if_fd);
+	if (osdep_iface_mac_get(if_name, &mac) < 0)
 		return -1;
-	}
 
 	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		close(if_fd);
+	if (mac_addrs == NULL)
 		return -1;
-	}
 
 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
+	rte_memcpy(mac_addrs, mac.addr_bytes, RTE_ETHER_ADDR_LEN);
 	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
-
-	close(if_fd);
-
-	return 0;
-
-#elif defined(RTE_EXEC_ENV_FREEBSD)
-	void *mac_addrs;
-	struct if_msghdr *ifm;
-	struct sockaddr_dl *sdl;
-	int mib[6];
-	size_t len = 0;
-	char *buf;
-
-	mib[0] = CTL_NET;
-	mib[1] = AF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_LINK;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = if_nametoindex(if_name);
-
-	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
-		return -1;
-
-	if (len == 0)
-		return -1;
-
-	buf = rte_malloc(NULL, len, 0);
-	if (!buf)
-		return -1;
-
-	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
-		rte_free(buf);
-		return -1;
-	}
-	ifm = (struct if_msghdr *)buf;
-	sdl = (struct sockaddr_dl *)(ifm + 1);
-
-	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		rte_free(buf);
-		return -1;
-	}
-
-	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
-	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			LLADDR(sdl), RTE_ETHER_ADDR_LEN);
-
-	rte_free(buf);
-
 	return 0;
-#else
-	return -1;
-#endif
 }
 
 static int
@@ -1330,7 +1257,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 	internals->single_iface = single_iface;
 
 	if (single_iface) {
-		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
+		internals->if_index =
+			osdep_iface_index_get(rx_queues->queue[0].name);
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
new file mode 100644
index 000000000..46810d86f
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#ifndef _RTE_PCAP_OSDEP_
+#define _RTE_PCAP_OSDEP_
+
+#include <rte_ether.h>
+
+/*
+ * Interface manipulation is always OS-specific.
+ */
+
+int osdep_iface_index_get(const char *name);
+int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
+
+#endif
diff --git a/drivers/net/pcap/pcap_osdep_freebsd.c b/drivers/net/pcap/pcap_osdep_freebsd.c
new file mode 100644
index 000000000..20556b3e9
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_freebsd.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len = 0;
+	char *buf;
+
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(if_name);
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+		return -1;
+
+	if (len == 0)
+		return -1;
+
+	buf = rte_malloc(NULL, len, 0);
+	if (!buf)
+		return -1;
+
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		rte_free(buf);
+		return -1;
+	}
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(ifm + 1);
+
+	rte_memcpy(mac->addr_bytes, LLADDR(sdl), RTE_ETHER_ADDR_LEN);
+
+	rte_free(buf);
+	return 0;
+}
diff --git a/drivers/net/pcap/pcap_osdep_linux.c b/drivers/net/pcap/pcap_osdep_linux.c
new file mode 100644
index 000000000..97033f57c
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_linux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct ifreq ifr;
+	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (if_fd == -1)
+		return -1;
+
+	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
+		close(if_fd);
+		return -1;
+	}
+
+	rte_memcpy(mac->addr_bytes, ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
+
+	close(if_fd);
+	return 0;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 4/6] net/pcap: add libpcap wrappers
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
                   ` (2 preceding siblings ...)
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

libpcap headers can expose OS headers. On Windows, system networking
headers are incompatible with DPDK ones, causing multiple name clashes.
API of libpcap itself involves a non-standard u_char type.

Add a limited set of trivial libpcap wrappers, so that libpcap headers
are not included directly by OS-independent PMD code. Use EAL types and
functions for time instead of POSIX ones.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build   |   1 +
 drivers/net/pcap/pcap_ethdev.c | 157 +++++++++++++++++----------------
 drivers/net/pcap/pcap_osdep.c  | 122 +++++++++++++++++++++++++
 drivers/net/pcap/pcap_osdep.h  |  50 +++++++++++
 4 files changed, 252 insertions(+), 78 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 26b606699..9ab95ec3e 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -13,6 +13,7 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 endif
 sources = files(
 	'pcap_ethdev.c',
+	'pcap_osdep.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index a102897e9..6461213e0 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -4,17 +4,13 @@
  * All rights reserved.
  */
 
-#include <time.h>
-
-#include <pcap.h>
-
-#include <rte_cycles.h>
 #include <ethdev_driver.h>
 #include <ethdev_vdev.h>
+#include <rte_bus_vdev.h>
+#include <rte_cycles.h>
 #include <rte_kvargs.h>
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
-#include <rte_bus_vdev.h>
 
 #include "pcap_osdep.h"
 
@@ -36,8 +32,8 @@
 
 #define RTE_PMD_PCAP_MAX_QUEUES 16
 
-static char errbuf[PCAP_ERRBUF_SIZE];
-static struct timeval start_time;
+static char errbuf[OSDEP_PCAP_ERRBUF_SIZE];
+static struct rte_time_us start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
 static uint8_t iface_idx;
@@ -83,16 +79,16 @@ struct pmd_internals {
 };
 
 struct pmd_process_private {
-	pcap_t *rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
-	pcap_t *tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
-	pcap_dumper_t *tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap * rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap * tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap_dumper * tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
 };
 
 struct pmd_devargs {
 	unsigned int num_of_queue;
 	struct devargs_queue {
-		pcap_dumper_t *dumper;
-		pcap_t *pcap;
+		osdep_pcap_dumper *dumper;
+		osdep_pcap *pcap;
 		const char *name;
 		const char *type;
 	} queue[RTE_PMD_PCAP_MAX_QUEUES];
@@ -137,7 +133,7 @@ RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
 static int
 eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf,
-		const u_char *data, uint16_t data_len)
+		const uint8_t *data, uint16_t data_len)
 {
 	/* Copy the first segment. */
 	uint16_t len = rte_pktmbuf_tailroom(mbuf);
@@ -214,14 +210,14 @@ static uint16_t
 eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 {
 	unsigned int i;
-	struct pcap_pkthdr header;
+	struct osdep_pcap_pkthdr header;
 	struct pmd_process_private *pp;
-	const u_char *packet;
+	const uint8_t *packet;
 	struct rte_mbuf *mbuf;
 	struct pcap_rx_queue *pcap_q = queue;
 	uint16_t num_rx = 0;
 	uint32_t rx_bytes = 0;
-	pcap_t *pcap;
+	osdep_pcap *pcap;
 
 	pp = rte_eth_devices[pcap_q->port_id].process_private;
 	pcap = pp->rx_pcap[pcap_q->queue_id];
@@ -234,7 +230,7 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	 */
 	for (i = 0; i < nb_pkts; i++) {
 		/* Get the next PCAP packet */
-		packet = pcap_next(pcap, &header);
+		packet = osdep_pcap_next(pcap, &header);
 		if (unlikely(packet == NULL))
 			break;
 
@@ -261,8 +257,8 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		mbuf->pkt_len = (uint16_t)header.caplen;
 		*RTE_MBUF_DYNFIELD(mbuf, timestamp_dynfield_offset,
 			rte_mbuf_timestamp_t *) =
-				(uint64_t)header.ts.tv_sec * 1000000 +
-				header.ts.tv_usec;
+				(uint64_t)header.ts.sec * 1000000 +
+				header.ts.usec;
 		mbuf->ol_flags |= timestamp_rx_dynflag;
 		mbuf->port = pcap_q->port_id;
 		bufs[num_rx] = mbuf;
@@ -285,20 +281,24 @@ eth_null_rx(void *queue __rte_unused,
 
 #define NSEC_PER_SEC	1000000000L
 
+/*
+ * This function stores nanoseconds in "usec" field of struct rte_time_us,
+ * because "ts" goes directly to nanosecond-precision dump.
+ */
 static inline void
-calculate_timestamp(struct timeval *ts) {
+calculate_timestamp(struct rte_time_us *ts) {
 	uint64_t cycles;
-	struct timeval cur_time;
+	struct rte_time_us cur_time;
 
 	cycles = rte_get_timer_cycles() - start_cycles;
-	cur_time.tv_sec = cycles / hz;
-	cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz;
-
-	ts->tv_sec = start_time.tv_sec + cur_time.tv_sec;
-	ts->tv_usec = start_time.tv_usec + cur_time.tv_usec;
-	if (ts->tv_usec >= NSEC_PER_SEC) {
-		ts->tv_usec -= NSEC_PER_SEC;
-		ts->tv_sec += 1;
+	cur_time.sec = cycles / hz;
+	cur_time.usec = (cycles % hz) * NSEC_PER_SEC / hz;
+
+	ts->sec = start_time.sec + cur_time.sec;
+	ts->usec = start_time.usec + cur_time.usec;
+	if (ts->usec >= NSEC_PER_SEC) {
+		ts->usec -= NSEC_PER_SEC;
+		ts->sec += 1;
 	}
 }
 
@@ -314,8 +314,8 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	struct pcap_tx_queue *dumper_q = queue;
 	uint16_t num_tx = 0;
 	uint32_t tx_bytes = 0;
-	struct pcap_pkthdr header;
-	pcap_dumper_t *dumper;
+	struct osdep_pcap_pkthdr header;
+	osdep_pcap_dumper *dumper;
 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
 	size_t len, caplen;
 
@@ -342,7 +342,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
 		 * a pointer to temp_data after copying into it.
 		 */
-		pcap_dump((u_char *)dumper, &header,
+		osdep_pcap_dump((uint8_t *)dumper, &header,
 			rte_pktmbuf_read(mbuf, 0, caplen, temp_data));
 
 		num_tx++;
@@ -355,7 +355,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	 * process stops and to make sure the pcap file is actually written,
 	 * we flush the pcap dumper within each burst.
 	 */
-	pcap_dump_flush(dumper);
+	osdep_pcap_dump_flush(dumper);
 	dumper_q->tx_stat.pkts += num_tx;
 	dumper_q->tx_stat.bytes += tx_bytes;
 	dumper_q->tx_stat.err_pkts += nb_pkts - num_tx;
@@ -400,7 +400,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	struct pcap_tx_queue *tx_queue = queue;
 	uint16_t num_tx = 0;
 	uint32_t tx_bytes = 0;
-	pcap_t *pcap;
+	osdep_pcap *pcap;
 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
 	size_t len;
 
@@ -426,7 +426,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
 		 * a pointer to temp_data after copying into it.
 		 */
-		ret = pcap_sendpacket(pcap,
+		ret = osdep_pcap_sendpacket(pcap,
 			rte_pktmbuf_read(mbuf, 0, len, temp_data), len);
 		if (unlikely(ret != 0))
 			break;
@@ -443,11 +443,11 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 }
 
 /*
- * pcap_open_live wrapper function
+ * osdep_pcap_open_live wrapper function
  */
 static inline int
-open_iface_live(const char *iface, pcap_t **pcap) {
-	*pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,
+open_iface_live(const char *iface, osdep_pcap **pcap) {
+	*pcap = osdep_pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,
 			RTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf);
 
 	if (*pcap == NULL) {
@@ -459,7 +459,7 @@ open_iface_live(const char *iface, pcap_t **pcap) {
 }
 
 static int
-open_single_iface(const char *iface, pcap_t **pcap)
+open_single_iface(const char *iface, osdep_pcap **pcap)
 {
 	if (open_iface_live(iface, pcap) < 0) {
 		PMD_LOG(ERR, "Couldn't open interface %s", iface);
@@ -470,39 +470,39 @@ open_single_iface(const char *iface, pcap_t **pcap)
 }
 
 static int
-open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper)
+open_single_tx_pcap(const char *pcap_filename, osdep_pcap_dumper **dumper)
 {
-	pcap_t *tx_pcap;
+	osdep_pcap *tx_pcap;
 
 	/*
-	 * We need to create a dummy empty pcap_t to use it
-	 * with pcap_dump_open(). We create big enough an Ethernet
+	 * We need to create a dummy empty osdep_pcap to use it
+	 * with osdep_pcap_dump_open(). We create big enough an Ethernet
 	 * pcap holder.
 	 */
-	tx_pcap = pcap_open_dead_with_tstamp_precision(DLT_EN10MB,
-			RTE_ETH_PCAP_SNAPSHOT_LEN, PCAP_TSTAMP_PRECISION_NANO);
+	tx_pcap = osdep_pcap_open_dead_with_tstamp_precision(OSDEP_DLT_EN10MB,
+		RTE_ETH_PCAP_SNAPSHOT_LEN, OSDEP_PCAP_TSTAMP_PRECISION_NANO);
 	if (tx_pcap == NULL) {
 		PMD_LOG(ERR, "Couldn't create dead pcap");
 		return -1;
 	}
 
-	/* The dumper is created using the previous pcap_t reference */
-	*dumper = pcap_dump_open(tx_pcap, pcap_filename);
+	/* The dumper is created using the previous osdep_pcap reference */
+	*dumper = osdep_pcap_dump_open(tx_pcap, pcap_filename);
 	if (*dumper == NULL) {
-		pcap_close(tx_pcap);
+		osdep_pcap_close(tx_pcap);
 		PMD_LOG(ERR, "Couldn't open %s for writing.",
 			pcap_filename);
 		return -1;
 	}
 
-	pcap_close(tx_pcap);
+	osdep_pcap_close(tx_pcap);
 	return 0;
 }
 
 static int
-open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)
+open_single_rx_pcap(const char *pcap_filename, osdep_pcap **pcap)
 {
-	*pcap = pcap_open_offline(pcap_filename, errbuf);
+	*pcap = osdep_pcap_open_offline(pcap_filename, errbuf);
 	if (*pcap == NULL) {
 		PMD_LOG(ERR, "Couldn't open %s: %s", pcap_filename,
 			errbuf);
@@ -513,17 +513,17 @@ open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)
 }
 
 static uint64_t
-count_packets_in_pcap(pcap_t **pcap, struct pcap_rx_queue *pcap_q)
+count_packets_in_pcap(osdep_pcap **pcap, struct pcap_rx_queue *pcap_q)
 {
-	const u_char *packet;
-	struct pcap_pkthdr header;
+	const uint8_t *packet;
+	struct osdep_pcap_pkthdr header;
 	uint64_t pcap_pkt_count = 0;
 
-	while ((packet = pcap_next(*pcap, &header)))
+	while ((packet = osdep_pcap_next(*pcap, &header)))
 		pcap_pkt_count++;
 
 	/* The pcap is reopened so it can be used as normal later. */
-	pcap_close(*pcap);
+	osdep_pcap_close(*pcap);
 	*pcap = NULL;
 	open_single_rx_pcap(pcap_q->name, pcap);
 
@@ -612,7 +612,7 @@ eth_dev_stop(struct rte_eth_dev *dev)
 
 	/* Special iface case. Single pcap is open and shared between tx/rx. */
 	if (internals->single_iface) {
-		pcap_close(pp->tx_pcap[0]);
+		osdep_pcap_close(pp->tx_pcap[0]);
 		pp->tx_pcap[0] = NULL;
 		pp->rx_pcap[0] = NULL;
 		goto status_down;
@@ -620,19 +620,19 @@ eth_dev_stop(struct rte_eth_dev *dev)
 
 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
 		if (pp->tx_dumper[i] != NULL) {
-			pcap_dump_close(pp->tx_dumper[i]);
+			osdep_pcap_dump_close(pp->tx_dumper[i]);
 			pp->tx_dumper[i] = NULL;
 		}
 
 		if (pp->tx_pcap[i] != NULL) {
-			pcap_close(pp->tx_pcap[i]);
+			osdep_pcap_close(pp->tx_pcap[i]);
 			pp->tx_pcap[i] = NULL;
 		}
 	}
 
 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		if (pp->rx_pcap[i] != NULL) {
-			pcap_close(pp->rx_pcap[i]);
+			osdep_pcap_close(pp->rx_pcap[i]);
 			pp->rx_pcap[i] = NULL;
 		}
 	}
@@ -804,11 +804,11 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (internals->infinite_rx) {
 		struct pmd_process_private *pp;
-		char ring_name[NAME_MAX];
+		char ring_name[RTE_RING_NAMESIZE];
 		static uint32_t ring_number;
 		uint64_t pcap_pkt_count = 0;
 		struct rte_mbuf *bufs[1];
-		pcap_t **pcap;
+		osdep_pcap **pcap;
 
 		pp = rte_eth_devices[pcap_q->port_id].process_private;
 		pcap = &pp->rx_pcap[pcap_q->queue_id];
@@ -932,7 +932,7 @@ static const struct eth_dev_ops ops = {
 
 static int
 add_queue(struct pmd_devargs *pmd, const char *name, const char *type,
-		pcap_t *pcap, pcap_dumper_t *dumper)
+		osdep_pcap *pcap, osdep_pcap_dumper *dumper)
 {
 	if (pmd->num_of_queue >= RTE_PMD_PCAP_MAX_QUEUES)
 		return -1;
@@ -955,13 +955,13 @@ open_rx_pcap(const char *key, const char *value, void *extra_args)
 {
 	const char *pcap_filename = value;
 	struct pmd_devargs *rx = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_rx_pcap(pcap_filename, &pcap) < 0)
 		return -1;
 
 	if (add_queue(rx, pcap_filename, key, pcap, NULL) < 0) {
-		pcap_close(pcap);
+		osdep_pcap_close(pcap);
 		return -1;
 	}
 
@@ -977,13 +977,13 @@ open_tx_pcap(const char *key, const char *value, void *extra_args)
 {
 	const char *pcap_filename = value;
 	struct pmd_devargs *dumpers = extra_args;
-	pcap_dumper_t *dumper;
+	osdep_pcap_dumper *dumper;
 
 	if (open_single_tx_pcap(pcap_filename, &dumper) < 0)
 		return -1;
 
 	if (add_queue(dumpers, pcap_filename, key, NULL, dumper) < 0) {
-		pcap_dump_close(dumper);
+		osdep_pcap_dump_close(dumper);
 		return -1;
 	}
 
@@ -998,7 +998,7 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
 {
 	const char *iface = value;
 	struct pmd_devargs *tx = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_iface(iface, &pcap) < 0)
 		return -1;
@@ -1011,13 +1011,14 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
 }
 
 static inline int
-set_iface_direction(const char *iface, pcap_t *pcap,
-		pcap_direction_t direction)
+set_iface_direction(const char *iface, osdep_pcap *pcap,
+		enum osdep_pcap_direction direction)
 {
-	const char *direction_str = (direction == PCAP_D_IN) ? "IN" : "OUT";
-	if (pcap_setdirection(pcap, direction) < 0) {
+	const char *direction_str =
+		(direction == OSDEP_PCAP_D_IN) ? "IN" : "OUT";
+	if (osdep_pcap_setdirection(pcap, direction) < 0) {
 		PMD_LOG(ERR, "Setting %s pcap direction %s failed - %s\n",
-				iface, direction_str, pcap_geterr(pcap));
+				iface, direction_str, osdep_pcap_geterr(pcap));
 		return -1;
 	}
 	PMD_LOG(INFO, "Setting %s pcap direction %s\n",
@@ -1030,12 +1031,12 @@ open_iface(const char *key, const char *value, void *extra_args)
 {
 	const char *iface = value;
 	struct pmd_devargs *pmd = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_iface(iface, &pcap) < 0)
 		return -1;
 	if (add_queue(pmd, iface, key, pcap, NULL) < 0) {
-		pcap_close(pcap);
+		osdep_pcap_close(pcap);
 		return -1;
 	}
 
@@ -1057,7 +1058,7 @@ open_rx_iface(const char *key, const char *value, void *extra_args)
 
 		set_iface_direction(pmd->queue[qid].name,
 				pmd->queue[qid].pcap,
-				PCAP_D_IN);
+				OSDEP_PCAP_D_IN);
 	}
 
 	return 0;
@@ -1311,7 +1312,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	name = rte_vdev_device_name(dev);
 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
 
-	gettimeofday(&start_time, NULL);
+	rte_time_get_us(&start_time);
 	start_cycles = rte_get_timer_cycles();
 	hz = rte_get_timer_hz();
 
diff --git a/drivers/net/pcap/pcap_osdep.c b/drivers/net/pcap/pcap_osdep.c
new file mode 100644
index 000000000..5cac9bb89
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.c
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <pcap.h>
+
+#include <rte_common.h>
+
+#include "pcap_osdep.h"
+
+static inline void
+to_osdep_header(const struct pcap_pkthdr *in, struct osdep_pcap_pkthdr *out)
+{
+	out->ts.sec = in->ts.tv_sec;
+	out->ts.usec = in->ts.tv_usec;
+	out->caplen = in->caplen;
+	out->len = in->len;
+}
+
+static inline void
+to_pcap_header(const struct osdep_pcap_pkthdr *in, struct pcap_pkthdr *out)
+{
+	out->ts.tv_sec = in->ts.sec;
+	out->ts.tv_usec = in->ts.usec;
+	out->caplen = in->caplen;
+	out->len = in->len;
+}
+
+osdep_pcap *
+osdep_pcap_open_live(const char *device, int snaplen,
+	int promisc, int to_ms, char *errbuf)
+{
+	RTE_BUILD_BUG_ON(OSDEP_PCAP_ERRBUF_SIZE != PCAP_ERRBUF_SIZE);
+
+	return (osdep_pcap *)pcap_open_live(device, snaplen, promisc, to_ms,
+		errbuf);
+}
+
+osdep_pcap *
+osdep_pcap_open_offline(const char *fname, char *errbuf)
+{
+	return (osdep_pcap *)pcap_open_offline(fname, errbuf);
+}
+
+osdep_pcap *
+osdep_pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+	unsigned int precision)
+{
+	RTE_BUILD_BUG_ON(OSDEP_DLT_EN10MB != DLT_EN10MB);
+	RTE_BUILD_BUG_ON(OSDEP_PCAP_TSTAMP_PRECISION_NANO !=
+			PCAP_TSTAMP_PRECISION_NANO);
+
+	return (osdep_pcap *)pcap_open_dead_with_tstamp_precision(linktype,
+		snaplen, precision);
+}
+
+const uint8_t *
+osdep_pcap_next(osdep_pcap *pcap, struct osdep_pcap_pkthdr *header)
+{
+	const uint8_t *data;
+	struct pcap_pkthdr pkthdr;
+
+	data = pcap_next((pcap_t *)pcap, &pkthdr);
+	to_osdep_header(&pkthdr, header);
+	return data;
+}
+
+int
+osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size)
+{
+	return pcap_sendpacket((pcap_t *)pcap, buf, size);
+}
+
+void
+osdep_pcap_close(osdep_pcap *pcap)
+{
+	pcap_close((pcap_t *)pcap);
+}
+
+osdep_pcap_dumper *
+osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname)
+{
+	return (osdep_pcap_dumper *)pcap_dump_open((pcap_t *)pcap, fname);
+}
+
+void
+osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header,
+	const uint8_t *sp)
+{
+	struct pcap_pkthdr pkthdr;
+
+	to_pcap_header(header, &pkthdr);
+	pcap_dump(user, &pkthdr, sp);
+}
+
+int
+osdep_pcap_dump_flush(osdep_pcap_dumper *p)
+{
+	return pcap_dump_flush((pcap_dumper_t *)p);
+}
+
+void
+osdep_pcap_dump_close(osdep_pcap_dumper *p)
+{
+	pcap_dump_close((pcap_dumper_t *)p);
+}
+
+int
+osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir)
+{
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_INOUT != (int)PCAP_D_INOUT);
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_IN != (int)PCAP_D_IN);
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_OUT != (int)PCAP_D_OUT);
+
+	return pcap_setdirection((pcap_t *)pcap, (pcap_direction_t)dir);
+}
+
+const char *
+osdep_pcap_geterr(osdep_pcap *pcap)
+{
+	return pcap_geterr((pcap_t *)pcap);
+}
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 46810d86f..bd00b728a 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -6,6 +6,7 @@
 #define _RTE_PCAP_OSDEP_
 
 #include <rte_ether.h>
+#include <rte_time.h>
 
 /*
  * Interface manipulation is always OS-specific.
@@ -14,4 +15,53 @@
 int osdep_iface_index_get(const char *name);
 int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
 
+/*
+ * On Windows, libpcap (npcap or WinPcap) exposes Win32 API which clashes
+ * with some DPDK constructs. Trivial libpcap wrappers with "osdep_" prefix
+ * are provided to isolate PMD code from Win32 API.
+ */
+
+#define OSDEP_DLT_EN10MB 1
+
+#define OSDEP_PCAP_ERRBUF_SIZE 256
+
+#define OSDEP_PCAP_TSTAMP_PRECISION_NANO 1
+
+/** Handle for an open packet capture. */
+typedef struct osdep_pcap_type osdep_pcap;
+
+/** Handle for an open packet dump. */
+typedef struct osdep_pcap_dumper_type osdep_pcap_dumper;
+
+struct osdep_pcap_pkthdr {
+	struct rte_time_us ts;
+	uint32_t caplen;
+	uint32_t len;
+};
+
+enum osdep_pcap_direction {
+	OSDEP_PCAP_D_INOUT = 0,
+	OSDEP_PCAP_D_IN,
+	OSDEP_PCAP_D_OUT
+};
+
+osdep_pcap *osdep_pcap_open_live(const char *device, int snaplen,
+	int promisc, int to_ms, char *errbuf);
+osdep_pcap *osdep_pcap_open_offline(const char *fname, char *errbuf);
+osdep_pcap *osdep_pcap_open_dead_with_tstamp_precision(int linktype,
+	int snaplen, unsigned int precision);
+const uint8_t *osdep_pcap_next(osdep_pcap *pcap,
+	struct osdep_pcap_pkthdr *header);
+int osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size);
+void osdep_pcap_close(osdep_pcap *pcap);
+
+osdep_pcap_dumper *osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname);
+void osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header,
+	const uint8_t *sp);
+int osdep_pcap_dump_flush(osdep_pcap_dumper *p);
+void osdep_pcap_dump_close(osdep_pcap_dumper *p);
+
+int osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir);
+const char *osdep_pcap_geterr(osdep_pcap *pcap);
+
 #endif
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 5/6] config: discover libpcap on Windows
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
                   ` (3 preceding siblings ...)
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 6/6] net/pcap: build " Dmitry Kozlyuk
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
  6 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Bruce Richardson

WinPcap or Npcap, can be installed anywhere.
Add a Meson option to specify SDK path.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 config/meson.build | 21 ++++++++++++++++++---
 meson_options.txt  |  6 ++++--
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/config/meson.build b/config/meson.build
index 3cf560b8a..6aae8276c 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -178,9 +178,24 @@ if not pcap_dep.found()
 	# pcap got a pkg-config file only in 1.9.0
 	pcap_dep = cc.find_library('pcap', required: false)
 endif
-if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
-	dpdk_conf.set('RTE_PORT_PCAP', 1)
-	dpdk_extra_ldflags += '-lpcap'
+if is_windows
+	# npcap SDK can be installed anywhere
+	pcap_sdk = get_option('pcap_sdk')
+	if pcap_sdk != ''
+		pcap_ldflags = ['-L@0@/Lib/x64'.format(pcap_sdk), '-lwpcap']
+		pcap_dep = declare_dependency(
+			compile_args: ['-I@0@/Include'.format(pcap_sdk)],
+			link_args: pcap_ldflags)
+	endif
+	if pcap_dep.found()
+		dpdk_conf.set('RTE_PORT_PCAP', 1)
+		dpdk_extra_ldflags += pcap_ldflags
+	endif
+else
+	if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
+		dpdk_conf.set('RTE_PORT_PCAP', 1)
+		dpdk_extra_ldflags += '-lpcap'
+	endif
 endif
 
 # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
diff --git a/meson_options.txt b/meson_options.txt
index 6eff62e47..d74146d3a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,6 +10,8 @@ option('enable_docs', type: 'boolean', value: false,
 	description: 'build documentation')
 option('enable_kmods', type: 'boolean', value: false,
 	description: 'build kernel modules')
+option('enable_trace_fp', type: 'boolean', value: false,
+	description: 'enable fast path trace points.')
 option('examples', type: 'string', value: '',
 	description: 'Comma-separated list of examples to build by default')
 option('flexran_sdk', type: 'string', value: '',
@@ -28,8 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
 	description: 'maximum number of cores/threads supported by EAL')
 option('max_numa_nodes', type: 'integer', value: 32,
 	description: 'maximum number of NUMA nodes supported by EAL')
-option('enable_trace_fp', type: 'boolean', value: false,
-	description: 'enable fast path trace points.')
+option('pcap_sdk', type: 'string', value: '',
+	description: 'Path to libpcap SDK used on Windows')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
 option('use_hpet', type: 'boolean', value: false,
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH 6/6] net/pcap: build on Windows
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
                   ` (4 preceding siblings ...)
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
@ 2021-02-14  1:20 ` Dmitry Kozlyuk
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
  6 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  1:20 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

Implement OS-dependent functions and enable PMD build on Windows.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build          |  11 ++-
 drivers/net/pcap/pcap_ethdev.c        |   4 -
 drivers/net/pcap/pcap_osdep.h         |   5 ++
 drivers/net/pcap/pcap_osdep_windows.c | 118 ++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 9ab95ec3e..614a4e340 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -1,19 +1,18 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-if is_windows
-	build = false
-	reason = 'not supported on Windows'
-	subdir_done()
-endif
-
 if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
+
 sources = files(
 	'pcap_ethdev.c',
 	'pcap_osdep.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
+
 ext_deps += pcap_dep
+if is_windows
+	ext_deps += cc.find_library('iphlpapi', required: true)
+endif
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 6461213e0..142533c6e 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -127,10 +127,6 @@ static struct rte_eth_link pmd_link = {
 
 RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
-#define PMD_LOG(level, fmt, args...) \
-	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
-		"%s(): " fmt "\n", __func__, ##args)
-
 static int
 eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf,
 		const uint8_t *data, uint16_t data_len)
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index bd00b728a..f7c311ef8 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -8,6 +8,11 @@
 #include <rte_ether.h>
 #include <rte_time.h>
 
+#define PMD_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
+		"%s(): " fmt "\n", __func__, ##args)
+extern int eth_pcap_logtype;
+
 /*
  * Interface manipulation is always OS-specific.
  */
diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
new file mode 100644
index 000000000..d6557ff73
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_windows.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
+
+#include "pcap_osdep.h"
+
+/*
+ * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
+ * Return NULL if "{GUID}" part is not found.
+ */
+static const char *
+iface_guid(const char *name)
+{
+	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
+
+	const char *ob, *cb;
+
+	ob = strchr(name, '{');
+	if (ob == NULL)
+		return NULL;
+
+	cb = strchr(ob, '}');
+	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
+		return NULL;
+
+	return ob;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
+ * Try to convert, fall back to original device name.
+ */
+int
+osdep_iface_index_get(const char *device_name)
+{
+	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
+	const char *guid;
+	ULONG index;
+	DWORD ret;
+
+	guid = iface_guid(device_name);
+	if (guid != NULL)
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"\\DEVICE\\TCPIP_%s", guid);
+	else
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"%s", device_name);
+
+	ret = GetAdapterIndex(adapter_name, &index);
+	if (ret != NO_ERROR) {
+		PMD_LOG(ERR, "GetAdapterIndex() = %lu\n", ret);
+		return -1;
+	}
+
+	return index;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdaptersAddresses() returns names in "{GUID}" form.
+ * Try to extract GUID from device name, fall back to original device name.
+ */
+int
+osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
+{
+	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
+	ULONG size, sys_ret;
+	const char *adapter_name;
+	int ret = -1;
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
+	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
+			sys_ret, ERROR_BUFFER_OVERFLOW);
+		return -1;
+	}
+
+	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
+	if (info == NULL) {
+		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
+		return -1;
+	}
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
+	if (sys_ret != ERROR_SUCCESS) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
+		free(info);
+		return -1;
+	}
+
+	adapter_name = iface_guid(device_name);
+	if (adapter_name == NULL)
+		adapter_name = device_name;
+
+	for (cur = info; cur != NULL; cur = cur->Next) {
+		if (strcmp(cur->AdapterName, adapter_name) == 0) {
+			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
+				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
+					RTE_ETHER_ADDR_LEN,
+					cur->PhysicalAddressLength);
+				return -1;
+			}
+
+			memcpy(mac->addr_bytes, cur->PhysicalAddress,
+				RTE_ETHER_ADDR_LEN);
+			ret = 0;
+			break;
+		}
+	}
+
+	free(info);
+	return ret;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 0/6] net/pcap: build on Windows
  2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
                   ` (5 preceding siblings ...)
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 6/6] net/pcap: build " Dmitry Kozlyuk
@ 2021-02-14  2:16 ` Dmitry Kozlyuk
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
                     ` (6 more replies)
  6 siblings, 7 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk

Most modern and actively maintained distribution of libpcap for Windows is Npcap
(https://nmap.org/npcap). It is free (as in "free beer") and open-source, but
Npcap redistribution with commercial products may be limited by its license.

Npcap can be installed anywhere, so a new Meson option is provided to find it:

    meson -Dpcap_sdk=C:\Npcap -Dexamples=skeleton build

Example of collecting packets from an interface to a file:

    .\build\examples\dpdk-skeleton.exe `
        --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
        --vdev "eth_pcap1,tx_pcap=capture.pcap"

Implementation in "pcap_osdep_windows.c" does some guesswork to convert
between variants of an interface name. Microsoft experts and interested
users, please take a look and/or give it a try in your environment.

There are no release notes for 21.05 yet, will send update after they appear.

v2: fix microsecond calculation on Windows in patch 1/6.

Dmitry Kozlyuk (6):
  eal: add internal API for current time
  net/pcap: fix format string
  net/pcap: move OS-dependent code to separate files
  net/pcap: add libpcap wrappers
  config: discover libpcap on Windows
  net/pcap: build on Windows

 config/meson.build                            |  21 +-
 drivers/net/pcap/meson.build                  |  17 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 251 ++++++------------
 drivers/net/pcap/pcap_osdep.c                 | 122 +++++++++
 drivers/net/pcap/pcap_osdep.h                 |  72 +++++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 ++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++
 drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++
 lib/librte_eal/include/rte_time.h             |  17 ++
 lib/librte_eal/rte_eal_exports.def            |   1 +
 lib/librte_eal/unix/eal_unix_timer.c          |  13 +
 lib/librte_eal/version.map                    |   1 +
 lib/librte_eal/windows/eal_timer.c            |  21 +-
 meson_options.txt                             |   6 +-
 14 files changed, 585 insertions(+), 176 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (88%)
 create mode 100644 drivers/net/pcap/pcap_osdep.c
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-03-01 22:39     ` Nick Connolly
                       ` (3 more replies)
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string Dmitry Kozlyuk
                     ` (5 subsequent siblings)
  6 siblings, 4 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev
  Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam,
	Ray Kinsella, Neil Horman

Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
to obtain current time with microsecond precision on all platforms.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 lib/librte_eal/include/rte_time.h    | 17 +++++++++++++++++
 lib/librte_eal/rte_eal_exports.def   |  1 +
 lib/librte_eal/unix/eal_unix_timer.c | 13 +++++++++++++
 lib/librte_eal/version.map           |  1 +
 lib/librte_eal/windows/eal_timer.c   | 21 ++++++++++++++++++++-
 5 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/include/rte_time.h b/lib/librte_eal/include/rte_time.h
index 5ad7c8841..50fa4f889 100644
--- a/lib/librte_eal/include/rte_time.h
+++ b/lib/librte_eal/include/rte_time.h
@@ -8,6 +8,8 @@
 #include <stdint.h>
 #include <time.h>
 
+#include <rte_compat.h>
+
 #define NSEC_PER_SEC             1000000000L
 
 /**
@@ -98,4 +100,19 @@ rte_ns_to_timespec(uint64_t nsec)
 	return ts;
 }
 
+/* Point of time with microsecond precision. */
+struct rte_time_us {
+	int64_t sec;  /**< Number of whole seconds. */
+	int64_t usec; /**< Fractional part of second in [0, 999999]. */
+};
+
+/**
+ * Get current system time.
+ *
+ * @param now
+ *  Receives current system time.
+ */
+__rte_internal
+void rte_time_get_us(struct rte_time_us *now);
+
 #endif /* _RTE_TIME_H_ */
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index 474cf123f..cb691f7bc 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -334,3 +334,4 @@ EXPORTS
 	rte_mem_map
 	rte_mem_page_size
 	rte_mem_unmap
+	rte_time_get_us
diff --git a/lib/librte_eal/unix/eal_unix_timer.c b/lib/librte_eal/unix/eal_unix_timer.c
index cc5015910..5612fdebe 100644
--- a/lib/librte_eal/unix/eal_unix_timer.c
+++ b/lib/librte_eal/unix/eal_unix_timer.c
@@ -4,7 +4,10 @@
 
 #include <time.h>
 
+#include <sys/time.h>
+
 #include <rte_cycles.h>
+#include <rte_time.h>
 
 void
 rte_delay_us_sleep(unsigned int us)
@@ -27,3 +30,13 @@ rte_delay_us_sleep(unsigned int us)
 		ind = 1 - ind;
 	}
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	struct timeval sys;
+
+	gettimeofday(&sys, NULL);
+	now->sec = sys.tv_sec;
+	now->usec = sys.tv_usec;
+}
diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map
index fce90a112..405bed766 100644
--- a/lib/librte_eal/version.map
+++ b/lib/librte_eal/version.map
@@ -421,4 +421,5 @@ INTERNAL {
 	rte_mem_map;
 	rte_mem_page_size;
 	rte_mem_unmap;
+	rte_time_get_us;
 };
diff --git a/lib/librte_eal/windows/eal_timer.c b/lib/librte_eal/windows/eal_timer.c
index b070cb775..a5c42106a 100644
--- a/lib/librte_eal/windows/eal_timer.c
+++ b/lib/librte_eal/windows/eal_timer.c
@@ -9,6 +9,7 @@
 #include <rte_cycles.h>
 #include <rte_eal.h>
 #include <rte_errno.h>
+#include <rte_time.h>
 #include "eal_private.h"
 
 #define US_PER_SEC 1E6
@@ -85,10 +86,28 @@ get_tsc_freq(void)
 	return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_10MHZ);
 }
 
-
 int
 rte_eal_timer_init(void)
 {
 	set_tsc_freq();
 	return 0;
 }
+
+void
+rte_time_get_us(struct rte_time_us *now)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_USEC = 10;
+	static const uint64_t USEC_PER_SEC = 1000000;
+
+	FILETIME ft;
+	uint64_t ticks, sec;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	ticks -= EPOCH;
+	sec = ticks / (TICKS_PER_USEC * USEC_PER_SEC);
+	now->sec = sec;
+	now->usec = ticks / TICKS_PER_USEC - sec * USEC_PER_SEC;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-02-25 14:45     ` Ferruh Yigit
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, stable, Ferruh Yigit

Use PRIu32 for uint32_t (found by -Wformat with Clang on Windows).

Fixes: a3f5252e5cbd ("net/pcap: enable infinitely Rx a pcap file")
Cc: stable@dpdk.org

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/rte_eth_pcap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 90f5d75ea..176928da3 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -827,7 +827,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 		pcap_pkt_count = count_packets_in_pcap(pcap, pcap_q);
 
-		snprintf(ring_name, sizeof(ring_name), "PCAP_RING%" PRIu16,
+		snprintf(ring_name, sizeof(ring_name), "PCAP_RING%" PRIu32,
 				ring_number);
 
 		pcap_q->pkts = rte_ring_create(ring_name,
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-02-25 14:51     ` Ferruh Yigit
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

PCAP PMD queries interface information differently for Linux and
FreeBSD, OS-specific code is guarded by #ifdef. In preparation to add
Windows-specific part and libpcap wrapper, extract OS-independent
interface and move implementations to separate files. Rename
rte_eth_pcap.c to pcap_ethdev.c for consistency with the rest of DPDK.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build                  |  5 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 88 ++-----------------
 drivers/net/pcap/pcap_osdep.h                 | 17 ++++
 drivers/net/pcap/pcap_osdep_freebsd.c         | 59 +++++++++++++
 drivers/net/pcap/pcap_osdep_linux.c           | 42 +++++++++
 5 files changed, 130 insertions(+), 81 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index b65d91e70..26b606699 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
-sources = files('rte_eth_pcap.c')
+sources = files(
+	'pcap_ethdev.c',
+	'pcap_osdep_@0@.c'.format(exec_env),
+)
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/pcap_ethdev.c
similarity index 95%
rename from drivers/net/pcap/rte_eth_pcap.c
rename to drivers/net/pcap/pcap_ethdev.c
index 176928da3..a102897e9 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -6,16 +6,6 @@
 
 #include <time.h>
 
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#if defined(RTE_EXEC_ENV_FREEBSD)
-#include <sys/sysctl.h>
-#include <net/if_dl.h>
-#endif
-
 #include <pcap.h>
 
 #include <rte_cycles.h>
@@ -25,7 +15,8 @@
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
 #include <rte_bus_vdev.h>
-#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
@@ -1191,84 +1182,20 @@ static int
 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
 		const unsigned int numa_node)
 {
-#if defined(RTE_EXEC_ENV_LINUX)
 	void *mac_addrs;
-	struct ifreq ifr;
-	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-	if (if_fd == -1)
-		return -1;
+	struct rte_ether_addr mac;
 
-	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
-		close(if_fd);
+	if (osdep_iface_mac_get(if_name, &mac) < 0)
 		return -1;
-	}
 
 	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		close(if_fd);
+	if (mac_addrs == NULL)
 		return -1;
-	}
 
 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
+	rte_memcpy(mac_addrs, mac.addr_bytes, RTE_ETHER_ADDR_LEN);
 	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
-
-	close(if_fd);
-
-	return 0;
-
-#elif defined(RTE_EXEC_ENV_FREEBSD)
-	void *mac_addrs;
-	struct if_msghdr *ifm;
-	struct sockaddr_dl *sdl;
-	int mib[6];
-	size_t len = 0;
-	char *buf;
-
-	mib[0] = CTL_NET;
-	mib[1] = AF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_LINK;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = if_nametoindex(if_name);
-
-	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
-		return -1;
-
-	if (len == 0)
-		return -1;
-
-	buf = rte_malloc(NULL, len, 0);
-	if (!buf)
-		return -1;
-
-	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
-		rte_free(buf);
-		return -1;
-	}
-	ifm = (struct if_msghdr *)buf;
-	sdl = (struct sockaddr_dl *)(ifm + 1);
-
-	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		rte_free(buf);
-		return -1;
-	}
-
-	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
-	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			LLADDR(sdl), RTE_ETHER_ADDR_LEN);
-
-	rte_free(buf);
-
 	return 0;
-#else
-	return -1;
-#endif
 }
 
 static int
@@ -1330,7 +1257,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 	internals->single_iface = single_iface;
 
 	if (single_iface) {
-		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
+		internals->if_index =
+			osdep_iface_index_get(rx_queues->queue[0].name);
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
new file mode 100644
index 000000000..46810d86f
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#ifndef _RTE_PCAP_OSDEP_
+#define _RTE_PCAP_OSDEP_
+
+#include <rte_ether.h>
+
+/*
+ * Interface manipulation is always OS-specific.
+ */
+
+int osdep_iface_index_get(const char *name);
+int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
+
+#endif
diff --git a/drivers/net/pcap/pcap_osdep_freebsd.c b/drivers/net/pcap/pcap_osdep_freebsd.c
new file mode 100644
index 000000000..20556b3e9
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_freebsd.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len = 0;
+	char *buf;
+
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(if_name);
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+		return -1;
+
+	if (len == 0)
+		return -1;
+
+	buf = rte_malloc(NULL, len, 0);
+	if (!buf)
+		return -1;
+
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		rte_free(buf);
+		return -1;
+	}
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(ifm + 1);
+
+	rte_memcpy(mac->addr_bytes, LLADDR(sdl), RTE_ETHER_ADDR_LEN);
+
+	rte_free(buf);
+	return 0;
+}
diff --git a/drivers/net/pcap/pcap_osdep_linux.c b/drivers/net/pcap/pcap_osdep_linux.c
new file mode 100644
index 000000000..97033f57c
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_linux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct ifreq ifr;
+	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (if_fd == -1)
+		return -1;
+
+	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
+		close(if_fd);
+		return -1;
+	}
+
+	rte_memcpy(mac->addr_bytes, ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
+
+	close(if_fd);
+	return 0;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
                     ` (2 preceding siblings ...)
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-02-25 14:59     ` Ferruh Yigit
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

libpcap headers can expose OS headers. On Windows, system networking
headers are incompatible with DPDK ones, causing multiple name clashes.
API of libpcap itself involves a non-standard u_char type.

Add a limited set of trivial libpcap wrappers, so that libpcap headers
are not included directly by OS-independent PMD code. Use EAL types and
functions for time instead of POSIX ones.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build   |   1 +
 drivers/net/pcap/pcap_ethdev.c | 157 +++++++++++++++++----------------
 drivers/net/pcap/pcap_osdep.c  | 122 +++++++++++++++++++++++++
 drivers/net/pcap/pcap_osdep.h  |  50 +++++++++++
 4 files changed, 252 insertions(+), 78 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 26b606699..9ab95ec3e 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -13,6 +13,7 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 endif
 sources = files(
 	'pcap_ethdev.c',
+	'pcap_osdep.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index a102897e9..6461213e0 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -4,17 +4,13 @@
  * All rights reserved.
  */
 
-#include <time.h>
-
-#include <pcap.h>
-
-#include <rte_cycles.h>
 #include <ethdev_driver.h>
 #include <ethdev_vdev.h>
+#include <rte_bus_vdev.h>
+#include <rte_cycles.h>
 #include <rte_kvargs.h>
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
-#include <rte_bus_vdev.h>
 
 #include "pcap_osdep.h"
 
@@ -36,8 +32,8 @@
 
 #define RTE_PMD_PCAP_MAX_QUEUES 16
 
-static char errbuf[PCAP_ERRBUF_SIZE];
-static struct timeval start_time;
+static char errbuf[OSDEP_PCAP_ERRBUF_SIZE];
+static struct rte_time_us start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
 static uint8_t iface_idx;
@@ -83,16 +79,16 @@ struct pmd_internals {
 };
 
 struct pmd_process_private {
-	pcap_t *rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
-	pcap_t *tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
-	pcap_dumper_t *tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap * rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap * tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+	osdep_pcap_dumper * tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
 };
 
 struct pmd_devargs {
 	unsigned int num_of_queue;
 	struct devargs_queue {
-		pcap_dumper_t *dumper;
-		pcap_t *pcap;
+		osdep_pcap_dumper *dumper;
+		osdep_pcap *pcap;
 		const char *name;
 		const char *type;
 	} queue[RTE_PMD_PCAP_MAX_QUEUES];
@@ -137,7 +133,7 @@ RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
 static int
 eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf,
-		const u_char *data, uint16_t data_len)
+		const uint8_t *data, uint16_t data_len)
 {
 	/* Copy the first segment. */
 	uint16_t len = rte_pktmbuf_tailroom(mbuf);
@@ -214,14 +210,14 @@ static uint16_t
 eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 {
 	unsigned int i;
-	struct pcap_pkthdr header;
+	struct osdep_pcap_pkthdr header;
 	struct pmd_process_private *pp;
-	const u_char *packet;
+	const uint8_t *packet;
 	struct rte_mbuf *mbuf;
 	struct pcap_rx_queue *pcap_q = queue;
 	uint16_t num_rx = 0;
 	uint32_t rx_bytes = 0;
-	pcap_t *pcap;
+	osdep_pcap *pcap;
 
 	pp = rte_eth_devices[pcap_q->port_id].process_private;
 	pcap = pp->rx_pcap[pcap_q->queue_id];
@@ -234,7 +230,7 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	 */
 	for (i = 0; i < nb_pkts; i++) {
 		/* Get the next PCAP packet */
-		packet = pcap_next(pcap, &header);
+		packet = osdep_pcap_next(pcap, &header);
 		if (unlikely(packet == NULL))
 			break;
 
@@ -261,8 +257,8 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		mbuf->pkt_len = (uint16_t)header.caplen;
 		*RTE_MBUF_DYNFIELD(mbuf, timestamp_dynfield_offset,
 			rte_mbuf_timestamp_t *) =
-				(uint64_t)header.ts.tv_sec * 1000000 +
-				header.ts.tv_usec;
+				(uint64_t)header.ts.sec * 1000000 +
+				header.ts.usec;
 		mbuf->ol_flags |= timestamp_rx_dynflag;
 		mbuf->port = pcap_q->port_id;
 		bufs[num_rx] = mbuf;
@@ -285,20 +281,24 @@ eth_null_rx(void *queue __rte_unused,
 
 #define NSEC_PER_SEC	1000000000L
 
+/*
+ * This function stores nanoseconds in "usec" field of struct rte_time_us,
+ * because "ts" goes directly to nanosecond-precision dump.
+ */
 static inline void
-calculate_timestamp(struct timeval *ts) {
+calculate_timestamp(struct rte_time_us *ts) {
 	uint64_t cycles;
-	struct timeval cur_time;
+	struct rte_time_us cur_time;
 
 	cycles = rte_get_timer_cycles() - start_cycles;
-	cur_time.tv_sec = cycles / hz;
-	cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz;
-
-	ts->tv_sec = start_time.tv_sec + cur_time.tv_sec;
-	ts->tv_usec = start_time.tv_usec + cur_time.tv_usec;
-	if (ts->tv_usec >= NSEC_PER_SEC) {
-		ts->tv_usec -= NSEC_PER_SEC;
-		ts->tv_sec += 1;
+	cur_time.sec = cycles / hz;
+	cur_time.usec = (cycles % hz) * NSEC_PER_SEC / hz;
+
+	ts->sec = start_time.sec + cur_time.sec;
+	ts->usec = start_time.usec + cur_time.usec;
+	if (ts->usec >= NSEC_PER_SEC) {
+		ts->usec -= NSEC_PER_SEC;
+		ts->sec += 1;
 	}
 }
 
@@ -314,8 +314,8 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	struct pcap_tx_queue *dumper_q = queue;
 	uint16_t num_tx = 0;
 	uint32_t tx_bytes = 0;
-	struct pcap_pkthdr header;
-	pcap_dumper_t *dumper;
+	struct osdep_pcap_pkthdr header;
+	osdep_pcap_dumper *dumper;
 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
 	size_t len, caplen;
 
@@ -342,7 +342,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
 		 * a pointer to temp_data after copying into it.
 		 */
-		pcap_dump((u_char *)dumper, &header,
+		osdep_pcap_dump((uint8_t *)dumper, &header,
 			rte_pktmbuf_read(mbuf, 0, caplen, temp_data));
 
 		num_tx++;
@@ -355,7 +355,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	 * process stops and to make sure the pcap file is actually written,
 	 * we flush the pcap dumper within each burst.
 	 */
-	pcap_dump_flush(dumper);
+	osdep_pcap_dump_flush(dumper);
 	dumper_q->tx_stat.pkts += num_tx;
 	dumper_q->tx_stat.bytes += tx_bytes;
 	dumper_q->tx_stat.err_pkts += nb_pkts - num_tx;
@@ -400,7 +400,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	struct pcap_tx_queue *tx_queue = queue;
 	uint16_t num_tx = 0;
 	uint32_t tx_bytes = 0;
-	pcap_t *pcap;
+	osdep_pcap *pcap;
 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
 	size_t len;
 
@@ -426,7 +426,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
 		 * a pointer to temp_data after copying into it.
 		 */
-		ret = pcap_sendpacket(pcap,
+		ret = osdep_pcap_sendpacket(pcap,
 			rte_pktmbuf_read(mbuf, 0, len, temp_data), len);
 		if (unlikely(ret != 0))
 			break;
@@ -443,11 +443,11 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 }
 
 /*
- * pcap_open_live wrapper function
+ * osdep_pcap_open_live wrapper function
  */
 static inline int
-open_iface_live(const char *iface, pcap_t **pcap) {
-	*pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,
+open_iface_live(const char *iface, osdep_pcap **pcap) {
+	*pcap = osdep_pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,
 			RTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf);
 
 	if (*pcap == NULL) {
@@ -459,7 +459,7 @@ open_iface_live(const char *iface, pcap_t **pcap) {
 }
 
 static int
-open_single_iface(const char *iface, pcap_t **pcap)
+open_single_iface(const char *iface, osdep_pcap **pcap)
 {
 	if (open_iface_live(iface, pcap) < 0) {
 		PMD_LOG(ERR, "Couldn't open interface %s", iface);
@@ -470,39 +470,39 @@ open_single_iface(const char *iface, pcap_t **pcap)
 }
 
 static int
-open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper)
+open_single_tx_pcap(const char *pcap_filename, osdep_pcap_dumper **dumper)
 {
-	pcap_t *tx_pcap;
+	osdep_pcap *tx_pcap;
 
 	/*
-	 * We need to create a dummy empty pcap_t to use it
-	 * with pcap_dump_open(). We create big enough an Ethernet
+	 * We need to create a dummy empty osdep_pcap to use it
+	 * with osdep_pcap_dump_open(). We create big enough an Ethernet
 	 * pcap holder.
 	 */
-	tx_pcap = pcap_open_dead_with_tstamp_precision(DLT_EN10MB,
-			RTE_ETH_PCAP_SNAPSHOT_LEN, PCAP_TSTAMP_PRECISION_NANO);
+	tx_pcap = osdep_pcap_open_dead_with_tstamp_precision(OSDEP_DLT_EN10MB,
+		RTE_ETH_PCAP_SNAPSHOT_LEN, OSDEP_PCAP_TSTAMP_PRECISION_NANO);
 	if (tx_pcap == NULL) {
 		PMD_LOG(ERR, "Couldn't create dead pcap");
 		return -1;
 	}
 
-	/* The dumper is created using the previous pcap_t reference */
-	*dumper = pcap_dump_open(tx_pcap, pcap_filename);
+	/* The dumper is created using the previous osdep_pcap reference */
+	*dumper = osdep_pcap_dump_open(tx_pcap, pcap_filename);
 	if (*dumper == NULL) {
-		pcap_close(tx_pcap);
+		osdep_pcap_close(tx_pcap);
 		PMD_LOG(ERR, "Couldn't open %s for writing.",
 			pcap_filename);
 		return -1;
 	}
 
-	pcap_close(tx_pcap);
+	osdep_pcap_close(tx_pcap);
 	return 0;
 }
 
 static int
-open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)
+open_single_rx_pcap(const char *pcap_filename, osdep_pcap **pcap)
 {
-	*pcap = pcap_open_offline(pcap_filename, errbuf);
+	*pcap = osdep_pcap_open_offline(pcap_filename, errbuf);
 	if (*pcap == NULL) {
 		PMD_LOG(ERR, "Couldn't open %s: %s", pcap_filename,
 			errbuf);
@@ -513,17 +513,17 @@ open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)
 }
 
 static uint64_t
-count_packets_in_pcap(pcap_t **pcap, struct pcap_rx_queue *pcap_q)
+count_packets_in_pcap(osdep_pcap **pcap, struct pcap_rx_queue *pcap_q)
 {
-	const u_char *packet;
-	struct pcap_pkthdr header;
+	const uint8_t *packet;
+	struct osdep_pcap_pkthdr header;
 	uint64_t pcap_pkt_count = 0;
 
-	while ((packet = pcap_next(*pcap, &header)))
+	while ((packet = osdep_pcap_next(*pcap, &header)))
 		pcap_pkt_count++;
 
 	/* The pcap is reopened so it can be used as normal later. */
-	pcap_close(*pcap);
+	osdep_pcap_close(*pcap);
 	*pcap = NULL;
 	open_single_rx_pcap(pcap_q->name, pcap);
 
@@ -612,7 +612,7 @@ eth_dev_stop(struct rte_eth_dev *dev)
 
 	/* Special iface case. Single pcap is open and shared between tx/rx. */
 	if (internals->single_iface) {
-		pcap_close(pp->tx_pcap[0]);
+		osdep_pcap_close(pp->tx_pcap[0]);
 		pp->tx_pcap[0] = NULL;
 		pp->rx_pcap[0] = NULL;
 		goto status_down;
@@ -620,19 +620,19 @@ eth_dev_stop(struct rte_eth_dev *dev)
 
 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
 		if (pp->tx_dumper[i] != NULL) {
-			pcap_dump_close(pp->tx_dumper[i]);
+			osdep_pcap_dump_close(pp->tx_dumper[i]);
 			pp->tx_dumper[i] = NULL;
 		}
 
 		if (pp->tx_pcap[i] != NULL) {
-			pcap_close(pp->tx_pcap[i]);
+			osdep_pcap_close(pp->tx_pcap[i]);
 			pp->tx_pcap[i] = NULL;
 		}
 	}
 
 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		if (pp->rx_pcap[i] != NULL) {
-			pcap_close(pp->rx_pcap[i]);
+			osdep_pcap_close(pp->rx_pcap[i]);
 			pp->rx_pcap[i] = NULL;
 		}
 	}
@@ -804,11 +804,11 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (internals->infinite_rx) {
 		struct pmd_process_private *pp;
-		char ring_name[NAME_MAX];
+		char ring_name[RTE_RING_NAMESIZE];
 		static uint32_t ring_number;
 		uint64_t pcap_pkt_count = 0;
 		struct rte_mbuf *bufs[1];
-		pcap_t **pcap;
+		osdep_pcap **pcap;
 
 		pp = rte_eth_devices[pcap_q->port_id].process_private;
 		pcap = &pp->rx_pcap[pcap_q->queue_id];
@@ -932,7 +932,7 @@ static const struct eth_dev_ops ops = {
 
 static int
 add_queue(struct pmd_devargs *pmd, const char *name, const char *type,
-		pcap_t *pcap, pcap_dumper_t *dumper)
+		osdep_pcap *pcap, osdep_pcap_dumper *dumper)
 {
 	if (pmd->num_of_queue >= RTE_PMD_PCAP_MAX_QUEUES)
 		return -1;
@@ -955,13 +955,13 @@ open_rx_pcap(const char *key, const char *value, void *extra_args)
 {
 	const char *pcap_filename = value;
 	struct pmd_devargs *rx = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_rx_pcap(pcap_filename, &pcap) < 0)
 		return -1;
 
 	if (add_queue(rx, pcap_filename, key, pcap, NULL) < 0) {
-		pcap_close(pcap);
+		osdep_pcap_close(pcap);
 		return -1;
 	}
 
@@ -977,13 +977,13 @@ open_tx_pcap(const char *key, const char *value, void *extra_args)
 {
 	const char *pcap_filename = value;
 	struct pmd_devargs *dumpers = extra_args;
-	pcap_dumper_t *dumper;
+	osdep_pcap_dumper *dumper;
 
 	if (open_single_tx_pcap(pcap_filename, &dumper) < 0)
 		return -1;
 
 	if (add_queue(dumpers, pcap_filename, key, NULL, dumper) < 0) {
-		pcap_dump_close(dumper);
+		osdep_pcap_dump_close(dumper);
 		return -1;
 	}
 
@@ -998,7 +998,7 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
 {
 	const char *iface = value;
 	struct pmd_devargs *tx = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_iface(iface, &pcap) < 0)
 		return -1;
@@ -1011,13 +1011,14 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
 }
 
 static inline int
-set_iface_direction(const char *iface, pcap_t *pcap,
-		pcap_direction_t direction)
+set_iface_direction(const char *iface, osdep_pcap *pcap,
+		enum osdep_pcap_direction direction)
 {
-	const char *direction_str = (direction == PCAP_D_IN) ? "IN" : "OUT";
-	if (pcap_setdirection(pcap, direction) < 0) {
+	const char *direction_str =
+		(direction == OSDEP_PCAP_D_IN) ? "IN" : "OUT";
+	if (osdep_pcap_setdirection(pcap, direction) < 0) {
 		PMD_LOG(ERR, "Setting %s pcap direction %s failed - %s\n",
-				iface, direction_str, pcap_geterr(pcap));
+				iface, direction_str, osdep_pcap_geterr(pcap));
 		return -1;
 	}
 	PMD_LOG(INFO, "Setting %s pcap direction %s\n",
@@ -1030,12 +1031,12 @@ open_iface(const char *key, const char *value, void *extra_args)
 {
 	const char *iface = value;
 	struct pmd_devargs *pmd = extra_args;
-	pcap_t *pcap = NULL;
+	osdep_pcap *pcap = NULL;
 
 	if (open_single_iface(iface, &pcap) < 0)
 		return -1;
 	if (add_queue(pmd, iface, key, pcap, NULL) < 0) {
-		pcap_close(pcap);
+		osdep_pcap_close(pcap);
 		return -1;
 	}
 
@@ -1057,7 +1058,7 @@ open_rx_iface(const char *key, const char *value, void *extra_args)
 
 		set_iface_direction(pmd->queue[qid].name,
 				pmd->queue[qid].pcap,
-				PCAP_D_IN);
+				OSDEP_PCAP_D_IN);
 	}
 
 	return 0;
@@ -1311,7 +1312,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	name = rte_vdev_device_name(dev);
 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
 
-	gettimeofday(&start_time, NULL);
+	rte_time_get_us(&start_time);
 	start_cycles = rte_get_timer_cycles();
 	hz = rte_get_timer_hz();
 
diff --git a/drivers/net/pcap/pcap_osdep.c b/drivers/net/pcap/pcap_osdep.c
new file mode 100644
index 000000000..5cac9bb89
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.c
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <pcap.h>
+
+#include <rte_common.h>
+
+#include "pcap_osdep.h"
+
+static inline void
+to_osdep_header(const struct pcap_pkthdr *in, struct osdep_pcap_pkthdr *out)
+{
+	out->ts.sec = in->ts.tv_sec;
+	out->ts.usec = in->ts.tv_usec;
+	out->caplen = in->caplen;
+	out->len = in->len;
+}
+
+static inline void
+to_pcap_header(const struct osdep_pcap_pkthdr *in, struct pcap_pkthdr *out)
+{
+	out->ts.tv_sec = in->ts.sec;
+	out->ts.tv_usec = in->ts.usec;
+	out->caplen = in->caplen;
+	out->len = in->len;
+}
+
+osdep_pcap *
+osdep_pcap_open_live(const char *device, int snaplen,
+	int promisc, int to_ms, char *errbuf)
+{
+	RTE_BUILD_BUG_ON(OSDEP_PCAP_ERRBUF_SIZE != PCAP_ERRBUF_SIZE);
+
+	return (osdep_pcap *)pcap_open_live(device, snaplen, promisc, to_ms,
+		errbuf);
+}
+
+osdep_pcap *
+osdep_pcap_open_offline(const char *fname, char *errbuf)
+{
+	return (osdep_pcap *)pcap_open_offline(fname, errbuf);
+}
+
+osdep_pcap *
+osdep_pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+	unsigned int precision)
+{
+	RTE_BUILD_BUG_ON(OSDEP_DLT_EN10MB != DLT_EN10MB);
+	RTE_BUILD_BUG_ON(OSDEP_PCAP_TSTAMP_PRECISION_NANO !=
+			PCAP_TSTAMP_PRECISION_NANO);
+
+	return (osdep_pcap *)pcap_open_dead_with_tstamp_precision(linktype,
+		snaplen, precision);
+}
+
+const uint8_t *
+osdep_pcap_next(osdep_pcap *pcap, struct osdep_pcap_pkthdr *header)
+{
+	const uint8_t *data;
+	struct pcap_pkthdr pkthdr;
+
+	data = pcap_next((pcap_t *)pcap, &pkthdr);
+	to_osdep_header(&pkthdr, header);
+	return data;
+}
+
+int
+osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size)
+{
+	return pcap_sendpacket((pcap_t *)pcap, buf, size);
+}
+
+void
+osdep_pcap_close(osdep_pcap *pcap)
+{
+	pcap_close((pcap_t *)pcap);
+}
+
+osdep_pcap_dumper *
+osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname)
+{
+	return (osdep_pcap_dumper *)pcap_dump_open((pcap_t *)pcap, fname);
+}
+
+void
+osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header,
+	const uint8_t *sp)
+{
+	struct pcap_pkthdr pkthdr;
+
+	to_pcap_header(header, &pkthdr);
+	pcap_dump(user, &pkthdr, sp);
+}
+
+int
+osdep_pcap_dump_flush(osdep_pcap_dumper *p)
+{
+	return pcap_dump_flush((pcap_dumper_t *)p);
+}
+
+void
+osdep_pcap_dump_close(osdep_pcap_dumper *p)
+{
+	pcap_dump_close((pcap_dumper_t *)p);
+}
+
+int
+osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir)
+{
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_INOUT != (int)PCAP_D_INOUT);
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_IN != (int)PCAP_D_IN);
+	RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_OUT != (int)PCAP_D_OUT);
+
+	return pcap_setdirection((pcap_t *)pcap, (pcap_direction_t)dir);
+}
+
+const char *
+osdep_pcap_geterr(osdep_pcap *pcap)
+{
+	return pcap_geterr((pcap_t *)pcap);
+}
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 46810d86f..bd00b728a 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -6,6 +6,7 @@
 #define _RTE_PCAP_OSDEP_
 
 #include <rte_ether.h>
+#include <rte_time.h>
 
 /*
  * Interface manipulation is always OS-specific.
@@ -14,4 +15,53 @@
 int osdep_iface_index_get(const char *name);
 int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
 
+/*
+ * On Windows, libpcap (npcap or WinPcap) exposes Win32 API which clashes
+ * with some DPDK constructs. Trivial libpcap wrappers with "osdep_" prefix
+ * are provided to isolate PMD code from Win32 API.
+ */
+
+#define OSDEP_DLT_EN10MB 1
+
+#define OSDEP_PCAP_ERRBUF_SIZE 256
+
+#define OSDEP_PCAP_TSTAMP_PRECISION_NANO 1
+
+/** Handle for an open packet capture. */
+typedef struct osdep_pcap_type osdep_pcap;
+
+/** Handle for an open packet dump. */
+typedef struct osdep_pcap_dumper_type osdep_pcap_dumper;
+
+struct osdep_pcap_pkthdr {
+	struct rte_time_us ts;
+	uint32_t caplen;
+	uint32_t len;
+};
+
+enum osdep_pcap_direction {
+	OSDEP_PCAP_D_INOUT = 0,
+	OSDEP_PCAP_D_IN,
+	OSDEP_PCAP_D_OUT
+};
+
+osdep_pcap *osdep_pcap_open_live(const char *device, int snaplen,
+	int promisc, int to_ms, char *errbuf);
+osdep_pcap *osdep_pcap_open_offline(const char *fname, char *errbuf);
+osdep_pcap *osdep_pcap_open_dead_with_tstamp_precision(int linktype,
+	int snaplen, unsigned int precision);
+const uint8_t *osdep_pcap_next(osdep_pcap *pcap,
+	struct osdep_pcap_pkthdr *header);
+int osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size);
+void osdep_pcap_close(osdep_pcap *pcap);
+
+osdep_pcap_dumper *osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname);
+void osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header,
+	const uint8_t *sp);
+int osdep_pcap_dump_flush(osdep_pcap_dumper *p);
+void osdep_pcap_dump_close(osdep_pcap_dumper *p);
+
+int osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir);
+const char *osdep_pcap_geterr(osdep_pcap *pcap);
+
 #endif
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
                     ` (3 preceding siblings ...)
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-02-25 15:02     ` Ferruh Yigit
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 6/6] net/pcap: build " Dmitry Kozlyuk
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
  6 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Bruce Richardson

WinPcap or Npcap, can be installed anywhere.
Add a Meson option to specify SDK path.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 config/meson.build | 21 ++++++++++++++++++---
 meson_options.txt  |  6 ++++--
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/config/meson.build b/config/meson.build
index 3cf560b8a..6aae8276c 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -178,9 +178,24 @@ if not pcap_dep.found()
 	# pcap got a pkg-config file only in 1.9.0
 	pcap_dep = cc.find_library('pcap', required: false)
 endif
-if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
-	dpdk_conf.set('RTE_PORT_PCAP', 1)
-	dpdk_extra_ldflags += '-lpcap'
+if is_windows
+	# npcap SDK can be installed anywhere
+	pcap_sdk = get_option('pcap_sdk')
+	if pcap_sdk != ''
+		pcap_ldflags = ['-L@0@/Lib/x64'.format(pcap_sdk), '-lwpcap']
+		pcap_dep = declare_dependency(
+			compile_args: ['-I@0@/Include'.format(pcap_sdk)],
+			link_args: pcap_ldflags)
+	endif
+	if pcap_dep.found()
+		dpdk_conf.set('RTE_PORT_PCAP', 1)
+		dpdk_extra_ldflags += pcap_ldflags
+	endif
+else
+	if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
+		dpdk_conf.set('RTE_PORT_PCAP', 1)
+		dpdk_extra_ldflags += '-lpcap'
+	endif
 endif
 
 # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
diff --git a/meson_options.txt b/meson_options.txt
index 6eff62e47..d74146d3a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,6 +10,8 @@ option('enable_docs', type: 'boolean', value: false,
 	description: 'build documentation')
 option('enable_kmods', type: 'boolean', value: false,
 	description: 'build kernel modules')
+option('enable_trace_fp', type: 'boolean', value: false,
+	description: 'enable fast path trace points.')
 option('examples', type: 'string', value: '',
 	description: 'Comma-separated list of examples to build by default')
 option('flexran_sdk', type: 'string', value: '',
@@ -28,8 +30,8 @@ option('max_lcores', type: 'integer', value: 128,
 	description: 'maximum number of cores/threads supported by EAL')
 option('max_numa_nodes', type: 'integer', value: 32,
 	description: 'maximum number of NUMA nodes supported by EAL')
-option('enable_trace_fp', type: 'boolean', value: false,
-	description: 'enable fast path trace points.')
+option('pcap_sdk', type: 'string', value: '',
+	description: 'Path to libpcap SDK used on Windows')
 option('tests', type: 'boolean', value: true,
 	description: 'build unit tests')
 option('use_hpet', type: 'boolean', value: false,
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v2 6/6] net/pcap: build on Windows
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
                     ` (4 preceding siblings ...)
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
@ 2021-02-14  2:16   ` Dmitry Kozlyuk
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
  6 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-14  2:16 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff, Mike Wells, Dmitry Kozlyuk, Ferruh Yigit

Implement OS-dependent functions and enable PMD build on Windows.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 drivers/net/pcap/meson.build          |  11 ++-
 drivers/net/pcap/pcap_ethdev.c        |   4 -
 drivers/net/pcap/pcap_osdep.h         |   5 ++
 drivers/net/pcap/pcap_osdep_windows.c | 118 ++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 9ab95ec3e..614a4e340 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -1,19 +1,18 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-if is_windows
-	build = false
-	reason = 'not supported on Windows'
-	subdir_done()
-endif
-
 if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
+
 sources = files(
 	'pcap_ethdev.c',
 	'pcap_osdep.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
+
 ext_deps += pcap_dep
+if is_windows
+	ext_deps += cc.find_library('iphlpapi', required: true)
+endif
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 6461213e0..142533c6e 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -127,10 +127,6 @@ static struct rte_eth_link pmd_link = {
 
 RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
-#define PMD_LOG(level, fmt, args...) \
-	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
-		"%s(): " fmt "\n", __func__, ##args)
-
 static int
 eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf,
 		const uint8_t *data, uint16_t data_len)
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index bd00b728a..f7c311ef8 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -8,6 +8,11 @@
 #include <rte_ether.h>
 #include <rte_time.h>
 
+#define PMD_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
+		"%s(): " fmt "\n", __func__, ##args)
+extern int eth_pcap_logtype;
+
 /*
  * Interface manipulation is always OS-specific.
  */
diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
new file mode 100644
index 000000000..d6557ff73
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_windows.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
+
+#include "pcap_osdep.h"
+
+/*
+ * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
+ * Return NULL if "{GUID}" part is not found.
+ */
+static const char *
+iface_guid(const char *name)
+{
+	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
+
+	const char *ob, *cb;
+
+	ob = strchr(name, '{');
+	if (ob == NULL)
+		return NULL;
+
+	cb = strchr(ob, '}');
+	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
+		return NULL;
+
+	return ob;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
+ * Try to convert, fall back to original device name.
+ */
+int
+osdep_iface_index_get(const char *device_name)
+{
+	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
+	const char *guid;
+	ULONG index;
+	DWORD ret;
+
+	guid = iface_guid(device_name);
+	if (guid != NULL)
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"\\DEVICE\\TCPIP_%s", guid);
+	else
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"%s", device_name);
+
+	ret = GetAdapterIndex(adapter_name, &index);
+	if (ret != NO_ERROR) {
+		PMD_LOG(ERR, "GetAdapterIndex() = %lu\n", ret);
+		return -1;
+	}
+
+	return index;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdaptersAddresses() returns names in "{GUID}" form.
+ * Try to extract GUID from device name, fall back to original device name.
+ */
+int
+osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
+{
+	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
+	ULONG size, sys_ret;
+	const char *adapter_name;
+	int ret = -1;
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
+	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
+			sys_ret, ERROR_BUFFER_OVERFLOW);
+		return -1;
+	}
+
+	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
+	if (info == NULL) {
+		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
+		return -1;
+	}
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
+	if (sys_ret != ERROR_SUCCESS) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
+		free(info);
+		return -1;
+	}
+
+	adapter_name = iface_guid(device_name);
+	if (adapter_name == NULL)
+		adapter_name = device_name;
+
+	for (cur = info; cur != NULL; cur = cur->Next) {
+		if (strcmp(cur->AdapterName, adapter_name) == 0) {
+			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
+				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
+					RTE_ETHER_ADDR_LEN,
+					cur->PhysicalAddressLength);
+				return -1;
+			}
+
+			memcpy(mac->addr_bytes, cur->PhysicalAddress,
+				RTE_ETHER_ADDR_LEN);
+			ret = 0;
+			break;
+		}
+	}
+
+	free(info);
+	return ret;
+}
-- 
2.29.2


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string Dmitry Kozlyuk
@ 2021-02-25 14:45     ` Ferruh Yigit
  2021-03-02 11:48       ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-02-25 14:45 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells, stable

On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> Use PRIu32 for uint32_t (found by -Wformat with Clang on Windows).
> 
> Fixes: a3f5252e5cbd ("net/pcap: enable infinitely Rx a pcap file")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-02-25 14:51     ` Ferruh Yigit
  2021-02-25 16:05       ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-02-25 14:51 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells

On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> PCAP PMD queries interface information differently for Linux and
> FreeBSD, OS-specific code is guarded by #ifdef. In preparation to add
> Windows-specific part and libpcap wrapper, extract OS-independent
> interface and move implementations to separate files. Rename
> rte_eth_pcap.c to pcap_ethdev.c for consistency with the rest of DPDK.
> 
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

<...>

> +int
> +osdep_iface_index_get(const char *name)
> +{
> +	return if_nametoindex(name);
> +}


The 'osdep_iface_index_get' wrapper is not required for this patch and can be 
done in patch 6/6, but OK to have here to make the switch clear.


Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
@ 2021-02-25 14:59     ` Ferruh Yigit
  2021-02-25 19:04       ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-02-25 14:59 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells

On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> libpcap headers can expose OS headers. On Windows, system networking
> headers are incompatible with DPDK ones, causing multiple name clashes.
> API of libpcap itself involves a non-standard u_char type.
> 
> Add a limited set of trivial libpcap wrappers, so that libpcap headers
> are not included directly by OS-independent PMD code. Use EAL types and
> functions for time instead of POSIX ones.
> 

It is not nice to duplicate the pcap struct and macros and have dpdk versions of 
them, it may have long term maintanance issues too.

What are the clashes in question?

If they are macros, can the issue solved after undefining some after including 
'pcap.h'?

And at the end of the day, shouldn't we need to resolve these clashes globally 
since we may hit same things with other PMDs or libraries as we enable them. I 
am for a global solution instead of these changes in pcap, but I guess question 
is how possible that global solution is..

> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

<...>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
@ 2021-02-25 15:02     ` Ferruh Yigit
  2021-02-25 16:04       ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-02-25 15:02 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells, Bruce Richardson

On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> WinPcap or Npcap, can be installed anywhere.
> Add a Meson option to specify SDK path.
> 

I am not sure if it is OK to add a meson option for this, can't we use the 
default path?

And does this mean we will need to add an option for each dependent library in 
Windows? If not, why pcap is special?

> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

<...>


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-25 15:02     ` Ferruh Yigit
@ 2021-02-25 16:04       ` Dmitry Kozlyuk
  2021-02-25 16:33         ` Bruce Richardson
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-25 16:04 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Tyler Retzlaff, Mike Wells, Bruce Richardson

2021-02-25 15:02, Ferruh Yigit:
> On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> > WinPcap or Npcap, can be installed anywhere.
> > Add a Meson option to specify SDK path.
> >   
> 
> I am not sure if it is OK to add a meson option for this, can't we use the 
> default path?
> 
> And does this mean we will need to add an option for each dependent library in 
> Windows? If not, why pcap is special?

There are some meson options for SDK paths already. Are they exceptions?

IMO, explicit specification is better because it allows switching
dependency versions and library distributions.
I understand that consensus it to keep build matrix size at minimum, but
options to specify SDK path don't change the number of variants what can be
found.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files
  2021-02-25 14:51     ` Ferruh Yigit
@ 2021-02-25 16:05       ` Dmitry Kozlyuk
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-25 16:05 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Tyler Retzlaff, Mike Wells

2021-02-25 14:51, Ferruh Yigit:
> On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> > PCAP PMD queries interface information differently for Linux and
> > FreeBSD, OS-specific code is guarded by #ifdef. In preparation to add
> > Windows-specific part and libpcap wrapper, extract OS-independent
> > interface and move implementations to separate files. Rename
> > rte_eth_pcap.c to pcap_ethdev.c for consistency with the rest of DPDK.
> > 
> > Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>  
> 
> <...>
> 
> > +int
> > +osdep_iface_index_get(const char *name)
> > +{
> > +	return if_nametoindex(name);
> > +}  
> 
> 
> The 'osdep_iface_index_get' wrapper is not required for this patch and can be 
> done in patch 6/6, but OK to have here to make the switch clear.

Yes, it was my intention to keep Windows patches separate.


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-25 16:04       ` Dmitry Kozlyuk
@ 2021-02-25 16:33         ` Bruce Richardson
  2021-02-25 17:42           ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Bruce Richardson @ 2021-02-25 16:33 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells

On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
> 2021-02-25 15:02, Ferruh Yigit:
> > On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> > > WinPcap or Npcap, can be installed anywhere.
> > > Add a Meson option to specify SDK path.
> > >   
> > 
> > I am not sure if it is OK to add a meson option for this, can't we use the 
> > default path?
> > 
> > And does this mean we will need to add an option for each dependent library in 
> > Windows? If not, why pcap is special?
> 
> There are some meson options for SDK paths already. Are they exceptions?
> 
Right now, yes, they are exceptions, but there is work underway to remove
them and just replace them with use of pkg-config. Is there some automatic
path discovery mechanism on windows, similar to pkg-config, that can be
used rather than having to add explicit dependency paths?

/bruce

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-25 16:33         ` Bruce Richardson
@ 2021-02-25 17:42           ` Dmitry Kozlyuk
  2021-03-16  9:16             ` Thomas Monjalon
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-25 17:42 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells

2021-02-25 16:33, Bruce Richardson:
> On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
> > 2021-02-25 15:02, Ferruh Yigit:  
> > > On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:  
> > > > WinPcap or Npcap, can be installed anywhere.
> > > > Add a Meson option to specify SDK path.
> > > >     
> > > 
> > > I am not sure if it is OK to add a meson option for this, can't we use the 
> > > default path?
> > > 
> > > And does this mean we will need to add an option for each dependent library in 
> > > Windows? If not, why pcap is special?  
> > 
> > There are some meson options for SDK paths already. Are they exceptions?
> >   
> Right now, yes, they are exceptions, but there is work underway to remove
> them and just replace them with use of pkg-config. Is there some automatic
> path discovery mechanism on windows, similar to pkg-config, that can be
> used rather than having to add explicit dependency paths?

pkg-config itself works on Windows if installed and given a PKG_CONFIG_PATH.

Npcap doesn't provide a .pc file, despite libpcap commit 4f6b2b99 having it.
Another quirk is that library is named libpcap.a/wpcap.lib on Unix/Windows.
I can just handle the name difference and assume it's in the search path.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-25 14:59     ` Ferruh Yigit
@ 2021-02-25 19:04       ` Dmitry Kozlyuk
  2021-02-25 20:31         ` Nick Connolly
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-25 19:04 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Nick Connolly, Jie Zhou

2021-02-25 14:59, Ferruh Yigit:
> On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
> > libpcap headers can expose OS headers. On Windows, system networking
> > headers are incompatible with DPDK ones, causing multiple name clashes.
> > API of libpcap itself involves a non-standard u_char type.
> > 
> > Add a limited set of trivial libpcap wrappers, so that libpcap headers
> > are not included directly by OS-independent PMD code. Use EAL types and
> > functions for time instead of POSIX ones.
> >   
> 
> It is not nice to duplicate the pcap struct and macros and have dpdk versions of 
> them, it may have long term maintanance issues too.
> 
> What are the clashes in question?
> 
> If they are macros, can the issue solved after undefining some after including 
> 'pcap.h'?
> 
> And at the end of the day, shouldn't we need to resolve these clashes globally 
> since we may hit same things with other PMDs or libraries as we enable them. I 
> am for a global solution instead of these changes in pcap, but I guess question 
> is how possible that global solution is..

Your comment made me revise Windows EAL networking shims. Surprisingly, if
changed to expose Windows networking headers (specifically, <ws2tcpip.h>) with
some additions (but no hacks), they create no issues to any existing code.

The only workaround remaining is `#undef s_addr` in <rte_ether.h>.

So maybe this commit can be dropped, if Windows EAL networking headers be
reworked in the following way:

	#if defined min
	#define USER_EXPLICITLY_WANTS_WINDOWS_H
	#endif

	#include <ws2tcpip.h>

	/* hide definitions that break portable code,
	 * e.g. it had to be done once already for i40e
	 */
	#ifndef USER_EXPLICITLY_WANTS_WINDOWS_H
	#undef min, max, ...
	#endif

	#define what's missing from Windows headers, e.g. IPPROTO_SCTP

+ Windows maintainers, Nick Connolly, and Jie Zhou to discuss.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-25 19:04       ` Dmitry Kozlyuk
@ 2021-02-25 20:31         ` Nick Connolly
  2021-02-25 23:10           ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Nick Connolly @ 2021-02-25 20:31 UTC (permalink / raw)
  To: Dmitry Kozlyuk, Ferruh Yigit
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Jie Zhou


> Your comment made me revise Windows EAL networking shims. Surprisingly, if
> changed to expose Windows networking headers (specifically, <ws2tcpip.h>) with
> some additions (but no hacks), they create no issues to any existing code.
>
> The only workaround remaining is `#undef s_addr` in <rte_ether.h>.
>
> So maybe this commit can be dropped, if Windows EAL networking headers be
> reworked in the following way:
>
> 	#if defined min
> 	#define USER_EXPLICITLY_WANTS_WINDOWS_H
> 	#endif
>
> 	#include <ws2tcpip.h>
>
> 	/* hide definitions that break portable code,
> 	 * e.g. it had to be done once already for i40e
> 	 */
> 	#ifndef USER_EXPLICITLY_WANTS_WINDOWS_H
> 	#undef min, max, ...
> 	#endif
>
> 	#define what's missing from Windows headers, e.g. IPPROTO_SCTP
>
> + Windows maintainers, Nick Connolly, and Jie Zhou to discuss.
In my opinion, there are long term maintenance issues either way round.

Wrapping the system headers hides the details and keeps the code 'clean',
but has to work with multiple compiler environments and versions of the
headers - not always straightforward.  Wrapping libpcap involves code
changes that need to be maintained.

For SPDK, changing the code wasn't really an option, so I had to go with
wrapping the headers. It's worked out ok so far. To make it a bit cleaner
I turned off as much as possible from Windows.h with #define NO*.
Supporting both clang and MinGW caused a few issues (e.g. MinGW has
mswsock.h), but they are solvable.

./inc/sys/socket.h and ./inc/wpdk/windows.h in https://github.com/wpdp/wpdk
show an example of what might need wrapping in the general case.

Regards,
Nick

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-25 20:31         ` Nick Connolly
@ 2021-02-25 23:10           ` Dmitry Kozlyuk
  2021-03-01 21:43             ` Nick Connolly
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-02-25 23:10 UTC (permalink / raw)
  To: Nick Connolly
  Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-02-25 20:31, Nick Connolly:
> > Your comment made me revise Windows EAL networking shims. Surprisingly, if
> > changed to expose Windows networking headers (specifically, <ws2tcpip.h>) with
> > some additions (but no hacks), they create no issues to any existing code.
> >
> > The only workaround remaining is `#undef s_addr` in <rte_ether.h>.
> >
> > So maybe this commit can be dropped, if Windows EAL networking headers be
> > reworked in the following way:
> >
> > 	#if defined min
> > 	#define USER_EXPLICITLY_WANTS_WINDOWS_H
> > 	#endif
> >
> > 	#include <ws2tcpip.h>
> >
> > 	/* hide definitions that break portable code,
> > 	 * e.g. it had to be done once already for i40e
> > 	 */
> > 	#ifndef USER_EXPLICITLY_WANTS_WINDOWS_H
> > 	#undef min, max, ...
> > 	#endif
> >
> > 	#define what's missing from Windows headers, e.g. IPPROTO_SCTP
> >
> > + Windows maintainers, Nick Connolly, and Jie Zhou to discuss.  
> In my opinion, there are long term maintenance issues either way round.
> 
> Wrapping the system headers hides the details and keeps the code 'clean',
> but has to work with multiple compiler environments and versions of the
> headers - not always straightforward. 

You're probably right.
We had an exchange with Tyler, let me quote:

[DmitryK]
> I'm pretty sure no DPDK header really needs anything beyond standard C,
> but one exception: intrinsic functions for vector instructions.
> Struct in_addr? An oversight, there's rte_ether_addr, should be rte_ip_addr.

Here's a complete list of offending files included from public headers,
with comments on usage:

POSIX

    netinet/in.h
    netinet/ip6.h
    netinet/ip.h
	cmdline:  struct in_addr, struct in6_addr, 6 constants
	net:      ditto
	security: ditto
    pthread.h
	eal:	not used
	ethdev:	pthread_mutex_t flow_ops_mutex;
    sched.h
	eal:       cpu_set_t
	telemetry: rte_cpuset_t (not used?)
    sys/types.h
	ehtdev:   not needed (FILE?)
	net:      not needed
	mbuf:     ditto
	pci:      ditto
	security: ditto
	sched:    ditto

Unix

    sys/queue.h
	(acl, eal, hash, lpm, mempool, pci, ring, table,
	 bus/{fslmc,pci,vdev,vmbus}, net/{memif,tap})
		multiprocessing

Thread-related stuff will go away as rte_thread.h expands.
Network headers are not much needed, as you can see above.
Other headers mostly not needed or can be replaced with standard ones.

Replacing `in_addr` with and `rte_ip_addr` will break API, but not ABI,
because it's essentially the same thing. We can define new types
conditionally, as it was done for struct cmdline, if need be.

Complete removal of non-standard dependencies in headers is within a grasp.
Then we can remove shims and include whatever needed.
Thoughts?

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-02-25 23:10           ` Dmitry Kozlyuk
@ 2021-03-01 21:43             ` Nick Connolly
  2021-03-01 23:05               ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Nick Connolly @ 2021-03-01 21:43 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou


> Complete removal of non-standard dependencies in headers is within a grasp.
> Then we can remove shims and include whatever needed.
> Thoughts?
Sounds good. A couple of 'gotchas' that I've come across (but may not be 
an issue for DPDK):

  * Memory allocation / free that spans a dll boundary (see earlier email).
  * posix_memalign is unfortunately specified as using free(), so we'll
    either have to modify the calls to rte_posix_memalign /
    rte_free_memalign (which means code analysis to find which free
    calls need changing), or wrapper free() to distinguish the two types
    of memory somehow. I 'solved' this for SPDK by using posix_memalign
    for everything and I have a vague recollection that the mingw libc
    does something similar.
  * Sockets are unfortunately specified as using close(). This is
    probably easy to address by rte_ wrapping all socket calls.

Regards,
Nick

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH 1/6] eal: add internal API for current time
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 1/6] eal: add internal API for current time Dmitry Kozlyuk
@ 2021-03-01 22:31   ` Nick Connolly
  2021-03-01 22:36     ` Nick Connolly
  0 siblings, 1 reply; 67+ messages in thread
From: Nick Connolly @ 2021-03-01 22:31 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev
  Cc: Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman

Calculation of usec value is incorrect - 'ticks' is not adjusted for 
epoch, whereas 'sec' has been, also subtraction has mismatched units - 
ticks in 100ns and sec * USEC_PER_SEC in usecs.


On 14/02/2021 01:20, Dmitry Kozlyuk wrote:
> +	GetSystemTimePreciseAsFileTime(&ft);
> +	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
> +	sec = (ticks - EPOCH) / (TICKS_PER_USEC * USEC_PER_SEC);
> +	now->sec = sec;
> +	now->usec = (ticks - sec * USEC_PER_SEC) / TICKS_PER_USEC;


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH 2/6] net/pcap: fix format string
  2021-02-14  1:20 ` [dpdk-dev] [PATCH 2/6] net/pcap: fix format string Dmitry Kozlyuk
@ 2021-03-01 22:33   ` Nick Connolly
  0 siblings, 0 replies; 67+ messages in thread
From: Nick Connolly @ 2021-03-01 22:33 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells, stable, Ferruh Yigit


> Use PRIu32 for uint32_t (found by -Wformat with Clang on Windows).
>
Acked-by: Nick Connolly <nick.connolly@mayadata.io>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH 1/6] eal: add internal API for current time
  2021-03-01 22:31   ` Nick Connolly
@ 2021-03-01 22:36     ` Nick Connolly
  0 siblings, 0 replies; 67+ messages in thread
From: Nick Connolly @ 2021-03-01 22:36 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev
  Cc: Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman


> Calculation of usec value is incorrect - 'ticks' is not adjusted for 
> epoch, whereas 'sec' has been, also subtraction has mismatched units - 
> ticks in 100ns and sec * USEC_PER_SEC in usecs.

Ignore - fixed in later version which I hadn't spotted.


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
@ 2021-03-01 22:39     ` Nick Connolly
  2021-03-05 17:50     ` Jie Zhou
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 67+ messages in thread
From: Nick Connolly @ 2021-03-01 22:39 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev
  Cc: Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman


> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.
>
Acked-by: Nick Connolly <nick.connolly@mayadata.io>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-01 21:43             ` Nick Connolly
@ 2021-03-01 23:05               ` Dmitry Kozlyuk
  2021-03-01 23:23                 ` Dmitry Kozlyuk
  2021-03-02 11:22                 ` Nick Connolly
  0 siblings, 2 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-01 23:05 UTC (permalink / raw)
  To: Nick Connolly
  Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-03-01 21:43, Nick Connolly:
> > Complete removal of non-standard dependencies in headers is within a grasp.
> > Then we can remove shims and include whatever needed.
> > Thoughts?
> Sounds good. A couple of 'gotchas' that I've come across (but may not be 
> an issue for DPDK):
> 
>   * Memory allocation / free that spans a dll boundary (see earlier email).

Not sure which email you mean, could you give a link?

>   * posix_memalign is unfortunately specified as using free(), so we'll
>     either have to modify the calls to rte_posix_memalign /
>     rte_free_memalign (which means code analysis to find which free
>     calls need changing), or wrapper free() to distinguish the two types
>     of memory somehow. I 'solved' this for SPDK by using posix_memalign
>     for everything and I have a vague recollection that the mingw libc
>     does something similar.

Is posix_memalign() used more extensively in SPDK? In DPDK, it's 2 PMDs:
  * mlx5 PMD uses _aligned_malloc/_aligned_free on Windows;
  * dpaax (PMD family) uses posix_memalign() to allocate pages.
There are "malloc" and "alloc_size" attributes that can help code analysis.

>   * Sockets are unfortunately specified as using close(). This is
>     probably easy to address by rte_ wrapping all socket calls.

Which public DPDK APIs operate on sockets?
I don't like the idea of wrapping APIs like sockets or files.
(Yes, we're discussing libpcap API wrappers in this thread, but we already
agreed they are a mistake and they were internal in the first place.)

I drafted what I was talking about: adding address types and removing shims:

* librte_net/rte_ip.h then includes <netinet/ip.h> or <ws2tcpip.h>
  conditionally for AF_xxx, IPPROTO_xxx, and a few other constants.
  That's probably OK, there are similar places for Linux/FreeBSD differences,
  e.g. in <rte_endian.h>.

* Some IPPROTO_xxx constants are missing on Windows, so rte_ip.h has to
  provide them. I hope Mirosoft will add them to system headers one day.

* It affects cmdline (mostly), ethdev, security, crypto/dpaax.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-01 23:05               ` Dmitry Kozlyuk
@ 2021-03-01 23:23                 ` Dmitry Kozlyuk
  2021-03-02 11:22                 ` Nick Connolly
  1 sibling, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-01 23:23 UTC (permalink / raw)
  To: Nick Connolly
  Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-03-02 02:05, Dmitry Kozlyuk:
> 2021-03-01 21:43, Nick Connolly:
> > > Complete removal of non-standard dependencies in headers is within a grasp.
> > > Then we can remove shims and include whatever needed.
> > > Thoughts?  
> > Sounds good. A couple of 'gotchas' that I've come across (but may not be 
> > an issue for DPDK):
> > 
> >   * Memory allocation / free that spans a dll boundary (see earlier email).  
> 
> Not sure which email you mean, could you give a link?

There it is:

	https://mails.dpdk.org/archives/dev/2021-February/200105.html

Yes, of course malloc/free shall be both on either library or caller site.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-01 23:05               ` Dmitry Kozlyuk
  2021-03-01 23:23                 ` Dmitry Kozlyuk
@ 2021-03-02 11:22                 ` Nick Connolly
  2021-03-03 16:32                   ` Dmitry Kozlyuk
  1 sibling, 1 reply; 67+ messages in thread
From: Nick Connolly @ 2021-03-02 11:22 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Ferruh Yigit, dev, Tyler Retzlaff, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou

> Is posix_memalign() used more extensively in SPDK? In DPDK, it's 2 PMDs:
Yes, there are about 80 references. A lot are in ISA-L where they are 
#defined to _aligned_malloc and can be ignored, but there still several 
in the rest of the code.


>>    * Sockets are unfortunately specified as using close(). This is
>>      probably easy to address by rte_ wrapping all socket calls.
> Which public DPDK APIs operate on sockets?
> I don't like the idea of wrapping APIs like sockets or files.
I'm not sure about use in public APIs - I'd hope none do. I was thinking 
about 'internal' use. The tricky issue here is that on Linux/FreeBSD 
socket() returns a small integer file descriptor whereas Windows returns 
a SOCKET type (which is a UINT_PTR and so larger than the 'int' that an 
fd occupies). In practice it looks as though SOCKET usually returns a 
small integer, but as far as I can see from the documentation it depends 
on the software stack that is in use. Even if it's a small integer, I 
don't think it has any correlation to the file descriptor table in the 
crt, which means that calls to read/write/close will all need to be 
handled so that they work.

> (Yes, we're discussing libpcap API wrappers in this thread, but we already
> agreed they are a mistake and they were internal in the first place.)
>
> I drafted what I was talking about: adding address types and removing shims:
>
> * librte_net/rte_ip.h then includes <netinet/ip.h> or <ws2tcpip.h>
>    conditionally for AF_xxx, IPPROTO_xxx, and a few other constants.
>    That's probably OK, there are similar places for Linux/FreeBSD differences,
>    e.g. in <rte_endian.h>.
>
> * Some IPPROTO_xxx constants are missing on Windows, so rte_ip.h has to
>    provide them. I hope Mirosoft will add them to system headers one day.
>
> * It affects cmdline (mostly), ethdev, security, crypto/dpaax.
Sounds good - well done!

Regards,
Nick


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [dpdk-stable] [PATCH v2 2/6] net/pcap: fix format string
  2021-02-25 14:45     ` Ferruh Yigit
@ 2021-03-02 11:48       ` Ferruh Yigit
  0 siblings, 0 replies; 67+ messages in thread
From: Ferruh Yigit @ 2021-03-02 11:48 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Tyler Retzlaff, Mike Wells, stable

On 2/25/2021 2:45 PM, Ferruh Yigit wrote:
> On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
>> Use PRIu32 for uint32_t (found by -Wformat with Clang on Windows).
>>
>> Fixes: a3f5252e5cbd ("net/pcap: enable infinitely Rx a pcap file")
>> Cc: stable@dpdk.org
>>
>> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> 
> Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>

This is trivial fix and not directly related to the patchset, let me merge it 
and get out of way, in next version you don't need to include this patch.

Applied to dpdk-next-net/main, thanks.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-02 11:22                 ` Nick Connolly
@ 2021-03-03 16:32                   ` Dmitry Kozlyuk
  2021-03-03 16:47                     ` Ferruh Yigit
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-03 16:32 UTC (permalink / raw)
  To: Nick Connolly, Ferruh Yigit
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-03-02 11:22, Nick Connolly:
> > Is posix_memalign() used more extensively in SPDK? In DPDK, it's 2 PMDs:  
> Yes, there are about 80 references. A lot are in ISA-L where they are 
> #defined to _aligned_malloc and can be ignored, but there still several 
> in the rest of the code.

I think portable code should try sticking to C11 aligned_malloc().
BTW, _aligned_malloc (with "_") only supports power-of-2 alignment.

There's a related passage in MSVC blog:

	Due to the nature of the Windows heap, aligned_alloc support is
	missing. The alternative is to use _aligned_malloc.

https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/

> >>    * Sockets are unfortunately specified as using close(). This is
> >>      probably easy to address by rte_ wrapping all socket calls.  
> > Which public DPDK APIs operate on sockets?
> > I don't like the idea of wrapping APIs like sockets or files.  
> I'm not sure about use in public APIs - I'd hope none do. I was thinking 
> about 'internal' use.

This is important (even more so for SPDK, I suspect), however, I'd like to
focus on public API first.

> > I drafted what I was talking about: adding address types and removing shims:
> >
> > * librte_net/rte_ip.h then includes <netinet/ip.h> or <ws2tcpip.h>
> >    conditionally for AF_xxx, IPPROTO_xxx, and a few other constants.
> >    That's probably OK, there are similar places for Linux/FreeBSD differences,
> >    e.g. in <rte_endian.h>.
> >
> > * Some IPPROTO_xxx constants are missing on Windows, so rte_ip.h has to
> >    provide them. I hope Mirosoft will add them to system headers one day.
> >
> > * It affects cmdline (mostly), ethdev, security, crypto/dpaax.  
> Sounds good - well done!

...or not :)

If we can't help including <ws2tcpip.h>/<netinet/ip.h> from public headers,
might as well use `struct in_addr`, just replace `#include <netinet/ip.h>`
with `#include <rte_ip.h>` everywhere.

The only remaining issue will be `s_addr` macro on Windows that conflicts with
`struct rte_ether_addr` field `s_addr`. I don't know a better solution than
renaming `s_addr` to `src_addr` in DPDK (OTOH, it will be consistent with
`struct rte_ipvX_hdr` field naming).

Ferruh, what do you think?

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-03 16:32                   ` Dmitry Kozlyuk
@ 2021-03-03 16:47                     ` Ferruh Yigit
  2021-03-03 18:19                       ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-03-03 16:47 UTC (permalink / raw)
  To: Dmitry Kozlyuk, Nick Connolly
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Jie Zhou

On 3/3/2021 4:32 PM, Dmitry Kozlyuk wrote:
> 2021-03-02 11:22, Nick Connolly:
>>> Is posix_memalign() used more extensively in SPDK? In DPDK, it's 2 PMDs:
>> Yes, there are about 80 references. A lot are in ISA-L where they are
>> #defined to _aligned_malloc and can be ignored, but there still several
>> in the rest of the code.
> 
> I think portable code should try sticking to C11 aligned_malloc().
> BTW, _aligned_malloc (with "_") only supports power-of-2 alignment.
> 
> There's a related passage in MSVC blog:
> 
> 	Due to the nature of the Windows heap, aligned_alloc support is
> 	missing. The alternative is to use _aligned_malloc.
> 
> https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/
> 
>>>>     * Sockets are unfortunately specified as using close(). This is
>>>>       probably easy to address by rte_ wrapping all socket calls.
>>> Which public DPDK APIs operate on sockets?
>>> I don't like the idea of wrapping APIs like sockets or files.
>> I'm not sure about use in public APIs - I'd hope none do. I was thinking
>> about 'internal' use.
> 
> This is important (even more so for SPDK, I suspect), however, I'd like to
> focus on public API first.
> 
>>> I drafted what I was talking about: adding address types and removing shims:
>>>
>>> * librte_net/rte_ip.h then includes <netinet/ip.h> or <ws2tcpip.h>
>>>     conditionally for AF_xxx, IPPROTO_xxx, and a few other constants.
>>>     That's probably OK, there are similar places for Linux/FreeBSD differences,
>>>     e.g. in <rte_endian.h>.
>>>
>>> * Some IPPROTO_xxx constants are missing on Windows, so rte_ip.h has to
>>>     provide them. I hope Mirosoft will add them to system headers one day.
>>>
>>> * It affects cmdline (mostly), ethdev, security, crypto/dpaax.
>> Sounds good - well done!
> 
> ...or not :)
> 
> If we can't help including <ws2tcpip.h>/<netinet/ip.h> from public headers,
> might as well use `struct in_addr`, just replace `#include <netinet/ip.h>`
> with `#include <rte_ip.h>` everywhere.
> 
> The only remaining issue will be `s_addr` macro on Windows that conflicts with
> `struct rte_ether_addr` field `s_addr`. I don't know a better solution than
> renaming `s_addr` to `src_addr` in DPDK (OTOH, it will be consistent with
> `struct rte_ipvX_hdr` field naming).
> 
> Ferruh, what do you think?
> 

No problem on the chosen name, that will work fine, but the 'struct 
rte_eth_addr' is public struct, we can't rename it without breaking the user 
applications.

Still it is possible to rename public struct, but it is a long process, need to 
send a deprecation notice and wait for next LTS, 21.11.

Ethernet header already has following, doesn't it help:
#undef s_addr /* Defined in winsock2.h included in windows.h. */

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-03 16:47                     ` Ferruh Yigit
@ 2021-03-03 18:19                       ` Dmitry Kozlyuk
  2021-03-03 19:30                         ` Ferruh Yigit
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-03 18:19 UTC (permalink / raw)
  To: Ferruh Yigit, Tyler Retzlaff
  Cc: Nick Connolly, dev, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-03-03 16:47, Ferruh Yigit:
> On 3/3/2021 4:32 PM, Dmitry Kozlyuk wrote:
[...]
> > If we can't help including <ws2tcpip.h>/<netinet/ip.h> from public headers,
> > might as well use `struct in_addr`, just replace `#include <netinet/ip.h>`
> > with `#include <rte_ip.h>` everywhere.
> > 
> > The only remaining issue will be `s_addr` macro on Windows that conflicts with
> > `struct rte_ether_addr` field `s_addr`. I don't know a better solution than
> > renaming `s_addr` to `src_addr` in DPDK (OTOH, it will be consistent with
> > `struct rte_ipvX_hdr` field naming).
> > 
> > Ferruh, what do you think?
> >   
> 
> No problem on the chosen name, that will work fine, but the 'struct 
> rte_eth_addr' is public struct, we can't rename it without breaking the user 
> applications.
> 
> Still it is possible to rename public struct, but it is a long process, need to 
> send a deprecation notice and wait for next LTS, 21.11.
> 
> Ethernet header already has following, doesn't it help:
> #undef s_addr /* Defined in winsock2.h included in windows.h. */

It helps until you do the following:

	#include <winsock2.h>	/* #define s_addr S_un.S_addr */
	#include <rte_ether.h>	/* #undef s_addr */

	struct in_addr a;
	a.s_addr = 0; /* ERROR, `s_addr` has been defined to do that */

Or the following:

	#include <rte_ether.h>
	#include <winsock2.h>

	struct rte_ether_hdr eh;
	eh.s_addr.addr_bytes[0] = 0;	/* ERROR: `addr_s` is a macro */

If you swap include order in each case, it compiles, i.e . code is fragile.
Shims redefine `struct in_addr` and we're trying to get rid of them anyway.


Here's a solution that always works, however ugly it looks. It defines
`struct rte_ether_hdr` for Windows such that `s_addr` macro works for it if
defined. We can keep it until 21.11, then remove it and rename fields. In
return, we can remove networking shims and workarounds immediately.

`S_un.S_addr` part of `struct in_addr` is documented, and thus is unlikely to
ever change:

	https://docs.microsoft.com/en-us/windows/win32/api/winsock2/ns-winsock2-in_addr


diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
index 060b63fc9..67d340bb2 100644
--- a/lib/librte_net/rte_ether.h
+++ b/lib/librte_net/rte_ether.h
@@ -23,10 +23,6 @@ extern "C" {
 #include <rte_mbuf.h>
 #include <rte_byteorder.h>
 
-#ifdef RTE_EXEC_ENV_WINDOWS /* Workaround conflict with rte_ether_hdr. */
-#undef s_addr /* Defined in winsock2.h included in windows.h. */
-#endif
-
 #define RTE_ETHER_ADDR_LEN  6 /**< Length of Ethernet address. */
 #define RTE_ETHER_TYPE_LEN  2 /**< Length of Ethernet type field. */
 #define RTE_ETHER_CRC_LEN   4 /**< Length of Ethernet CRC. */
@@ -257,6 +253,8 @@ __rte_experimental
 int
 rte_ether_unformat_addr(const char *str, struct rte_ether_addr *eth_addr);
 
+#if !defined RTE_EXEC_ENV_WINDOWS || defined __DOXYGEN__
+
 /**
  * Ethernet header: Contains the destination address, source address
  * and frame type.
@@ -267,6 +265,28 @@ struct rte_ether_hdr {
 	uint16_t ether_type;      /**< Frame type. */
 } __rte_aligned(2);
 
+#else
+
+#pragma push_macro("s_addr")
+#ifdef s_addr
+#undef s_addr
+#endif
+
+struct rte_ether_hdr {
+	struct rte_ether_addr d_addr; /**< Destination address. */
+	RTE_STD_C11
+	union {
+		struct rte_ether_addr s_addr; /**< Source address. */
+		struct {
+			struct rte_ether_addr S_un;
+		} S_addr;
+	};
+	uint16_t ether_type; /**< Frame type. */
+} __rte_aligned(2);
+
+#pragma pop_macro("s_addr")
+#endif
+
 /**
  * Ethernet VLAN Header.
  * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-03 18:19                       ` Dmitry Kozlyuk
@ 2021-03-03 19:30                         ` Ferruh Yigit
  2021-03-03 23:03                           ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-03-03 19:30 UTC (permalink / raw)
  To: Dmitry Kozlyuk, Tyler Retzlaff
  Cc: Nick Connolly, dev, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Jie Zhou

On 3/3/2021 6:19 PM, Dmitry Kozlyuk wrote:
> 2021-03-03 16:47, Ferruh Yigit:
>> On 3/3/2021 4:32 PM, Dmitry Kozlyuk wrote:
> [...]
>>> If we can't help including <ws2tcpip.h>/<netinet/ip.h> from public headers,
>>> might as well use `struct in_addr`, just replace `#include <netinet/ip.h>`
>>> with `#include <rte_ip.h>` everywhere.
>>>
>>> The only remaining issue will be `s_addr` macro on Windows that conflicts with
>>> `struct rte_ether_addr` field `s_addr`. I don't know a better solution than
>>> renaming `s_addr` to `src_addr` in DPDK (OTOH, it will be consistent with
>>> `struct rte_ipvX_hdr` field naming).
>>>
>>> Ferruh, what do you think?
>>>    
>>
>> No problem on the chosen name, that will work fine, but the 'struct
>> rte_eth_addr' is public struct, we can't rename it without breaking the user
>> applications.
>>
>> Still it is possible to rename public struct, but it is a long process, need to
>> send a deprecation notice and wait for next LTS, 21.11.
>>
>> Ethernet header already has following, doesn't it help:
>> #undef s_addr /* Defined in winsock2.h included in windows.h. */
> 
> It helps until you do the following:
> 
> 	#include <winsock2.h>	/* #define s_addr S_un.S_addr */
> 	#include <rte_ether.h>	/* #undef s_addr */
> 
> 	struct in_addr a;
> 	a.s_addr = 0; /* ERROR, `s_addr` has been defined to do that */
> 
> Or the following:
> 
> 	#include <rte_ether.h>
> 	#include <winsock2.h>
> 
> 	struct rte_ether_hdr eh;
> 	eh.s_addr.addr_bytes[0] = 0;	/* ERROR: `addr_s` is a macro */
> 
> If you swap include order in each case, it compiles, i.e . code is fragile.
> Shims redefine `struct in_addr` and we're trying to get rid of them anyway.
> 

Got it, thanks for clarification.

> 
> Here's a solution that always works, however ugly it looks. It defines
> `struct rte_ether_hdr` for Windows such that `s_addr` macro works for it if
> defined. We can keep it until 21.11, then remove it and rename fields. In
> return, we can remove networking shims and workarounds immediately.
> 

Agree it looks ugly :), but I am OK with above plan.
You need to send a deprecation notice for this. We can discuss there if 'd_addr' 
also should be renamed for consistency, or leave with the workaround instead of 
rename ...

> `S_un.S_addr` part of `struct in_addr` is documented, and thus is unlikely to
> ever change:
> 
> 	https://docs.microsoft.com/en-us/windows/win32/api/winsock2/ns-winsock2-in_addr
> 
> 
> diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> index 060b63fc9..67d340bb2 100644
> --- a/lib/librte_net/rte_ether.h
> +++ b/lib/librte_net/rte_ether.h
> @@ -23,10 +23,6 @@ extern "C" {
>   #include <rte_mbuf.h>
>   #include <rte_byteorder.h>
>   
> -#ifdef RTE_EXEC_ENV_WINDOWS /* Workaround conflict with rte_ether_hdr. */
> -#undef s_addr /* Defined in winsock2.h included in windows.h. */
> -#endif
> -
>   #define RTE_ETHER_ADDR_LEN  6 /**< Length of Ethernet address. */
>   #define RTE_ETHER_TYPE_LEN  2 /**< Length of Ethernet type field. */
>   #define RTE_ETHER_CRC_LEN   4 /**< Length of Ethernet CRC. */
> @@ -257,6 +253,8 @@ __rte_experimental
>   int
>   rte_ether_unformat_addr(const char *str, struct rte_ether_addr *eth_addr);
>   
> +#if !defined RTE_EXEC_ENV_WINDOWS || defined __DOXYGEN__
> +
>   /**
>    * Ethernet header: Contains the destination address, source address
>    * and frame type.
> @@ -267,6 +265,28 @@ struct rte_ether_hdr {
>   	uint16_t ether_type;      /**< Frame type. */
>   } __rte_aligned(2);
>   
> +#else
> +
> +#pragma push_macro("s_addr")
> +#ifdef s_addr
> +#undef s_addr
> +#endif

I guess this needs to be as following, in case this header included before the 
windows header:

#ifdef s_addr
#pragma push_macro("s_addr")
#undef s_addr
#endif

> +
> +struct rte_ether_hdr {
> +	struct rte_ether_addr d_addr; /**< Destination address. */
> +	RTE_STD_C11
> +	union {
> +		struct rte_ether_addr s_addr; /**< Source address. */
> +		struct {
> +			struct rte_ether_addr S_un;
> +		} S_addr;
> +	};
> +	uint16_t ether_type; /**< Frame type. */
> +} __rte_aligned(2);
> +
> +#pragma pop_macro("s_addr")
> +#endif
> +
>   /**
>    * Ethernet VLAN Header.
>    * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type
> 


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
  2021-03-03 19:30                         ` Ferruh Yigit
@ 2021-03-03 23:03                           ` Dmitry Kozlyuk
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-03 23:03 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: Tyler Retzlaff, Nick Connolly, dev, Mike Wells,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam, Jie Zhou

2021-03-03 19:30, Ferruh Yigit:
> On 3/3/2021 6:19 PM, Dmitry Kozlyuk wrote:
> > 2021-03-03 16:47, Ferruh Yigit:  
> >> On 3/3/2021 4:32 PM, Dmitry Kozlyuk wrote:  
[...]
> > +#pragma push_macro("s_addr")
> > +#ifdef s_addr
> > +#undef s_addr
> > +#endif  
> 
> I guess this needs to be as following, in case this header included before the 
> windows header:
> 
> #ifdef s_addr
> #pragma push_macro("s_addr")
> #undef s_addr
> #endif

It actually works both ways.
I used #ifdef inside so that #pragma pop_macro doesn't need its own guard.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
  2021-03-01 22:39     ` Nick Connolly
@ 2021-03-05 17:50     ` Jie Zhou
  2021-03-16  9:18     ` Thomas Monjalon
  2021-03-16 18:59     ` Stephen Hemminger
  3 siblings, 0 replies; 67+ messages in thread
From: Jie Zhou @ 2021-03-05 17:50 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman

On Sun, Feb 14, 2021 at 05:16:11AM +0300, Dmitry Kozlyuk wrote:
> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.
> 
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> ---
>  lib/librte_eal/include/rte_time.h    | 17 +++++++++++++++++
>  lib/librte_eal/rte_eal_exports.def   |  1 +
>  lib/librte_eal/unix/eal_unix_timer.c | 13 +++++++++++++
>  lib/librte_eal/version.map           |  1 +
>  lib/librte_eal/windows/eal_timer.c   | 21 ++++++++++++++++++++-
>  5 files changed, 52 insertions(+), 1 deletion(-)
>
Acked-by: Jie Zhou <jizh@linux.microsoft.com>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-02-25 17:42           ` Dmitry Kozlyuk
@ 2021-03-16  9:16             ` Thomas Monjalon
  2021-03-16  9:37               ` Dmitry Kozlyuk
  0 siblings, 1 reply; 67+ messages in thread
From: Thomas Monjalon @ 2021-03-16  9:16 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: Bruce Richardson, dev, Ferruh Yigit, Tyler Retzlaff, Mike Wells

25/02/2021 18:42, Dmitry Kozlyuk:
> 2021-02-25 16:33, Bruce Richardson:
> > On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
> > > 2021-02-25 15:02, Ferruh Yigit:  
> > > > On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:  
> > > > > WinPcap or Npcap, can be installed anywhere.
> > > > > Add a Meson option to specify SDK path.
> > > > >     
> > > > 
> > > > I am not sure if it is OK to add a meson option for this, can't we use the 
> > > > default path?
> > > > 
> > > > And does this mean we will need to add an option for each dependent library in 
> > > > Windows? If not, why pcap is special?  
> > > 
> > > There are some meson options for SDK paths already. Are they exceptions?
> > >   
> > Right now, yes, they are exceptions, but there is work underway to remove
> > them and just replace them with use of pkg-config. Is there some automatic
> > path discovery mechanism on windows, similar to pkg-config, that can be
> > used rather than having to add explicit dependency paths?
> 
> pkg-config itself works on Windows if installed and given a PKG_CONFIG_PATH.
> 
> Npcap doesn't provide a .pc file, despite libpcap commit 4f6b2b99 having it.

Please work with them to provide a .pc.

> Another quirk is that library is named libpcap.a/wpcap.lib on Unix/Windows.
> I can just handle the name difference and assume it's in the search path.

Yes please avoid adding a meson option for a path.



^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
  2021-03-01 22:39     ` Nick Connolly
  2021-03-05 17:50     ` Jie Zhou
@ 2021-03-16  9:18     ` Thomas Monjalon
  2021-03-16 18:59     ` Stephen Hemminger
  3 siblings, 0 replies; 67+ messages in thread
From: Thomas Monjalon @ 2021-03-16  9:18 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella

14/02/2021 03:16, Dmitry Kozlyuk:
> Many PMDs use POSIX gettimeofday(). Add rte_time_get_us() function
> to obtain current time with microsecond precision on all platforms.

Please could you replace the current use of gettimeofday?




^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows
  2021-03-16  9:16             ` Thomas Monjalon
@ 2021-03-16  9:37               ` Dmitry Kozlyuk
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-16  9:37 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Bruce Richardson, dev, Ferruh Yigit, Tyler Retzlaff, Mike Wells

2021-03-16 10:16 (UTC+0100), Thomas Monjalon:
> 25/02/2021 18:42, Dmitry Kozlyuk:
> > 2021-02-25 16:33, Bruce Richardson:  
> > > On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:  
> > > > 2021-02-25 15:02, Ferruh Yigit:    
> > > > > On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:    
[...]
> > pkg-config itself works on Windows if installed and given a PKG_CONFIG_PATH.
> > 
> > Npcap doesn't provide a .pc file, despite libpcap commit 4f6b2b99 having it.  
> 
> Please work with them to provide a .pc.

Good idea, but I can't tell how soon they do'll it.

> > Another quirk is that library is named libpcap.a/wpcap.lib on Unix/Windows.
> > I can just handle the name difference and assume it's in the search path.  
> 
> Yes please avoid adding a meson option for a path.

I have v3 that relies on search paths only with just a library name fixup.
It's blocked by [2] and, transitively, by [1].

[1]: http://patchwork.dpdk.org/project/dpdk/list/?series=15513
[1]: http://patchwork.dpdk.org/project/dpdk/list/?series=15640

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
                       ` (2 preceding siblings ...)
  2021-03-16  9:18     ` Thomas Monjalon
@ 2021-03-16 18:59     ` Stephen Hemminger
  2021-03-16 20:07       ` Dmitry Kozlyuk
  3 siblings, 1 reply; 67+ messages in thread
From: Stephen Hemminger @ 2021-03-16 18:59 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman

On Sun, 14 Feb 2021 05:16:11 +0300
Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:

> +rte_time_get_us(struct rte_time_us *now)
> +{
> +	struct timeval sys;
> +
> +	gettimeofday(&sys, NULL);
> +	now->sec = sys.tv_sec;
> +	now->usec = sys.tv_usec;
> +}

Why would drivers want the default (wall clock) time instead
of using monotonic clock. The wall clock gets changed by NTP
and that is rarely what you want except for the case of log messages.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-03-16 18:59     ` Stephen Hemminger
@ 2021-03-16 20:07       ` Dmitry Kozlyuk
  2021-03-17  9:50         ` Morten Brørup
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-16 20:07 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman

2021-03-16 11:59 (UTC-0700), Stephen Hemminger:
> On Sun, 14 Feb 2021 05:16:11 +0300
> Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:
> 
> > +rte_time_get_us(struct rte_time_us *now)
> > +{
> > +	struct timeval sys;
> > +
> > +	gettimeofday(&sys, NULL);
> > +	now->sec = sys.tv_sec;
> > +	now->usec = sys.tv_usec;
> > +}  
> 
> Why would drivers want the default (wall clock) time instead
> of using monotonic clock. The wall clock gets changed by NTP
> and that is rarely what you want except for the case of log messages.

* gettimeofday() is mostly used to measure time (tests, hns3 PMD), so you're
right, monotonic clock is what that code really needs.

* ena PMD uses gettimeofday() with pthread_cond_timedwait() without calling
pthread_cond_setclock(), which is a bug, I believe.

* hns3 PMD actually uses gettimeofday() for logs.

For wall clock time there is C11 timespec_get(), so I agree this API should
be changed to monotonic, thanks.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time
  2021-03-16 20:07       ` Dmitry Kozlyuk
@ 2021-03-17  9:50         ` Morten Brørup
  0 siblings, 0 replies; 67+ messages in thread
From: Morten Brørup @ 2021-03-17  9:50 UTC (permalink / raw)
  To: Dmitry Kozlyuk, Stephen Hemminger
  Cc: dev, Tyler Retzlaff, Mike Wells, Narcisa Ana Maria Vasile,
	Dmitry Malloy, Pallavi Kadam, Ray Kinsella, Neil Horman

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Dmitry Kozlyuk
> Sent: Tuesday, March 16, 2021 9:08 PM
> 
> 2021-03-16 11:59 (UTC-0700), Stephen Hemminger:
> > On Sun, 14 Feb 2021 05:16:11 +0300
> > Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> wrote:
> >
> > > +rte_time_get_us(struct rte_time_us *now)
> > > +{
> > > +	struct timeval sys;
> > > +
> > > +	gettimeofday(&sys, NULL);
> > > +	now->sec = sys.tv_sec;
> > > +	now->usec = sys.tv_usec;
> > > +}
> >
> > Why would drivers want the default (wall clock) time instead
> > of using monotonic clock. The wall clock gets changed by NTP
> > and that is rarely what you want except for the case of log messages.
> 
> * gettimeofday() is mostly used to measure time (tests, hns3 PMD), so
> you're
> right, monotonic clock is what that code really needs.

If using monotonic time here, we don't need a struct. A single 64 bit integer counting microseconds can hold thousands of years.

> 
> * ena PMD uses gettimeofday() with pthread_cond_timedwait() without
> calling
> pthread_cond_setclock(), which is a bug, I believe.
> 
> * hns3 PMD actually uses gettimeofday() for logs.
> 
> For wall clock time there is C11 timespec_get(), so I agree this API
> should
> be changed to monotonic, thanks.


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v3 0/3] net/pcap: build on Windows
  2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
                     ` (5 preceding siblings ...)
  2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 6/6] net/pcap: build " Dmitry Kozlyuk
@ 2021-03-24  0:50   ` Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
                       ` (4 more replies)
  6 siblings, 5 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-24  0:50 UTC (permalink / raw)
  To: dev; +Cc: Nick Connolly, Mike Wells, Tyler Retzlaff, Dmitry Kozlyuk

NOTE: dependency patches are requirements, CI may fail.

Most modern and actively maintained distribution of libpcap for Windows
is Npcap [1]. It currently doesn't provide a pkg-config file [2].
By default it is installed to C:\Program Files\Npcap and can be located
using standard environment variables [3]:

    $env:C_INCLUDE_PATH += ";C:\Program Files\Npcap"
    $env:LIBRARY_PATH += ";C:\Program Files\Npcap\Lib\x64"     # MinGW
    $env:LINK += ' /LIBPATH:"C:\Program Files\Npcap\Lib\x64"'  # Clang

The following libpcap.pc also works if placed in PKG_CONFIG_PATH:

    prefix="C:/Program Files/Npcap"
    Name: libpcap
    Version: 1.10
    Description: Platform-independent network traffic capture library
    Cflags: -I${prefix}/Include
    Libs: -L${prefix}/Lib/x64 -lwpcap

Example of collecting packets from an interface to a file:

    .\build\examples\dpdk-skeleton.exe `
        --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
        --vdev "eth_pcap1,tx_pcap=capture.pcap"

Interface name can be obtained as follows, with Wireshark installed:

    & "C:\Program Files\Wireshark\tshark.exe" -D

Implementation in "pcap_osdep_windows.c" does some guesswork to convert
between variants of an interface name. Microsoft experts and interested
users, please take a look and/or give it a try in your environment.

[1]: https://nmap.org/npcap
[2]: https://github.com/nmap/npcap/issues/299
[3]: https://mesonbuild.com/Reference-manual.html#compiler-object

Depends-on: series-15801 ("eal/windows: do not expose POSIX symbols")
Depends-on: patch-89639 ("[v2,3/3] meson: remove unnecessary explicit link to libpcap")

v3:
    * Use environment and pkg-config to locate libpcap (Bruce).
    * Use C11 timespec_get() instead of EAL wrapper.
    * Drop libpcap wrappers in net/pcap (Ferruh).

Dmitry Kozlyuk (3):
  eal/windows: add timespec_get shim for MinGW
  net/pcap: move OS-dependent code to separate files
  net/pcap: build on Windows

 config/meson.build                            |   3 +-
 doc/guides/rel_notes/release_21_05.rst        |   4 +
 drivers/net/pcap/meson.build                  |  16 +--
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 109 +++-------------
 drivers/net/pcap/pcap_osdep.h                 |  18 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 +++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++++++++++++
 .../windows/include/rte_os_internal.h         |  32 +++++
 9 files changed, 303 insertions(+), 98 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v3 1/3] eal/windows: add timespec_get shim for MinGW
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
@ 2021-03-24  0:50     ` Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-24  0:50 UTC (permalink / raw)
  To: dev
  Cc: Nick Connolly, Mike Wells, Tyler Retzlaff, Dmitry Kozlyuk,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam

MinGW-w64 does not currently implement C11 timespec_get.
Add an internal shim until this is fixed on MinGW side.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 .../windows/include/rte_os_internal.h         | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/lib/librte_eal/windows/include/rte_os_internal.h b/lib/librte_eal/windows/include/rte_os_internal.h
index 89ac5c9cbd..df37eb6cf7 100644
--- a/lib/librte_eal/windows/include/rte_os_internal.h
+++ b/lib/librte_eal/windows/include/rte_os_internal.h
@@ -3,7 +3,10 @@
 #ifndef _RTE_OS_INTERNAL_H_
 #define _RTE_OS_INTERNAL_H_
 
+#include <time.h>
+
 #include <rte_os.h>
+#include <rte_windows.h>
 
 /**
  * @file
@@ -33,4 +36,33 @@
 #define IPPROTO_SCTP	132
 #endif
 
+#ifdef RTE_TOOLCHAIN_GCC
+
+#define TIME_UTC 1
+
+static inline int
+rte_timespec_get(struct timespec *now, int base)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_SEC = 10000000;
+	static const uint64_t NS_PER_TICK = 100;
+
+	FILETIME ft;
+	uint64_t ticks;
+
+	if (base != TIME_UTC)
+		return 0;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	ticks -= EPOCH;
+	now->tv_sec = ticks / TICKS_PER_SEC;
+	now->tv_nsec = (ticks - now->tv_sec * TICKS_PER_SEC) * NS_PER_TICK;
+	return base;
+}
+
+#define timespec_get(ts, base) rte_timespec_get(ts, base)
+
+#endif /* RTE_TOOLCHAIN_GCC */
 #endif /* _RTE_OS_INTERNAL_H_ */
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v3 2/3] net/pcap: move OS-dependent code to separate files
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
@ 2021-03-24  0:50     ` Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 3/3] net/pcap: build on Windows Dmitry Kozlyuk
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-24  0:50 UTC (permalink / raw)
  To: dev
  Cc: Nick Connolly, Mike Wells, Tyler Retzlaff, Dmitry Kozlyuk, Ferruh Yigit

PCAP PMD queries interface information differently for Linux and
FreeBSD, OS-specific code is guarded by #ifdef. This PMD also depends on
POSIX bits, namely gettimeofday() and NAME_MAX.

Move OS-dependent code to separate files.
Replace POSIX bits with DPDK equivalents.
Rename rte_eth_pcap.c to pcap_ethdev.c, like it is in most other PMDs.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 drivers/net/pcap/meson.build                  |   5 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 105 ++++--------------
 drivers/net/pcap/pcap_osdep.h                 |  13 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 ++++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 5 files changed, 137 insertions(+), 87 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index b65d91e70a..26b6066990 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
-sources = files('rte_eth_pcap.c')
+sources = files(
+	'pcap_ethdev.c',
+	'pcap_osdep_@0@.c'.format(exec_env),
+)
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/pcap_ethdev.c
similarity index 95%
rename from drivers/net/pcap/rte_eth_pcap.c
rename to drivers/net/pcap/pcap_ethdev.c
index 28a5027315..1578de1204 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -6,16 +6,6 @@
 
 #include <time.h>
 
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#if defined(RTE_EXEC_ENV_FREEBSD)
-#include <sys/sysctl.h>
-#include <net/if_dl.h>
-#endif
-
 #include <pcap.h>
 
 #include <rte_cycles.h>
@@ -25,7 +15,9 @@
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
 #include <rte_bus_vdev.h>
-#include <rte_string_fns.h>
+#include <rte_os_internal.h>
+
+#include "pcap_osdep.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
@@ -46,7 +38,7 @@
 #define RTE_PMD_PCAP_MAX_QUEUES 16
 
 static char errbuf[PCAP_ERRBUF_SIZE];
-static struct timeval start_time;
+static struct timespec start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
 static uint8_t iface_idx;
@@ -354,17 +346,21 @@ eth_null_rx(void *queue __rte_unused,
 
 #define NSEC_PER_SEC	1000000000L
 
+/*
+ * This function stores nanoseconds in `tv_usec` field of `struct timeval`,
+ * because `ts` goes directly to nanosecond-precision dump.
+ */
 static inline void
 calculate_timestamp(struct timeval *ts) {
 	uint64_t cycles;
-	struct timeval cur_time;
+	struct timespec cur_time;
 
 	cycles = rte_get_timer_cycles() - start_cycles;
 	cur_time.tv_sec = cycles / hz;
-	cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz;
+	cur_time.tv_nsec = (cycles % hz) * NSEC_PER_SEC / hz;
 
 	ts->tv_sec = start_time.tv_sec + cur_time.tv_sec;
-	ts->tv_usec = start_time.tv_usec + cur_time.tv_usec;
+	ts->tv_usec = start_time.tv_nsec + cur_time.tv_nsec;
 	if (ts->tv_usec >= NSEC_PER_SEC) {
 		ts->tv_usec -= NSEC_PER_SEC;
 		ts->tv_sec += 1;
@@ -883,7 +879,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (internals->infinite_rx) {
 		struct pmd_process_private *pp;
-		char ring_name[NAME_MAX];
+		char ring_name[RTE_RING_NAMESIZE];
 		static uint32_t ring_number;
 		uint64_t pcap_pkt_count = 0;
 		struct rte_mbuf *bufs[1];
@@ -1261,84 +1257,20 @@ static int
 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
 		const unsigned int numa_node)
 {
-#if defined(RTE_EXEC_ENV_LINUX)
 	void *mac_addrs;
-	struct ifreq ifr;
-	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-	if (if_fd == -1)
-		return -1;
+	struct rte_ether_addr mac;
 
-	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
-		close(if_fd);
+	if (osdep_iface_mac_get(if_name, &mac) < 0)
 		return -1;
-	}
 
 	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		close(if_fd);
+	if (mac_addrs == NULL)
 		return -1;
-	}
 
 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
+	rte_memcpy(mac_addrs, mac.addr_bytes, RTE_ETHER_ADDR_LEN);
 	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
-
-	close(if_fd);
-
-	return 0;
-
-#elif defined(RTE_EXEC_ENV_FREEBSD)
-	void *mac_addrs;
-	struct if_msghdr *ifm;
-	struct sockaddr_dl *sdl;
-	int mib[6];
-	size_t len = 0;
-	char *buf;
-
-	mib[0] = CTL_NET;
-	mib[1] = AF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_LINK;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = if_nametoindex(if_name);
-
-	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
-		return -1;
-
-	if (len == 0)
-		return -1;
-
-	buf = rte_malloc(NULL, len, 0);
-	if (!buf)
-		return -1;
-
-	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
-		rte_free(buf);
-		return -1;
-	}
-	ifm = (struct if_msghdr *)buf;
-	sdl = (struct sockaddr_dl *)(ifm + 1);
-
-	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		rte_free(buf);
-		return -1;
-	}
-
-	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
-	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			LLADDR(sdl), RTE_ETHER_ADDR_LEN);
-
-	rte_free(buf);
-
 	return 0;
-#else
-	return -1;
-#endif
 }
 
 static int
@@ -1400,7 +1332,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 	internals->single_iface = single_iface;
 
 	if (single_iface) {
-		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
+		internals->if_index =
+			osdep_iface_index_get(rx_queues->queue[0].name);
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
@@ -1453,7 +1386,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	name = rte_vdev_device_name(dev);
 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
 
-	gettimeofday(&start_time, NULL);
+	timespec_get(&start_time, TIME_UTC);
 	start_cycles = rte_get_timer_cycles();
 	hz = rte_get_timer_hz();
 
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
new file mode 100644
index 0000000000..9de422ab8d
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#ifndef _RTE_PCAP_OSDEP_
+#define _RTE_PCAP_OSDEP_
+
+#include <rte_ether.h>
+
+int osdep_iface_index_get(const char *name);
+int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
+
+#endif
diff --git a/drivers/net/pcap/pcap_osdep_freebsd.c b/drivers/net/pcap/pcap_osdep_freebsd.c
new file mode 100644
index 0000000000..20556b3e92
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_freebsd.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len = 0;
+	char *buf;
+
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(if_name);
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+		return -1;
+
+	if (len == 0)
+		return -1;
+
+	buf = rte_malloc(NULL, len, 0);
+	if (!buf)
+		return -1;
+
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		rte_free(buf);
+		return -1;
+	}
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(ifm + 1);
+
+	rte_memcpy(mac->addr_bytes, LLADDR(sdl), RTE_ETHER_ADDR_LEN);
+
+	rte_free(buf);
+	return 0;
+}
diff --git a/drivers/net/pcap/pcap_osdep_linux.c b/drivers/net/pcap/pcap_osdep_linux.c
new file mode 100644
index 0000000000..97033f57c5
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_linux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct ifreq ifr;
+	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (if_fd == -1)
+		return -1;
+
+	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
+		close(if_fd);
+		return -1;
+	}
+
+	rte_memcpy(mac->addr_bytes, ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
+
+	close(if_fd);
+	return 0;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v3 3/3] net/pcap: build on Windows
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-03-24  0:50     ` Dmitry Kozlyuk
  2021-04-09 10:51     ` [dpdk-dev] [PATCH v3 0/3] " Ferruh Yigit
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
  4 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-03-24  0:50 UTC (permalink / raw)
  To: dev
  Cc: Nick Connolly, Mike Wells, Tyler Retzlaff, Dmitry Kozlyuk,
	Bruce Richardson, Ferruh Yigit

Implement OS-dependent functions and enable build for Windows.
Account for different library name in Windows libpcap distributions.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 config/meson.build                     |   3 +-
 doc/guides/rel_notes/release_21_05.rst |   4 +
 drivers/net/pcap/meson.build           |  11 ++-
 drivers/net/pcap/pcap_ethdev.c         |   4 -
 drivers/net/pcap/pcap_osdep.h          |   5 ++
 drivers/net/pcap/pcap_osdep_windows.c  | 118 +++++++++++++++++++++++++
 6 files changed, 134 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

diff --git a/config/meson.build b/config/meson.build
index 95777cf331..a15731cfc6 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -179,7 +179,8 @@ endif
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 if not pcap_dep.found()
 	# pcap got a pkg-config file only in 1.9.0
-	pcap_dep = cc.find_library('pcap', required: false)
+	pcap_lib = is_windows ? 'wpcap' : 'pcap'
+	pcap_dep = cc.find_library(pcap_lib, required: false)
 endif
 if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
 	dpdk_conf.set('RTE_PORT_PCAP', 1)
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 8e686cc627..ae78273075 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -101,6 +101,10 @@ New Features
   * Added command to display Rx queue used descriptor count.
     ``show port (port_id) rxq (queue_id) desc used count``
 
+* **Enabled libpcap-based PMD on Windows.**
+
+   A libpcap distribution, such as Npcap or WinPcap, is required to run the PMD.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 26b6066990..63ad3f34f0 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -1,18 +1,17 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-if is_windows
-	build = false
-	reason = 'not supported on Windows'
-	subdir_done()
-endif
-
 if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
+
 sources = files(
 	'pcap_ethdev.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
+
 ext_deps += pcap_dep
+if is_windows
+	ext_deps += cc.find_library('iphlpapi', required: true)
+endif
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 1578de1204..875b736e97 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -142,10 +142,6 @@ static struct rte_eth_link pmd_link = {
 
 RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
-#define PMD_LOG(level, fmt, args...) \
-	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
-		"%s(): " fmt "\n", __func__, ##args)
-
 static struct queue_missed_stat*
 queue_missed_stat_update(struct rte_eth_dev *dev, unsigned int qid)
 {
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 9de422ab8d..bf41cba982 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -7,6 +7,11 @@
 
 #include <rte_ether.h>
 
+#define PMD_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
+		"%s(): " fmt "\n", __func__, ##args)
+extern int eth_pcap_logtype;
+
 int osdep_iface_index_get(const char *name);
 int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
 
diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
new file mode 100644
index 0000000000..1d398dc7ed
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_windows.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
+
+#include "pcap_osdep.h"
+
+/*
+ * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
+ * Return NULL if "{GUID}" part is not found.
+ */
+static const char *
+iface_guid(const char *name)
+{
+	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
+
+	const char *ob, *cb;
+
+	ob = strchr(name, '{');
+	if (ob == NULL)
+		return NULL;
+
+	cb = strchr(ob, '}');
+	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
+		return NULL;
+
+	return ob;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
+ * Try to convert, fall back to original device name.
+ */
+int
+osdep_iface_index_get(const char *device_name)
+{
+	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
+	const char *guid;
+	ULONG index;
+	DWORD ret;
+
+	guid = iface_guid(device_name);
+	if (guid != NULL)
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"\\DEVICE\\TCPIP_%S", guid);
+	else
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"%S", device_name);
+
+	ret = GetAdapterIndex(adapter_name, &index);
+	if (ret != NO_ERROR) {
+		PMD_LOG(ERR, "GetAdapterIndex(%S) = %lu\n", adapter_name, ret);
+		return -1;
+	}
+
+	return index;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdaptersAddresses() returns names in "{GUID}" form.
+ * Try to extract GUID from device name, fall back to original device name.
+ */
+int
+osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
+{
+	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
+	ULONG size, sys_ret;
+	const char *adapter_name;
+	int ret = -1;
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
+	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
+			sys_ret, ERROR_BUFFER_OVERFLOW);
+		return -1;
+	}
+
+	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
+	if (info == NULL) {
+		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
+		return -1;
+	}
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
+	if (sys_ret != ERROR_SUCCESS) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
+		free(info);
+		return -1;
+	}
+
+	adapter_name = iface_guid(device_name);
+	if (adapter_name == NULL)
+		adapter_name = device_name;
+
+	for (cur = info; cur != NULL; cur = cur->Next) {
+		if (strcmp(cur->AdapterName, adapter_name) == 0) {
+			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
+				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
+					RTE_ETHER_ADDR_LEN,
+					cur->PhysicalAddressLength);
+				break;
+			}
+
+			memcpy(mac->addr_bytes, cur->PhysicalAddress,
+				RTE_ETHER_ADDR_LEN);
+			ret = 0;
+			break;
+		}
+	}
+
+	free(info);
+	return ret;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/3] net/pcap: build on Windows
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
                       ` (2 preceding siblings ...)
  2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 3/3] net/pcap: build on Windows Dmitry Kozlyuk
@ 2021-04-09 10:51     ` Ferruh Yigit
  2021-04-09 11:03       ` Dmitry Kozlyuk
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
  4 siblings, 1 reply; 67+ messages in thread
From: Ferruh Yigit @ 2021-04-09 10:51 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Nick Connolly, Mike Wells, Tyler Retzlaff

On 3/24/2021 12:50 AM, Dmitry Kozlyuk wrote:
> NOTE: dependency patches are requirements, CI may fail.
> 
> Most modern and actively maintained distribution of libpcap for Windows
> is Npcap [1]. It currently doesn't provide a pkg-config file [2].
> By default it is installed to C:\Program Files\Npcap and can be located
> using standard environment variables [3]:
> 
>      $env:C_INCLUDE_PATH += ";C:\Program Files\Npcap"
>      $env:LIBRARY_PATH += ";C:\Program Files\Npcap\Lib\x64"     # MinGW
>      $env:LINK += ' /LIBPATH:"C:\Program Files\Npcap\Lib\x64"'  # Clang
> 
> The following libpcap.pc also works if placed in PKG_CONFIG_PATH:
> 
>      prefix="C:/Program Files/Npcap"
>      Name: libpcap
>      Version: 1.10
>      Description: Platform-independent network traffic capture library
>      Cflags: -I${prefix}/Include
>      Libs: -L${prefix}/Lib/x64 -lwpcap
> 
> Example of collecting packets from an interface to a file:
> 
>      .\build\examples\dpdk-skeleton.exe `
>          --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
>          --vdev "eth_pcap1,tx_pcap=capture.pcap"
> 
> Interface name can be obtained as follows, with Wireshark installed:
> 
>      & "C:\Program Files\Wireshark\tshark.exe" -D
> 
> Implementation in "pcap_osdep_windows.c" does some guesswork to convert
> between variants of an interface name. Microsoft experts and interested
> users, please take a look and/or give it a try in your environment.
> 
> [1]: https://nmap.org/npcap
> [2]: https://github.com/nmap/npcap/issues/299
> [3]: https://mesonbuild.com/Reference-manual.html#compiler-object
> 
> Depends-on: series-15801 ("eal/windows: do not expose POSIX symbols")
> Depends-on: patch-89639 ("[v2,3/3] meson: remove unnecessary explicit link to libpcap")
> 

Hi Dmitry,

What is the status of the dependent patches, are they merged?

> v3:
>      * Use environment and pkg-config to locate libpcap (Bruce).
>      * Use C11 timespec_get() instead of EAL wrapper.
>      * Drop libpcap wrappers in net/pcap (Ferruh).
> 
> Dmitry Kozlyuk (3):
>    eal/windows: add timespec_get shim for MinGW
>    net/pcap: move OS-dependent code to separate files
>    net/pcap: build on Windows
> 
>   config/meson.build                            |   3 +-
>   doc/guides/rel_notes/release_21_05.rst        |   4 +
>   drivers/net/pcap/meson.build                  |  16 +--
>   .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 109 +++-------------
>   drivers/net/pcap/pcap_osdep.h                 |  18 +++
>   drivers/net/pcap/pcap_osdep_freebsd.c         |  59 +++++++++
>   drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
>   drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++++++++++++
>   .../windows/include/rte_os_internal.h         |  32 +++++
>   9 files changed, 303 insertions(+), 98 deletions(-)
>   rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
>   create mode 100644 drivers/net/pcap/pcap_osdep.h
>   create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
>   create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
>   create mode 100644 drivers/net/pcap/pcap_osdep_windows.c
> 


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/3] net/pcap: build on Windows
  2021-04-09 10:51     ` [dpdk-dev] [PATCH v3 0/3] " Ferruh Yigit
@ 2021-04-09 11:03       ` Dmitry Kozlyuk
  2021-04-09 11:24         ` Ferruh Yigit
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-09 11:03 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Nick Connolly, Mike Wells, Tyler Retzlaff

2021-04-09 11:51 (UTC+0100), Ferruh Yigit:
> On 3/24/2021 12:50 AM, Dmitry Kozlyuk wrote:
[...]
> > Depends-on: series-15801 ("eal/windows: do not expose POSIX symbols")
> > Depends-on: patch-89639 ("[v2,3/3] meson: remove unnecessary explicit link to libpcap")
> >   
> 
> Hi Dmitry,
> 
> What is the status of the dependent patches, are they merged?

Hi Ferruh,

Not yet, but reviews are progressing.
series-15801 has some acks and no pending changes, probably close to merge.
AFAIK, Thomas is now reviewing patch-89639 to improve its description.
This series will need a v4 for trivial rebase and to trigger a CI run.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/3] net/pcap: build on Windows
  2021-04-09 11:03       ` Dmitry Kozlyuk
@ 2021-04-09 11:24         ` Ferruh Yigit
  0 siblings, 0 replies; 67+ messages in thread
From: Ferruh Yigit @ 2021-04-09 11:24 UTC (permalink / raw)
  To: Dmitry Kozlyuk
  Cc: dev, Nick Connolly, Mike Wells, Tyler Retzlaff, Thomas Monjalon

On 4/9/2021 12:03 PM, Dmitry Kozlyuk wrote:
> 2021-04-09 11:51 (UTC+0100), Ferruh Yigit:
>> On 3/24/2021 12:50 AM, Dmitry Kozlyuk wrote:
> [...]
>>> Depends-on: series-15801 ("eal/windows: do not expose POSIX symbols")
>>> Depends-on: patch-89639 ("[v2,3/3] meson: remove unnecessary explicit link to libpcap")
>>>    
>>
>> Hi Dmitry,
>>
>> What is the status of the dependent patches, are they merged?
> 
> Hi Ferruh,
> 
> Not yet, but reviews are progressing.
> series-15801 has some acks and no pending changes, probably close to merge.
> AFAIK, Thomas is now reviewing patch-89639 to improve its description.
> This series will need a v4 for trivial rebase and to trigger a CI run.
> 

Thanks Dmitry, cc'ed Thomas.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v4 0/3] net/pcap: build on Windows
  2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
                       ` (3 preceding siblings ...)
  2021-04-09 10:51     ` [dpdk-dev] [PATCH v3 0/3] " Ferruh Yigit
@ 2021-04-15 22:10     ` Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
                         ` (5 more replies)
  4 siblings, 6 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-15 22:10 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk

Most modern and actively maintained distribution of libpcap for Windows
is Npcap [1]. It currently doesn't provide a pkg-config file [2].
By default it is installed to C:\Program Files\Npcap and can be located
using standard environment variables [3]:

    $env:C_INCLUDE_PATH += ";C:\Program Files\Npcap"
    $env:LIBRARY_PATH += ";C:\Program Files\Npcap\Lib\x64"     # MinGW
    $env:LINK += ' /LIBPATH:"C:\Program Files\Npcap\Lib\x64"'  # Clang

The following libpcap.pc also works if placed in PKG_CONFIG_PATH:

    prefix="C:/Program Files/Npcap"
    Name: libpcap
    Version: 1.10
    Description: Platform-independent network traffic capture library
    Cflags: -I${prefix}/Include
    Libs: -L${prefix}/Lib/x64 -lwpcap

Example of collecting packets from an interface to a file:

    .\build\examples\dpdk-skeleton.exe `
        --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
        --vdev "eth_pcap1,tx_pcap=capture.pcap"

Interface name can be obtained as follows, with Wireshark installed:

    & "C:\Program Files\Wireshark\tshark.exe" -D

Implementation in "pcap_osdep_windows.c" does some guesswork to convert
between variants of an interface name. Microsoft experts and interested
users, please take a look and/or give it a try in your environment.

[1]: https://nmap.org/npcap
[2]: https://github.com/nmap/npcap/issues/299
[3]: https://mesonbuild.com/Reference-manual.html#compiler-object

v4:
    * Change libpcap discovery to work without dependent patch.
    * Fix memory leak in osdep_iface_mac_get (in v3, actually).
    * rte_os_internal.h -> rte_os_shim.h in patch 3/3.

Dmitry Kozlyuk (3):
  eal/windows: add timespec_get shim for MinGW
  net/pcap: move OS-dependent code to separate files
  net/pcap: build on Windows

 config/meson.build                            |   5 +-
 doc/guides/rel_notes/release_21_05.rst        |   4 +
 drivers/net/pcap/meson.build                  |  16 +--
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 109 +++-------------
 drivers/net/pcap/pcap_osdep.h                 |  18 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 +++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++++++++++++
 lib/librte_eal/windows/include/rte_os_shim.h  |  32 +++++
 9 files changed, 304 insertions(+), 99 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v4 1/3] eal/windows: add timespec_get shim for MinGW
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
@ 2021-04-15 22:10       ` Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-15 22:10 UTC (permalink / raw)
  To: dev
  Cc: Dmitry Kozlyuk, Jie Zhou, Nick Connolly,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam

MinGW-w64 does not currently implement C11 timespec_get.
Add an internal shim until this is fixed on MinGW side.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Acked-by: Jie Zhou <jizh@linux.microsoft.com>
Acked-by: Nick Connolly <nick.connolly@mayadata.io>
---
 lib/librte_eal/windows/include/rte_os_shim.h | 32 ++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/lib/librte_eal/windows/include/rte_os_shim.h b/lib/librte_eal/windows/include/rte_os_shim.h
index f40fb62d1d..e50895fd83 100644
--- a/lib/librte_eal/windows/include/rte_os_shim.h
+++ b/lib/librte_eal/windows/include/rte_os_shim.h
@@ -3,7 +3,10 @@
 #ifndef _RTE_OS_SHIM_
 #define _RTE_OS_SHIM_
 
+#include <time.h>
+
 #include <rte_os.h>
+#include <rte_windows.h>
 
 /**
  * @file
@@ -33,4 +36,33 @@
 #define IPPROTO_SCTP	132
 #endif
 
+#ifdef RTE_TOOLCHAIN_GCC
+
+#define TIME_UTC 1
+
+static inline int
+rte_timespec_get(struct timespec *now, int base)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_SEC = 10000000;
+	static const uint64_t NS_PER_TICK = 100;
+
+	FILETIME ft;
+	uint64_t ticks;
+
+	if (base != TIME_UTC)
+		return 0;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	ticks -= EPOCH;
+	now->tv_sec = ticks / TICKS_PER_SEC;
+	now->tv_nsec = (ticks - now->tv_sec * TICKS_PER_SEC) * NS_PER_TICK;
+	return base;
+}
+
+#define timespec_get(ts, base) rte_timespec_get(ts, base)
+
+#endif /* RTE_TOOLCHAIN_GCC */
 #endif /* _RTE_OS_SHIM_ */
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v4 2/3] net/pcap: move OS-dependent code to separate files
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
@ 2021-04-15 22:10       ` Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows Dmitry Kozlyuk
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-15 22:10 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk, Ferruh Yigit

PCAP PMD queries interface information differently for Linux and
FreeBSD, OS-specific code is guarded by #ifdef. This PMD also depends on
POSIX bits, namely gettimeofday() and NAME_MAX.

Move OS-dependent code to separate files.
Replace POSIX bits with DPDK equivalents.
Rename rte_eth_pcap.c to pcap_ethdev.c, like it is in most other PMDs.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 drivers/net/pcap/meson.build                  |   5 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 104 +++---------------
 drivers/net/pcap/pcap_osdep.h                 |  13 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 ++++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 5 files changed, 136 insertions(+), 87 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index b65d91e70a..26b6066990 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
-sources = files('rte_eth_pcap.c')
+sources = files(
+	'pcap_ethdev.c',
+	'pcap_osdep_@0@.c'.format(exec_env),
+)
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/pcap_ethdev.c
similarity index 95%
rename from drivers/net/pcap/rte_eth_pcap.c
rename to drivers/net/pcap/pcap_ethdev.c
index 28a5027315..4ac594eeca 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -6,16 +6,6 @@
 
 #include <time.h>
 
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#if defined(RTE_EXEC_ENV_FREEBSD)
-#include <sys/sysctl.h>
-#include <net/if_dl.h>
-#endif
-
 #include <pcap.h>
 
 #include <rte_cycles.h>
@@ -25,7 +15,8 @@
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
 #include <rte_bus_vdev.h>
-#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
@@ -46,7 +37,7 @@
 #define RTE_PMD_PCAP_MAX_QUEUES 16
 
 static char errbuf[PCAP_ERRBUF_SIZE];
-static struct timeval start_time;
+static struct timespec start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
 static uint8_t iface_idx;
@@ -354,17 +345,21 @@ eth_null_rx(void *queue __rte_unused,
 
 #define NSEC_PER_SEC	1000000000L
 
+/*
+ * This function stores nanoseconds in `tv_usec` field of `struct timeval`,
+ * because `ts` goes directly to nanosecond-precision dump.
+ */
 static inline void
 calculate_timestamp(struct timeval *ts) {
 	uint64_t cycles;
-	struct timeval cur_time;
+	struct timespec cur_time;
 
 	cycles = rte_get_timer_cycles() - start_cycles;
 	cur_time.tv_sec = cycles / hz;
-	cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz;
+	cur_time.tv_nsec = (cycles % hz) * NSEC_PER_SEC / hz;
 
 	ts->tv_sec = start_time.tv_sec + cur_time.tv_sec;
-	ts->tv_usec = start_time.tv_usec + cur_time.tv_usec;
+	ts->tv_usec = start_time.tv_nsec + cur_time.tv_nsec;
 	if (ts->tv_usec >= NSEC_PER_SEC) {
 		ts->tv_usec -= NSEC_PER_SEC;
 		ts->tv_sec += 1;
@@ -883,7 +878,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (internals->infinite_rx) {
 		struct pmd_process_private *pp;
-		char ring_name[NAME_MAX];
+		char ring_name[RTE_RING_NAMESIZE];
 		static uint32_t ring_number;
 		uint64_t pcap_pkt_count = 0;
 		struct rte_mbuf *bufs[1];
@@ -1261,84 +1256,20 @@ static int
 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
 		const unsigned int numa_node)
 {
-#if defined(RTE_EXEC_ENV_LINUX)
 	void *mac_addrs;
-	struct ifreq ifr;
-	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-	if (if_fd == -1)
-		return -1;
+	struct rte_ether_addr mac;
 
-	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
-		close(if_fd);
+	if (osdep_iface_mac_get(if_name, &mac) < 0)
 		return -1;
-	}
 
 	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		close(if_fd);
+	if (mac_addrs == NULL)
 		return -1;
-	}
 
 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
+	rte_memcpy(mac_addrs, mac.addr_bytes, RTE_ETHER_ADDR_LEN);
 	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
-
-	close(if_fd);
-
-	return 0;
-
-#elif defined(RTE_EXEC_ENV_FREEBSD)
-	void *mac_addrs;
-	struct if_msghdr *ifm;
-	struct sockaddr_dl *sdl;
-	int mib[6];
-	size_t len = 0;
-	char *buf;
-
-	mib[0] = CTL_NET;
-	mib[1] = AF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_LINK;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = if_nametoindex(if_name);
-
-	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
-		return -1;
-
-	if (len == 0)
-		return -1;
-
-	buf = rte_malloc(NULL, len, 0);
-	if (!buf)
-		return -1;
-
-	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
-		rte_free(buf);
-		return -1;
-	}
-	ifm = (struct if_msghdr *)buf;
-	sdl = (struct sockaddr_dl *)(ifm + 1);
-
-	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		rte_free(buf);
-		return -1;
-	}
-
-	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
-	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			LLADDR(sdl), RTE_ETHER_ADDR_LEN);
-
-	rte_free(buf);
-
 	return 0;
-#else
-	return -1;
-#endif
 }
 
 static int
@@ -1400,7 +1331,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 	internals->single_iface = single_iface;
 
 	if (single_iface) {
-		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
+		internals->if_index =
+			osdep_iface_index_get(rx_queues->queue[0].name);
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
@@ -1453,7 +1385,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	name = rte_vdev_device_name(dev);
 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
 
-	gettimeofday(&start_time, NULL);
+	timespec_get(&start_time, TIME_UTC);
 	start_cycles = rte_get_timer_cycles();
 	hz = rte_get_timer_hz();
 
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
new file mode 100644
index 0000000000..9de422ab8d
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#ifndef _RTE_PCAP_OSDEP_
+#define _RTE_PCAP_OSDEP_
+
+#include <rte_ether.h>
+
+int osdep_iface_index_get(const char *name);
+int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
+
+#endif
diff --git a/drivers/net/pcap/pcap_osdep_freebsd.c b/drivers/net/pcap/pcap_osdep_freebsd.c
new file mode 100644
index 0000000000..20556b3e92
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_freebsd.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len = 0;
+	char *buf;
+
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(if_name);
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+		return -1;
+
+	if (len == 0)
+		return -1;
+
+	buf = rte_malloc(NULL, len, 0);
+	if (!buf)
+		return -1;
+
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		rte_free(buf);
+		return -1;
+	}
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(ifm + 1);
+
+	rte_memcpy(mac->addr_bytes, LLADDR(sdl), RTE_ETHER_ADDR_LEN);
+
+	rte_free(buf);
+	return 0;
+}
diff --git a/drivers/net/pcap/pcap_osdep_linux.c b/drivers/net/pcap/pcap_osdep_linux.c
new file mode 100644
index 0000000000..97033f57c5
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_linux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct ifreq ifr;
+	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (if_fd == -1)
+		return -1;
+
+	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
+		close(if_fd);
+		return -1;
+	}
+
+	rte_memcpy(mac->addr_bytes, ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
+
+	close(if_fd);
+	return 0;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-04-15 22:10       ` Dmitry Kozlyuk
  2021-04-19 21:05         ` Tyler Retzlaff
  2021-04-16 17:22       ` [dpdk-dev] [PATCH v4 0/3] " Ferruh Yigit
                         ` (2 subsequent siblings)
  5 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-15 22:10 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk, Tyler Retzlaff, Bruce Richardson, Ferruh Yigit

Implement OS-dependent functions and enable build for Windows.
Account for different library name in Windows libpcap distributions.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
Tyler, IIRC you were reviewing the code?
This patch is the most important one but surprisingly has no acks.
---
 config/meson.build                     |   5 +-
 doc/guides/rel_notes/release_21_05.rst |   4 +
 drivers/net/pcap/meson.build           |  11 ++-
 drivers/net/pcap/pcap_ethdev.c         |   5 +-
 drivers/net/pcap/pcap_osdep.h          |   5 ++
 drivers/net/pcap/pcap_osdep_windows.c  | 118 +++++++++++++++++++++++++
 6 files changed, 136 insertions(+), 12 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

diff --git a/config/meson.build b/config/meson.build
index 6e6ef8c0e1..6737cc3e26 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -182,13 +182,14 @@ endif
 
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
+pcap_lib = is_windows ? 'wpcap' : 'pcap'
 if not pcap_dep.found()
 	# pcap got a pkg-config file only in 1.9.0
-	pcap_dep = cc.find_library('pcap', required: false)
+	pcap_dep = cc.find_library(pcap_lib, required: false)
 endif
 if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
 	dpdk_conf.set('RTE_PORT_PCAP', 1)
-	dpdk_extra_ldflags += '-lpcap'
+	dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
 endif
 
 # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 2e3bf5c95a..ed0e23a47b 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -174,6 +174,10 @@ New Features
   * Added command to display Rx queue used descriptor count.
     ``show port (port_id) rxq (queue_id) desc used count``
 
+* **Enabled libpcap-based PMD on Windows.**
+
+   A libpcap distribution, such as Npcap or WinPcap, is required to run the PMD.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 26b6066990..63ad3f34f0 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -1,18 +1,17 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-if is_windows
-	build = false
-	reason = 'not supported on Windows'
-	subdir_done()
-endif
-
 if not dpdk_conf.has('RTE_PORT_PCAP')
 	build = false
 	reason = 'missing dependency, "libpcap"'
 endif
+
 sources = files(
 	'pcap_ethdev.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
+
 ext_deps += pcap_dep
+if is_windows
+	ext_deps += cc.find_library('iphlpapi', required: true)
+endif
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 4ac594eeca..3961843efc 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -15,6 +15,7 @@
 #include <rte_malloc.h>
 #include <rte_mbuf.h>
 #include <rte_bus_vdev.h>
+#include <rte_os_shim.h>
 
 #include "pcap_osdep.h"
 
@@ -141,10 +142,6 @@ static struct rte_eth_link pmd_link = {
 
 RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
-#define PMD_LOG(level, fmt, args...) \
-	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
-		"%s(): " fmt "\n", __func__, ##args)
-
 static struct queue_missed_stat*
 queue_missed_stat_update(struct rte_eth_dev *dev, unsigned int qid)
 {
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 9de422ab8d..bf41cba982 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -7,6 +7,11 @@
 
 #include <rte_ether.h>
 
+#define PMD_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
+		"%s(): " fmt "\n", __func__, ##args)
+extern int eth_pcap_logtype;
+
 int osdep_iface_index_get(const char *name);
 int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
 
diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
new file mode 100644
index 0000000000..1d398dc7ed
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_windows.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
+
+#include "pcap_osdep.h"
+
+/*
+ * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
+ * Return NULL if "{GUID}" part is not found.
+ */
+static const char *
+iface_guid(const char *name)
+{
+	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
+
+	const char *ob, *cb;
+
+	ob = strchr(name, '{');
+	if (ob == NULL)
+		return NULL;
+
+	cb = strchr(ob, '}');
+	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
+		return NULL;
+
+	return ob;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
+ * Try to convert, fall back to original device name.
+ */
+int
+osdep_iface_index_get(const char *device_name)
+{
+	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
+	const char *guid;
+	ULONG index;
+	DWORD ret;
+
+	guid = iface_guid(device_name);
+	if (guid != NULL)
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"\\DEVICE\\TCPIP_%S", guid);
+	else
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"%S", device_name);
+
+	ret = GetAdapterIndex(adapter_name, &index);
+	if (ret != NO_ERROR) {
+		PMD_LOG(ERR, "GetAdapterIndex(%S) = %lu\n", adapter_name, ret);
+		return -1;
+	}
+
+	return index;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdaptersAddresses() returns names in "{GUID}" form.
+ * Try to extract GUID from device name, fall back to original device name.
+ */
+int
+osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
+{
+	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
+	ULONG size, sys_ret;
+	const char *adapter_name;
+	int ret = -1;
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
+	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
+			sys_ret, ERROR_BUFFER_OVERFLOW);
+		return -1;
+	}
+
+	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
+	if (info == NULL) {
+		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
+		return -1;
+	}
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
+	if (sys_ret != ERROR_SUCCESS) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
+		free(info);
+		return -1;
+	}
+
+	adapter_name = iface_guid(device_name);
+	if (adapter_name == NULL)
+		adapter_name = device_name;
+
+	for (cur = info; cur != NULL; cur = cur->Next) {
+		if (strcmp(cur->AdapterName, adapter_name) == 0) {
+			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
+				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
+					RTE_ETHER_ADDR_LEN,
+					cur->PhysicalAddressLength);
+				break;
+			}
+
+			memcpy(mac->addr_bytes, cur->PhysicalAddress,
+				RTE_ETHER_ADDR_LEN);
+			ret = 0;
+			break;
+		}
+	}
+
+	free(info);
+	return ret;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/3] net/pcap: build on Windows
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
                         ` (2 preceding siblings ...)
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows Dmitry Kozlyuk
@ 2021-04-16 17:22       ` Ferruh Yigit
  2021-04-20 22:20       ` Thomas Monjalon
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
  5 siblings, 0 replies; 67+ messages in thread
From: Ferruh Yigit @ 2021-04-16 17:22 UTC (permalink / raw)
  To: Dmitry Kozlyuk, dev; +Cc: Thomas Monjalon, David Marchand

On 4/15/2021 11:10 PM, Dmitry Kozlyuk wrote:
> Most modern and actively maintained distribution of libpcap for Windows
> is Npcap [1]. It currently doesn't provide a pkg-config file [2].
> By default it is installed to C:\Program Files\Npcap and can be located
> using standard environment variables [3]:
> 
>      $env:C_INCLUDE_PATH += ";C:\Program Files\Npcap"
>      $env:LIBRARY_PATH += ";C:\Program Files\Npcap\Lib\x64"     # MinGW
>      $env:LINK += ' /LIBPATH:"C:\Program Files\Npcap\Lib\x64"'  # Clang
> 
> The following libpcap.pc also works if placed in PKG_CONFIG_PATH:
> 
>      prefix="C:/Program Files/Npcap"
>      Name: libpcap
>      Version: 1.10
>      Description: Platform-independent network traffic capture library
>      Cflags: -I${prefix}/Include
>      Libs: -L${prefix}/Lib/x64 -lwpcap
> 
> Example of collecting packets from an interface to a file:
> 
>      .\build\examples\dpdk-skeleton.exe `
>          --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
>          --vdev "eth_pcap1,tx_pcap=capture.pcap"
> 
> Interface name can be obtained as follows, with Wireshark installed:
> 
>      & "C:\Program Files\Wireshark\tshark.exe" -D
> 
> Implementation in "pcap_osdep_windows.c" does some guesswork to convert
> between variants of an interface name. Microsoft experts and interested
> users, please take a look and/or give it a try in your environment.
> 
> [1]: https://nmap.org/npcap
> [2]: https://github.com/nmap/npcap/issues/299
> [3]: https://mesonbuild.com/Reference-manual.html#compiler-object
> 
> v4:
>      * Change libpcap discovery to work without dependent patch.
>      * Fix memory leak in osdep_iface_mac_get (in v3, actually).
>      * rte_os_internal.h -> rte_os_shim.h in patch 3/3.
> 
> Dmitry Kozlyuk (3):
>    eal/windows: add timespec_get shim for MinGW
>    net/pcap: move OS-dependent code to separate files
>    net/pcap: build on Windows
> 


Hi Dmitry,

Since the dependent patches merged, I checked/tested the set and it looks good 
to me, pcap patch already has my review tag.

But not able to test the pcap on Windows. Because if Windows & eal part of the 
patch, I am delegating it to Thomas in patchwork.

>   config/meson.build                            |   5 +-
>   doc/guides/rel_notes/release_21_05.rst        |   4 +
>   drivers/net/pcap/meson.build                  |  16 +--
>   .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 109 +++-------------
>   drivers/net/pcap/pcap_osdep.h                 |  18 +++
>   drivers/net/pcap/pcap_osdep_freebsd.c         |  59 +++++++++
>   drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
>   drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++++++++++++
>   lib/librte_eal/windows/include/rte_os_shim.h  |  32 +++++
>   9 files changed, 304 insertions(+), 99 deletions(-)
>   rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
>   create mode 100644 drivers/net/pcap/pcap_osdep.h
>   create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
>   create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
>   create mode 100644 drivers/net/pcap/pcap_osdep_windows.c
> 


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows
  2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows Dmitry Kozlyuk
@ 2021-04-19 21:05         ` Tyler Retzlaff
  0 siblings, 0 replies; 67+ messages in thread
From: Tyler Retzlaff @ 2021-04-19 21:05 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: dev, Bruce Richardson, Ferruh Yigit

On Fri, Apr 16, 2021 at 01:10:55AM +0300, Dmitry Kozlyuk wrote:
> Implement OS-dependent functions and enable build for Windows.
> Account for different library name in Windows libpcap distributions.
> 
> Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>

Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com>

> ---
> Tyler, IIRC you were reviewing the code?
> This patch is the most important one but surprisingly has no acks.
> ---
>  config/meson.build                     |   5 +-
>  doc/guides/rel_notes/release_21_05.rst |   4 +
>  drivers/net/pcap/meson.build           |  11 ++-
>  drivers/net/pcap/pcap_ethdev.c         |   5 +-
>  drivers/net/pcap/pcap_osdep.h          |   5 ++
>  drivers/net/pcap/pcap_osdep_windows.c  | 118 +++++++++++++++++++++++++
>  6 files changed, 136 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/net/pcap/pcap_osdep_windows.c
> 
> diff --git a/config/meson.build b/config/meson.build
> index 6e6ef8c0e1..6737cc3e26 100644
> --- a/config/meson.build
> +++ b/config/meson.build
> @@ -182,13 +182,14 @@ endif
>  
>  # check for pcap
>  pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
> +pcap_lib = is_windows ? 'wpcap' : 'pcap'
>  if not pcap_dep.found()
>  	# pcap got a pkg-config file only in 1.9.0
> -	pcap_dep = cc.find_library('pcap', required: false)
> +	pcap_dep = cc.find_library(pcap_lib, required: false)
>  endif
>  if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
>  	dpdk_conf.set('RTE_PORT_PCAP', 1)
> -	dpdk_extra_ldflags += '-lpcap'
> +	dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
>  endif
>  
>  # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
> diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
> index 2e3bf5c95a..ed0e23a47b 100644
> --- a/doc/guides/rel_notes/release_21_05.rst
> +++ b/doc/guides/rel_notes/release_21_05.rst
> @@ -174,6 +174,10 @@ New Features
>    * Added command to display Rx queue used descriptor count.
>      ``show port (port_id) rxq (queue_id) desc used count``
>  
> +* **Enabled libpcap-based PMD on Windows.**
> +
> +   A libpcap distribution, such as Npcap or WinPcap, is required to run the PMD.
> +
>  
>  Removed Items
>  -------------
> diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
> index 26b6066990..63ad3f34f0 100644
> --- a/drivers/net/pcap/meson.build
> +++ b/drivers/net/pcap/meson.build
> @@ -1,18 +1,17 @@
>  # SPDX-License-Identifier: BSD-3-Clause
>  # Copyright(c) 2017 Intel Corporation
>  
> -if is_windows
> -	build = false
> -	reason = 'not supported on Windows'
> -	subdir_done()
> -endif
> -
>  if not dpdk_conf.has('RTE_PORT_PCAP')
>  	build = false
>  	reason = 'missing dependency, "libpcap"'
>  endif
> +
>  sources = files(
>  	'pcap_ethdev.c',
>  	'pcap_osdep_@0@.c'.format(exec_env),
>  )
> +
>  ext_deps += pcap_dep
> +if is_windows
> +	ext_deps += cc.find_library('iphlpapi', required: true)
> +endif
> diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
> index 4ac594eeca..3961843efc 100644
> --- a/drivers/net/pcap/pcap_ethdev.c
> +++ b/drivers/net/pcap/pcap_ethdev.c
> @@ -15,6 +15,7 @@
>  #include <rte_malloc.h>
>  #include <rte_mbuf.h>
>  #include <rte_bus_vdev.h>
> +#include <rte_os_shim.h>
>  
>  #include "pcap_osdep.h"
>  
> @@ -141,10 +142,6 @@ static struct rte_eth_link pmd_link = {
>  
>  RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
>  
> -#define PMD_LOG(level, fmt, args...) \
> -	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
> -		"%s(): " fmt "\n", __func__, ##args)
> -
>  static struct queue_missed_stat*
>  queue_missed_stat_update(struct rte_eth_dev *dev, unsigned int qid)
>  {
> diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
> index 9de422ab8d..bf41cba982 100644
> --- a/drivers/net/pcap/pcap_osdep.h
> +++ b/drivers/net/pcap/pcap_osdep.h
> @@ -7,6 +7,11 @@
>  
>  #include <rte_ether.h>
>  
> +#define PMD_LOG(level, fmt, args...) \
> +	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
> +		"%s(): " fmt "\n", __func__, ##args)
> +extern int eth_pcap_logtype;
> +
>  int osdep_iface_index_get(const char *name);
>  int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
>  
> diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
> new file mode 100644
> index 0000000000..1d398dc7ed
> --- /dev/null
> +++ b/drivers/net/pcap/pcap_osdep_windows.c
> @@ -0,0 +1,118 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2021 Dmitry Kozlyuk
> + */
> +
> +#include <winsock2.h>
> +#include <iphlpapi.h>
> +#include <strsafe.h>
> +
> +#include "pcap_osdep.h"
> +
> +/*
> + * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
> + * Return NULL if "{GUID}" part is not found.
> + */
> +static const char *
> +iface_guid(const char *name)
> +{
> +	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
> +
> +	const char *ob, *cb;
> +
> +	ob = strchr(name, '{');
> +	if (ob == NULL)
> +		return NULL;
> +
> +	cb = strchr(ob, '}');
> +	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
> +		return NULL;
> +
> +	return ob;
> +}
> +
> +/*
> + * libpcap takes device names like "\Device\NPF_{GUID}",
> + * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
> + * Try to convert, fall back to original device name.
> + */
> +int
> +osdep_iface_index_get(const char *device_name)
> +{
> +	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
> +	const char *guid;
> +	ULONG index;
> +	DWORD ret;
> +
> +	guid = iface_guid(device_name);
> +	if (guid != NULL)
> +		StringCbPrintfW(adapter_name, sizeof(adapter_name),
> +			L"\\DEVICE\\TCPIP_%S", guid);
> +	else
> +		StringCbPrintfW(adapter_name, sizeof(adapter_name),
> +			L"%S", device_name);
> +
> +	ret = GetAdapterIndex(adapter_name, &index);
> +	if (ret != NO_ERROR) {
> +		PMD_LOG(ERR, "GetAdapterIndex(%S) = %lu\n", adapter_name, ret);
> +		return -1;
> +	}
> +
> +	return index;
> +}
> +
> +/*
> + * libpcap takes device names like "\Device\NPF_{GUID}",
> + * GetAdaptersAddresses() returns names in "{GUID}" form.
> + * Try to extract GUID from device name, fall back to original device name.
> + */
> +int
> +osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
> +{
> +	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
> +	ULONG size, sys_ret;
> +	const char *adapter_name;
> +	int ret = -1;
> +
> +	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
> +	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
> +		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
> +			sys_ret, ERROR_BUFFER_OVERFLOW);
> +		return -1;
> +	}
> +
> +	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
> +	if (info == NULL) {
> +		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
> +		return -1;
> +	}
> +
> +	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
> +	if (sys_ret != ERROR_SUCCESS) {
> +		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
> +		free(info);
> +		return -1;
> +	}
> +
> +	adapter_name = iface_guid(device_name);
> +	if (adapter_name == NULL)
> +		adapter_name = device_name;
> +
> +	for (cur = info; cur != NULL; cur = cur->Next) {
> +		if (strcmp(cur->AdapterName, adapter_name) == 0) {
> +			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
> +				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
> +					RTE_ETHER_ADDR_LEN,
> +					cur->PhysicalAddressLength);
> +				break;
> +			}
> +
> +			memcpy(mac->addr_bytes, cur->PhysicalAddress,
> +				RTE_ETHER_ADDR_LEN);
> +			ret = 0;
> +			break;
> +		}
> +	}
> +
> +	free(info);
> +	return ret;
> +}
> -- 
> 2.29.3

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/3] net/pcap: build on Windows
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
                         ` (3 preceding siblings ...)
  2021-04-16 17:22       ` [dpdk-dev] [PATCH v4 0/3] " Ferruh Yigit
@ 2021-04-20 22:20       ` Thomas Monjalon
  2021-04-21 14:53         ` Dmitry Kozlyuk
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
  5 siblings, 1 reply; 67+ messages in thread
From: Thomas Monjalon @ 2021-04-20 22:20 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: dev

> Dmitry Kozlyuk (3):
>   eal/windows: add timespec_get shim for MinGW
>   net/pcap: move OS-dependent code to separate files
>   net/pcap: build on Windows

Compilation is failing on FreeBSD 11:
http://mails.dpdk.org/archives/test-report/2021-April/188997.html
	implicit declaration of function 'timespec_get' is invalid in C99
	use of undeclared identifier 'TIME_UTC'

It should be fixed by including time.h

I cannot reproduce the issue with FreeBSD 12.




^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/3] net/pcap: build on Windows
  2021-04-20 22:20       ` Thomas Monjalon
@ 2021-04-21 14:53         ` Dmitry Kozlyuk
  2021-04-21 18:12           ` Thomas Monjalon
  0 siblings, 1 reply; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-21 14:53 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

2021-04-21 00:20 (UTC+0200), Thomas Monjalon:
> > Dmitry Kozlyuk (3):
> >   eal/windows: add timespec_get shim for MinGW
> >   net/pcap: move OS-dependent code to separate files
> >   net/pcap: build on Windows  
> 
> Compilation is failing on FreeBSD 11:
> http://mails.dpdk.org/archives/test-report/2021-April/188997.html
> 	implicit declaration of function 'timespec_get' is invalid in C99
> 	use of undeclared identifier 'TIME_UTC'
> 
> It should be fixed by including time.h 

No, FreeBSD 11 is missing timespec_get indeed.

> I cannot reproduce the issue with FreeBSD 12.

After adding a FreeBSD 11 shim and rebasing over "main"
I get another error unrelated to the patch.
It seems FreeBSD 11 is missing pthread_setname_np() as well.

[11/1847] Compiling C object lib/librte_telemetry.a.p/telemetry_telemetry.c.o
../src/lib/telemetry/telemetry.c:445:2: warning: implicit declaration of function 'pthread_setname_np' is invalid in C99 [-Wimplicit-function-declaration]
        pthread_setname_np(t_old, "telemetry-v1");
        ^
../src/lib/telemetry/telemetry.c:474:2: warning: implicit declaration of function 'pthread_setname_np' is invalid in C99 [-Wimplicit-function-declaration]
        pthread_setname_np(t_new, "telemetry-v2");
        ^
2 warnings generated.
[60/1847] Linking target lib/librte_telemetry.so.21.2
FAILED: lib/librte_telemetry.so.21.2 
cc  -o lib/librte_telemetry.so.21.2 lib/librte_telemetry.a.p/telemetry_telemetry.c.o lib/librte_telemetry.a.p/telemetry_telemetry_data.c.o lib/librte_telemetry.a.p/telemetry_telemetry_legacy.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,-O1 -shared -fPIC -Wl,--start-group -Wl,-soname,librte_telemetry.so.21 -Wl,--no-as-needed -pthread -lm -lexecinfo -Wl,--end-group -Wl,--version-script=/tmp/src/lib/telemetry/version.map
lib/librte_telemetry.a.p/telemetry_telemetry.c.o: In function `rte_telemetry_init':
telemetry.c:(.text.internal+0x15a): undefined reference to `pthread_setname_np'
telemetry.c:(.text.internal+0x24d): undefined reference to `pthread_setname_np'
cc: error: linker command failed with exit code 1 (use -v to see invocation)

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/3] net/pcap: build on Windows
  2021-04-21 14:53         ` Dmitry Kozlyuk
@ 2021-04-21 18:12           ` Thomas Monjalon
  0 siblings, 0 replies; 67+ messages in thread
From: Thomas Monjalon @ 2021-04-21 18:12 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: dev

21/04/2021 16:53, Dmitry Kozlyuk:
> 2021-04-21 00:20 (UTC+0200), Thomas Monjalon:
> > > Dmitry Kozlyuk (3):
> > >   eal/windows: add timespec_get shim for MinGW
> > >   net/pcap: move OS-dependent code to separate files
> > >   net/pcap: build on Windows  
> > 
> > Compilation is failing on FreeBSD 11:
> > http://mails.dpdk.org/archives/test-report/2021-April/188997.html
> > 	implicit declaration of function 'timespec_get' is invalid in C99
> > 	use of undeclared identifier 'TIME_UTC'
> > 
> > It should be fixed by including time.h 
> 
> No, FreeBSD 11 is missing timespec_get indeed.
> 
> > I cannot reproduce the issue with FreeBSD 12.
> 
> After adding a FreeBSD 11 shim and rebasing over "main"
> I get another error unrelated to the patch.
> It seems FreeBSD 11 is missing pthread_setname_np() as well.
> 
> [11/1847] Compiling C object lib/librte_telemetry.a.p/telemetry_telemetry.c.o
> ../src/lib/telemetry/telemetry.c:445:2: warning: implicit declaration of function 'pthread_setname_np' is invalid in C99 [-Wimplicit-function-declaration]
>         pthread_setname_np(t_old, "telemetry-v1");
>         ^
> ../src/lib/telemetry/telemetry.c:474:2: warning: implicit declaration of function 'pthread_setname_np' is invalid in C99 [-Wimplicit-function-declaration]
>         pthread_setname_np(t_new, "telemetry-v2");
>         ^

Sorry, that's because I've merged a patch which is failing
with FreeBSD < 12.2 and I missed the CI report.

I am fixing with this patch:
https://patches.dpdk.org/project/dpdk/patch/20210421181157.1634301-1-thomas@monjalon.net/



^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v5 0/3] net/pcap: build on Windows
  2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
                         ` (4 preceding siblings ...)
  2021-04-20 22:20       ` Thomas Monjalon
@ 2021-04-21 19:33       ` Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 1/3] eal: add timespec_get shim Dmitry Kozlyuk
                           ` (3 more replies)
  5 siblings, 4 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-21 19:33 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk

Most modern and actively maintained distribution of libpcap for Windows
is Npcap [1]. It currently doesn't provide a pkg-config file [2].
By default it is installed to C:\Program Files\Npcap and can be located
using standard environment variables [3]:

    $env:C_INCLUDE_PATH += ";C:\Program Files\Npcap"
    $env:LIBRARY_PATH += ";C:\Program Files\Npcap\Lib\x64"     # MinGW
    $env:LINK += ' /LIBPATH:"C:\Program Files\Npcap\Lib\x64"'  # Clang

The following libpcap.pc also works if placed in PKG_CONFIG_PATH:

    prefix="C:/Program Files/Npcap"
    Name: libpcap
    Version: 1.10
    Description: Platform-independent network traffic capture library
    Cflags: -I${prefix}/Include
    Libs: -L${prefix}/Lib/x64 -lwpcap

Example of collecting packets from an interface to a file:

    .\build\examples\dpdk-skeleton.exe `
        --vdev "eth_pcap0,iface=\Device\NPF_{DDD48985-A77C-4FC9-AF48-61E547C8797E}" `
        --vdev "eth_pcap1,tx_pcap=capture.pcap"

Interface name can be obtained as follows, with Wireshark installed:

    & "C:\Program Files\Wireshark\tshark.exe" -D

[1]: https://nmap.org/npcap
[2]: https://github.com/nmap/npcap/issues/299
[3]: https://mesonbuild.com/Reference-manual.html#compiler-object

v5:
    * Add timespec_get() shim for FreeBSD < 12.2 (CI, Thomas).   

Dmitry Kozlyuk (3):
  eal: add timespec_get shim
  net/pcap: move OS-dependent code to separate files
  net/pcap: build on Windows

 config/meson.build                            |   9 +-
 doc/guides/rel_notes/release_21_05.rst        |   4 +
 drivers/net/pcap/meson.build                  |  16 +--
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 109 +++-------------
 drivers/net/pcap/pcap_osdep.h                 |  18 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 +++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 drivers/net/pcap/pcap_osdep_windows.c         | 118 ++++++++++++++++++
 lib/eal/freebsd/include/rte_os_shim.h         |  17 +++
 lib/eal/windows/include/rte_os_shim.h         |  32 +++++
 10 files changed, 323 insertions(+), 101 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v5 1/3] eal: add timespec_get shim
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
@ 2021-04-21 19:33         ` Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-21 19:33 UTC (permalink / raw)
  To: dev
  Cc: Dmitry Kozlyuk, Jie Zhou, Nick Connolly, Bruce Richardson,
	Narcisa Ana Maria Vasile, Dmitry Malloy, Pallavi Kadam

C11 timespec_get() is not provided on some platforms:

* MinGW-w64 does not currently implement it [1].
* FreeBSD 11 with Clang 10.0.0 does not provide it.

Add internal shims to Windows and FreeBSD EALs.
For Windows, it can be removed after [1] is fixed.

[1]: https://sourceforge.net/p/mingw-w64/mailman/message/37224689/

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Acked-by: Jie Zhou <jizh@linux.microsoft.com>
Acked-by: Nick Connolly <nick.connolly@mayadata.io>
---
 lib/eal/freebsd/include/rte_os_shim.h | 17 ++++++++++++++
 lib/eal/windows/include/rte_os_shim.h | 32 +++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/lib/eal/freebsd/include/rte_os_shim.h b/lib/eal/freebsd/include/rte_os_shim.h
index 1e85229ca9..10b51b802f 100644
--- a/lib/eal/freebsd/include/rte_os_shim.h
+++ b/lib/eal/freebsd/include/rte_os_shim.h
@@ -3,6 +3,8 @@
 #ifndef _RTE_OS_SHIM_
 #define _RTE_OS_SHIM_
 
+#include <time.h>
+
 #include <rte_os.h>
 
 /**
@@ -11,4 +13,19 @@
  * Provides semi-standard OS facilities by convenient names.
  */
 
+#ifndef TIME_UTC
+
+#define TIME_UTC 1
+
+static inline int
+rte_timespec_get(struct timespec *now, int base)
+{
+	if (base != TIME_UTC || clock_gettime(CLOCK_REALTIME, now) < 0)
+		return 0;
+	return base;
+}
+
+#define timespec_get(ts, base) rte_timespec_get(ts, base)
+
+#endif /* !defined TIME_UTC */
 #endif /* _RTE_OS_SHIM_ */
diff --git a/lib/eal/windows/include/rte_os_shim.h b/lib/eal/windows/include/rte_os_shim.h
index f40fb62d1d..e50895fd83 100644
--- a/lib/eal/windows/include/rte_os_shim.h
+++ b/lib/eal/windows/include/rte_os_shim.h
@@ -3,7 +3,10 @@
 #ifndef _RTE_OS_SHIM_
 #define _RTE_OS_SHIM_
 
+#include <time.h>
+
 #include <rte_os.h>
+#include <rte_windows.h>
 
 /**
  * @file
@@ -33,4 +36,33 @@
 #define IPPROTO_SCTP	132
 #endif
 
+#ifdef RTE_TOOLCHAIN_GCC
+
+#define TIME_UTC 1
+
+static inline int
+rte_timespec_get(struct timespec *now, int base)
+{
+	/* 100ns ticks from 1601-01-01 to 1970-01-01 */
+	static const uint64_t EPOCH = 116444736000000000ULL;
+	static const uint64_t TICKS_PER_SEC = 10000000;
+	static const uint64_t NS_PER_TICK = 100;
+
+	FILETIME ft;
+	uint64_t ticks;
+
+	if (base != TIME_UTC)
+		return 0;
+
+	GetSystemTimePreciseAsFileTime(&ft);
+	ticks = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+	ticks -= EPOCH;
+	now->tv_sec = ticks / TICKS_PER_SEC;
+	now->tv_nsec = (ticks - now->tv_sec * TICKS_PER_SEC) * NS_PER_TICK;
+	return base;
+}
+
+#define timespec_get(ts, base) rte_timespec_get(ts, base)
+
+#endif /* RTE_TOOLCHAIN_GCC */
 #endif /* _RTE_OS_SHIM_ */
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v5 2/3] net/pcap: move OS-dependent code to separate files
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 1/3] eal: add timespec_get shim Dmitry Kozlyuk
@ 2021-04-21 19:33         ` Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 3/3] net/pcap: build on Windows Dmitry Kozlyuk
  2021-04-21 21:54         ` [dpdk-dev] [PATCH v5 0/3] " Thomas Monjalon
  3 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-21 19:33 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk, Ferruh Yigit

PCAP PMD queries interface information differently for Linux and
FreeBSD, OS-specific code is guarded by #ifdef. This PMD also depends on
POSIX bits, namely gettimeofday() and NAME_MAX.

Move OS-dependent code to separate files.
Replace POSIX bits with DPDK equivalents.
Rename rte_eth_pcap.c to pcap_ethdev.c, like it is in most other PMDs.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 drivers/net/pcap/meson.build                  |   5 +-
 .../pcap/{rte_eth_pcap.c => pcap_ethdev.c}    | 104 +++---------------
 drivers/net/pcap/pcap_osdep.h                 |  13 +++
 drivers/net/pcap/pcap_osdep_freebsd.c         |  59 ++++++++++
 drivers/net/pcap/pcap_osdep_linux.c           |  42 +++++++
 5 files changed, 136 insertions(+), 87 deletions(-)
 rename drivers/net/pcap/{rte_eth_pcap.c => pcap_ethdev.c} (95%)
 create mode 100644 drivers/net/pcap/pcap_osdep.h
 create mode 100644 drivers/net/pcap/pcap_osdep_freebsd.c
 create mode 100644 drivers/net/pcap/pcap_osdep_linux.c

diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 61c0551582..d02a98b6f4 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')
     build = false
     reason = 'missing dependency, "libpcap"'
 endif
-sources = files('rte_eth_pcap.c')
+sources = files(
+	'pcap_ethdev.c',
+	'pcap_osdep_@0@.c'.format(exec_env),
+)
 ext_deps += pcap_dep
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/pcap_ethdev.c
similarity index 95%
rename from drivers/net/pcap/rte_eth_pcap.c
rename to drivers/net/pcap/pcap_ethdev.c
index ef50d088f3..5ff7339e97 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -6,16 +6,6 @@
 
 #include <time.h>
 
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#if defined(RTE_EXEC_ENV_FREEBSD)
-#include <sys/sysctl.h>
-#include <net/if_dl.h>
-#endif
-
 #include <pcap.h>
 
 #include <rte_cycles.h>
@@ -26,7 +16,8 @@
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
 #include <rte_bus_vdev.h>
-#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
 
 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
 #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
@@ -47,7 +38,7 @@
 #define RTE_PMD_PCAP_MAX_QUEUES 16
 
 static char errbuf[PCAP_ERRBUF_SIZE];
-static struct timeval start_time;
+static struct timespec start_time;
 static uint64_t start_cycles;
 static uint64_t hz;
 static uint8_t iface_idx;
@@ -355,17 +346,21 @@ eth_null_rx(void *queue __rte_unused,
 
 #define NSEC_PER_SEC	1000000000L
 
+/*
+ * This function stores nanoseconds in `tv_usec` field of `struct timeval`,
+ * because `ts` goes directly to nanosecond-precision dump.
+ */
 static inline void
 calculate_timestamp(struct timeval *ts) {
 	uint64_t cycles;
-	struct timeval cur_time;
+	struct timespec cur_time;
 
 	cycles = rte_get_timer_cycles() - start_cycles;
 	cur_time.tv_sec = cycles / hz;
-	cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz;
+	cur_time.tv_nsec = (cycles % hz) * NSEC_PER_SEC / hz;
 
 	ts->tv_sec = start_time.tv_sec + cur_time.tv_sec;
-	ts->tv_usec = start_time.tv_usec + cur_time.tv_usec;
+	ts->tv_usec = start_time.tv_nsec + cur_time.tv_nsec;
 	if (ts->tv_usec >= NSEC_PER_SEC) {
 		ts->tv_usec -= NSEC_PER_SEC;
 		ts->tv_sec += 1;
@@ -884,7 +879,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 
 	if (internals->infinite_rx) {
 		struct pmd_process_private *pp;
-		char ring_name[NAME_MAX];
+		char ring_name[RTE_RING_NAMESIZE];
 		static uint32_t ring_number;
 		uint64_t pcap_pkt_count = 0;
 		struct rte_mbuf *bufs[1];
@@ -1262,84 +1257,20 @@ static int
 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
 		const unsigned int numa_node)
 {
-#if defined(RTE_EXEC_ENV_LINUX)
 	void *mac_addrs;
-	struct ifreq ifr;
-	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-	if (if_fd == -1)
-		return -1;
+	struct rte_ether_addr mac;
 
-	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
-		close(if_fd);
+	if (osdep_iface_mac_get(if_name, &mac) < 0)
 		return -1;
-	}
 
 	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		close(if_fd);
+	if (mac_addrs == NULL)
 		return -1;
-	}
 
 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
+	rte_memcpy(mac_addrs, mac.addr_bytes, RTE_ETHER_ADDR_LEN);
 	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
-
-	close(if_fd);
-
-	return 0;
-
-#elif defined(RTE_EXEC_ENV_FREEBSD)
-	void *mac_addrs;
-	struct if_msghdr *ifm;
-	struct sockaddr_dl *sdl;
-	int mib[6];
-	size_t len = 0;
-	char *buf;
-
-	mib[0] = CTL_NET;
-	mib[1] = AF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_LINK;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = if_nametoindex(if_name);
-
-	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
-		return -1;
-
-	if (len == 0)
-		return -1;
-
-	buf = rte_malloc(NULL, len, 0);
-	if (!buf)
-		return -1;
-
-	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
-		rte_free(buf);
-		return -1;
-	}
-	ifm = (struct if_msghdr *)buf;
-	sdl = (struct sockaddr_dl *)(ifm + 1);
-
-	mac_addrs = rte_zmalloc_socket(NULL, RTE_ETHER_ADDR_LEN, 0, numa_node);
-	if (!mac_addrs) {
-		rte_free(buf);
-		return -1;
-	}
-
-	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
-	eth_dev->data->mac_addrs = mac_addrs;
-	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
-			LLADDR(sdl), RTE_ETHER_ADDR_LEN);
-
-	rte_free(buf);
-
 	return 0;
-#else
-	return -1;
-#endif
 }
 
 static int
@@ -1401,7 +1332,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 	internals->single_iface = single_iface;
 
 	if (single_iface) {
-		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
+		internals->if_index =
+			osdep_iface_index_get(rx_queues->queue[0].name);
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
@@ -1454,7 +1386,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	name = rte_vdev_device_name(dev);
 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
 
-	gettimeofday(&start_time, NULL);
+	timespec_get(&start_time, TIME_UTC);
 	start_cycles = rte_get_timer_cycles();
 	hz = rte_get_timer_hz();
 
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
new file mode 100644
index 0000000000..9de422ab8d
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#ifndef _RTE_PCAP_OSDEP_
+#define _RTE_PCAP_OSDEP_
+
+#include <rte_ether.h>
+
+int osdep_iface_index_get(const char *name);
+int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
+
+#endif
diff --git a/drivers/net/pcap/pcap_osdep_freebsd.c b/drivers/net/pcap/pcap_osdep_freebsd.c
new file mode 100644
index 0000000000..20556b3e92
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_freebsd.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	int mib[6];
+	size_t len = 0;
+	char *buf;
+
+	mib[0] = CTL_NET;
+	mib[1] = AF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = if_nametoindex(if_name);
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
+		return -1;
+
+	if (len == 0)
+		return -1;
+
+	buf = rte_malloc(NULL, len, 0);
+	if (!buf)
+		return -1;
+
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		rte_free(buf);
+		return -1;
+	}
+	ifm = (struct if_msghdr *)buf;
+	sdl = (struct sockaddr_dl *)(ifm + 1);
+
+	rte_memcpy(mac->addr_bytes, LLADDR(sdl), RTE_ETHER_ADDR_LEN);
+
+	rte_free(buf);
+	return 0;
+}
diff --git a/drivers/net/pcap/pcap_osdep_linux.c b/drivers/net/pcap/pcap_osdep_linux.c
new file mode 100644
index 0000000000..97033f57c5
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_linux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <rte_memcpy.h>
+#include <rte_string_fns.h>
+
+#include "pcap_osdep.h"
+
+int
+osdep_iface_index_get(const char *name)
+{
+	return if_nametoindex(name);
+}
+
+int
+osdep_iface_mac_get(const char *if_name, struct rte_ether_addr *mac)
+{
+	struct ifreq ifr;
+	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	if (if_fd == -1)
+		return -1;
+
+	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
+		close(if_fd);
+		return -1;
+	}
+
+	rte_memcpy(mac->addr_bytes, ifr.ifr_hwaddr.sa_data, RTE_ETHER_ADDR_LEN);
+
+	close(if_fd);
+	return 0;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [dpdk-dev] [PATCH v5 3/3] net/pcap: build on Windows
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 1/3] eal: add timespec_get shim Dmitry Kozlyuk
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
@ 2021-04-21 19:33         ` Dmitry Kozlyuk
  2021-04-21 21:54         ` [dpdk-dev] [PATCH v5 0/3] " Thomas Monjalon
  3 siblings, 0 replies; 67+ messages in thread
From: Dmitry Kozlyuk @ 2021-04-21 19:33 UTC (permalink / raw)
  To: dev; +Cc: Dmitry Kozlyuk, Tyler Retzlaff, Bruce Richardson, Ferruh Yigit

Implement OS-dependent functions and enable build for Windows.
Account for different library name in Windows libpcap distributions.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 config/meson.build                     |   9 +-
 doc/guides/rel_notes/release_21_05.rst |   4 +
 drivers/net/pcap/meson.build           |  11 ++-
 drivers/net/pcap/pcap_ethdev.c         |   5 +-
 drivers/net/pcap/pcap_osdep.h          |   5 ++
 drivers/net/pcap/pcap_osdep_windows.c  | 118 +++++++++++++++++++++++++
 6 files changed, 138 insertions(+), 14 deletions(-)
 create mode 100644 drivers/net/pcap/pcap_osdep_windows.c

diff --git a/config/meson.build b/config/meson.build
index 9e49abc0f8..d31ddef4e4 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -180,13 +180,14 @@ endif
 
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
+pcap_lib = is_windows ? 'wpcap' : 'pcap'
 if not pcap_dep.found()
-    # pcap got a pkg-config file only in 1.9.0
-    pcap_dep = cc.find_library('pcap', required: false)
+	# pcap got a pkg-config file only in 1.9.0
+	pcap_dep = cc.find_library(pcap_lib, required: false)
 endif
 if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
-    dpdk_conf.set('RTE_PORT_PCAP', 1)
-    dpdk_extra_ldflags += '-lpcap'
+	dpdk_conf.set('RTE_PORT_PCAP', 1)
+	dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
 endif
 
 # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 565e764811..3ba8e5ce7d 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -235,6 +235,10 @@ New Features
   * Added support for crypto adapter forward mode in octeontx2 event and crypto
     device driver.
 
+* **Enabled libpcap-based PMD on Windows.**
+
+   A libpcap distribution, such as Npcap or WinPcap, is required to run the PMD.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index d02a98b6f4..eec63a9b08 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build
@@ -1,18 +1,17 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-if is_windows
-    build = false
-    reason = 'not supported on Windows'
-    subdir_done()
-endif
-
 if not dpdk_conf.has('RTE_PORT_PCAP')
     build = false
     reason = 'missing dependency, "libpcap"'
 endif
+
 sources = files(
 	'pcap_ethdev.c',
 	'pcap_osdep_@0@.c'.format(exec_env),
 )
+
 ext_deps += pcap_dep
+if is_windows
+	ext_deps += cc.find_library('iphlpapi', required: true)
+endif
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 5ff7339e97..883a0c494a 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -16,6 +16,7 @@
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
 #include <rte_bus_vdev.h>
+#include <rte_os_shim.h>
 
 #include "pcap_osdep.h"
 
@@ -142,10 +143,6 @@ static struct rte_eth_link pmd_link = {
 
 RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE);
 
-#define PMD_LOG(level, fmt, args...) \
-	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
-		"%s(): " fmt "\n", __func__, ##args)
-
 static struct queue_missed_stat*
 queue_missed_stat_update(struct rte_eth_dev *dev, unsigned int qid)
 {
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 9de422ab8d..bf41cba982 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h
@@ -7,6 +7,11 @@
 
 #include <rte_ether.h>
 
+#define PMD_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
+		"%s(): " fmt "\n", __func__, ##args)
+extern int eth_pcap_logtype;
+
 int osdep_iface_index_get(const char *name);
 int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac);
 
diff --git a/drivers/net/pcap/pcap_osdep_windows.c b/drivers/net/pcap/pcap_osdep_windows.c
new file mode 100644
index 0000000000..1d398dc7ed
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep_windows.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 Dmitry Kozlyuk
+ */
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
+
+#include "pcap_osdep.h"
+
+/*
+ * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part.
+ * Return NULL if "{GUID}" part is not found.
+ */
+static const char *
+iface_guid(const char *name)
+{
+	static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */
+
+	const char *ob, *cb;
+
+	ob = strchr(name, '{');
+	if (ob == NULL)
+		return NULL;
+
+	cb = strchr(ob, '}');
+	if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */
+		return NULL;
+
+	return ob;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}".
+ * Try to convert, fall back to original device name.
+ */
+int
+osdep_iface_index_get(const char *device_name)
+{
+	WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH];
+	const char *guid;
+	ULONG index;
+	DWORD ret;
+
+	guid = iface_guid(device_name);
+	if (guid != NULL)
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"\\DEVICE\\TCPIP_%S", guid);
+	else
+		StringCbPrintfW(adapter_name, sizeof(adapter_name),
+			L"%S", device_name);
+
+	ret = GetAdapterIndex(adapter_name, &index);
+	if (ret != NO_ERROR) {
+		PMD_LOG(ERR, "GetAdapterIndex(%S) = %lu\n", adapter_name, ret);
+		return -1;
+	}
+
+	return index;
+}
+
+/*
+ * libpcap takes device names like "\Device\NPF_{GUID}",
+ * GetAdaptersAddresses() returns names in "{GUID}" form.
+ * Try to extract GUID from device name, fall back to original device name.
+ */
+int
+osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac)
+{
+	IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL;
+	ULONG size, sys_ret;
+	const char *adapter_name;
+	int ret = -1;
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
+	if (sys_ret != ERROR_BUFFER_OVERFLOW) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n",
+			sys_ret, ERROR_BUFFER_OVERFLOW);
+		return -1;
+	}
+
+	info = (IP_ADAPTER_ADDRESSES *)malloc(size);
+	if (info == NULL) {
+		PMD_LOG(ERR, "Cannot allocate adapter address info\n");
+		return -1;
+	}
+
+	sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size);
+	if (sys_ret != ERROR_SUCCESS) {
+		PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret);
+		free(info);
+		return -1;
+	}
+
+	adapter_name = iface_guid(device_name);
+	if (adapter_name == NULL)
+		adapter_name = device_name;
+
+	for (cur = info; cur != NULL; cur = cur->Next) {
+		if (strcmp(cur->AdapterName, adapter_name) == 0) {
+			if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) {
+				PMD_LOG(ERR, "Physical address length: want %u, got %lu",
+					RTE_ETHER_ADDR_LEN,
+					cur->PhysicalAddressLength);
+				break;
+			}
+
+			memcpy(mac->addr_bytes, cur->PhysicalAddress,
+				RTE_ETHER_ADDR_LEN);
+			ret = 0;
+			break;
+		}
+	}
+
+	free(info);
+	return ret;
+}
-- 
2.29.3


^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [dpdk-dev] [PATCH v5 0/3] net/pcap: build on Windows
  2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
                           ` (2 preceding siblings ...)
  2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 3/3] net/pcap: build on Windows Dmitry Kozlyuk
@ 2021-04-21 21:54         ` Thomas Monjalon
  3 siblings, 0 replies; 67+ messages in thread
From: Thomas Monjalon @ 2021-04-21 21:54 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: dev

> Dmitry Kozlyuk (3):
>   eal: add timespec_get shim
>   net/pcap: move OS-dependent code to separate files
>   net/pcap: build on Windows

Unfortunately the CI testing FreeBSD 11 is not running on this series,
but I feel it's OK to be part of the 21.05-rc1.

Applied, thanks



^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2021-04-21 21:54 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-14  1:20 [dpdk-dev] [PATCH 0/6] net/pcap: build on Windows Dmitry Kozlyuk
2021-02-14  1:20 ` [dpdk-dev] [PATCH 1/6] eal: add internal API for current time Dmitry Kozlyuk
2021-03-01 22:31   ` Nick Connolly
2021-03-01 22:36     ` Nick Connolly
2021-02-14  1:20 ` [dpdk-dev] [PATCH 2/6] net/pcap: fix format string Dmitry Kozlyuk
2021-03-01 22:33   ` Nick Connolly
2021-02-14  1:20 ` [dpdk-dev] [PATCH 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
2021-02-14  1:20 ` [dpdk-dev] [PATCH 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
2021-02-14  1:20 ` [dpdk-dev] [PATCH 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
2021-02-14  1:20 ` [dpdk-dev] [PATCH 6/6] net/pcap: build " Dmitry Kozlyuk
2021-02-14  2:16 ` [dpdk-dev] [PATCH v2 0/6] " Dmitry Kozlyuk
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 1/6] eal: add internal API for current time Dmitry Kozlyuk
2021-03-01 22:39     ` Nick Connolly
2021-03-05 17:50     ` Jie Zhou
2021-03-16  9:18     ` Thomas Monjalon
2021-03-16 18:59     ` Stephen Hemminger
2021-03-16 20:07       ` Dmitry Kozlyuk
2021-03-17  9:50         ` Morten Brørup
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 2/6] net/pcap: fix format string Dmitry Kozlyuk
2021-02-25 14:45     ` Ferruh Yigit
2021-03-02 11:48       ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 3/6] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
2021-02-25 14:51     ` Ferruh Yigit
2021-02-25 16:05       ` Dmitry Kozlyuk
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers Dmitry Kozlyuk
2021-02-25 14:59     ` Ferruh Yigit
2021-02-25 19:04       ` Dmitry Kozlyuk
2021-02-25 20:31         ` Nick Connolly
2021-02-25 23:10           ` Dmitry Kozlyuk
2021-03-01 21:43             ` Nick Connolly
2021-03-01 23:05               ` Dmitry Kozlyuk
2021-03-01 23:23                 ` Dmitry Kozlyuk
2021-03-02 11:22                 ` Nick Connolly
2021-03-03 16:32                   ` Dmitry Kozlyuk
2021-03-03 16:47                     ` Ferruh Yigit
2021-03-03 18:19                       ` Dmitry Kozlyuk
2021-03-03 19:30                         ` Ferruh Yigit
2021-03-03 23:03                           ` Dmitry Kozlyuk
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 5/6] config: discover libpcap on Windows Dmitry Kozlyuk
2021-02-25 15:02     ` Ferruh Yigit
2021-02-25 16:04       ` Dmitry Kozlyuk
2021-02-25 16:33         ` Bruce Richardson
2021-02-25 17:42           ` Dmitry Kozlyuk
2021-03-16  9:16             ` Thomas Monjalon
2021-03-16  9:37               ` Dmitry Kozlyuk
2021-02-14  2:16   ` [dpdk-dev] [PATCH v2 6/6] net/pcap: build " Dmitry Kozlyuk
2021-03-24  0:50   ` [dpdk-dev] [PATCH v3 0/3] " Dmitry Kozlyuk
2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
2021-03-24  0:50     ` [dpdk-dev] [PATCH v3 3/3] net/pcap: build on Windows Dmitry Kozlyuk
2021-04-09 10:51     ` [dpdk-dev] [PATCH v3 0/3] " Ferruh Yigit
2021-04-09 11:03       ` Dmitry Kozlyuk
2021-04-09 11:24         ` Ferruh Yigit
2021-04-15 22:10     ` [dpdk-dev] [PATCH v4 " Dmitry Kozlyuk
2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 1/3] eal/windows: add timespec_get shim for MinGW Dmitry Kozlyuk
2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
2021-04-15 22:10       ` [dpdk-dev] [PATCH v4 3/3] net/pcap: build on Windows Dmitry Kozlyuk
2021-04-19 21:05         ` Tyler Retzlaff
2021-04-16 17:22       ` [dpdk-dev] [PATCH v4 0/3] " Ferruh Yigit
2021-04-20 22:20       ` Thomas Monjalon
2021-04-21 14:53         ` Dmitry Kozlyuk
2021-04-21 18:12           ` Thomas Monjalon
2021-04-21 19:33       ` [dpdk-dev] [PATCH v5 " Dmitry Kozlyuk
2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 1/3] eal: add timespec_get shim Dmitry Kozlyuk
2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 2/3] net/pcap: move OS-dependent code to separate files Dmitry Kozlyuk
2021-04-21 19:33         ` [dpdk-dev] [PATCH v5 3/3] net/pcap: build on Windows Dmitry Kozlyuk
2021-04-21 21:54         ` [dpdk-dev] [PATCH v5 0/3] " Thomas Monjalon

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).