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
@@ -98,4 +100,19 @@ rte_ns_to_timespec(uint64_t nsec)returnts;}+/* Point of time with microsecond precision. */+structrte_time_us{+int64_tsec;/**< Number of whole seconds. */+int64_tusec;/**< Fractional part of second in [0, 999999]. */+};++/**+*Getcurrentsystemtime.+*+*@paramnow+*Receivescurrentsystemtime.+*/+__rte_internal+voidrte_time_get_us(structrte_time_us*now);+#endif /* _RTE_TIME_H_ */
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')build=falsereason='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.csimilarity index 95%rename from drivers/net/pcap/rte_eth_pcap.crename to drivers/net/pcap/pcap_ethdev.cindex 176928da3..a102897e9 100644--- a/drivers/net/pcap/rte_eth_pcap.c+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -1191,84 +1182,20 @@ static inteth_pcap_update_mac(constchar*if_name,structrte_eth_dev*eth_dev,constunsignedintnuma_node){-#if defined(RTE_EXEC_ENV_LINUX)void*mac_addrs;-structifreqifr;-intif_fd=socket(AF_INET,SOCK_DGRAM,0);--if(if_fd==-1)-return-1;+structrte_ether_addrmac;-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);--return0;--#elif defined(RTE_EXEC_ENV_FREEBSD)-void*mac_addrs;-structif_msghdr*ifm;-structsockaddr_dl*sdl;-intmib[6];-size_tlen=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=(structif_msghdr*)buf;-sdl=(structsockaddr_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);-return0;-#else-return-1;-#endif}staticint
@@ -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){
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 <redacted>
---
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
@@ -13,6 +13,7 @@ if not dpdk_conf.has('RTE_PORT_PCAP')endifsources=files('pcap_ethdev.c',+'pcap_osdep.c','pcap_osdep_@0@.c'.format(exec_env),)ext_deps+=pcap_dep
@@ -470,39 +470,39 @@ open_single_iface(const char *iface, pcap_t **pcap)}staticint-open_single_tx_pcap(constchar*pcap_filename,pcap_dumper_t**dumper)+open_single_tx_pcap(constchar*pcap_filename,osdep_pcap_dumper**dumper){-pcap_t*tx_pcap;+osdep_pcap*tx_pcap;/*-*Weneedtocreateadummyemptypcap_ttouseit-*withpcap_dump_open().WecreatebigenoughanEthernet+*Weneedtocreateadummyemptyosdep_pcaptouseit+*withosdep_pcap_dump_open().WecreatebigenoughanEthernet*pcapholder.*/-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);return0;}staticint-open_single_rx_pcap(constchar*pcap_filename,pcap_t**pcap)+open_single_rx_pcap(constchar*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)}staticuint64_t-count_packets_in_pcap(pcap_t**pcap,structpcap_rx_queue*pcap_q)+count_packets_in_pcap(osdep_pcap**pcap,structpcap_rx_queue*pcap_q){-constu_char*packet;-structpcap_pkthdrheader;+constuint8_t*packet;+structosdep_pcap_pkthdrheader;uint64_tpcap_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;gotostatus_down;
@@ -14,4 +15,53 @@intosdep_iface_index_get(constchar*name);intosdep_iface_mac_get(constchar*name,structrte_ether_addr*mac);+/*+*OnWindows,libpcap(npcaporWinPcap)exposesWin32APIwhichclashes+*withsomeDPDKconstructs.Triviallibpcapwrapperswith"osdep_"prefix+*areprovidedtoisolatePMDcodefromWin32API.+*/++#define OSDEP_DLT_EN10MB 1++#define OSDEP_PCAP_ERRBUF_SIZE 256++#define OSDEP_PCAP_TSTAMP_PRECISION_NANO 1++/** Handle for an open packet capture. */+typedefstructosdep_pcap_typeosdep_pcap;++/** Handle for an open packet dump. */+typedefstructosdep_pcap_dumper_typeosdep_pcap_dumper;++structosdep_pcap_pkthdr{+structrte_time_usts;+uint32_tcaplen;+uint32_tlen;+};++enumosdep_pcap_direction{+OSDEP_PCAP_D_INOUT=0,+OSDEP_PCAP_D_IN,+OSDEP_PCAP_D_OUT+};++osdep_pcap*osdep_pcap_open_live(constchar*device,intsnaplen,+intpromisc,intto_ms,char*errbuf);+osdep_pcap*osdep_pcap_open_offline(constchar*fname,char*errbuf);+osdep_pcap*osdep_pcap_open_dead_with_tstamp_precision(intlinktype,+intsnaplen,unsignedintprecision);+constuint8_t*osdep_pcap_next(osdep_pcap*pcap,+structosdep_pcap_pkthdr*header);+intosdep_pcap_sendpacket(osdep_pcap*pcap,constuint8_t*buf,intsize);+voidosdep_pcap_close(osdep_pcap*pcap);++osdep_pcap_dumper*osdep_pcap_dump_open(osdep_pcap*pcap,constchar*fname);+voidosdep_pcap_dump(uint8_t*user,conststructosdep_pcap_pkthdr*header,+constuint8_t*sp);+intosdep_pcap_dump_flush(osdep_pcap_dumper*p);+voidosdep_pcap_dump_close(osdep_pcap_dumper*p);++intosdep_pcap_setdirection(osdep_pcap*pcap,enumosdep_pcap_directiondir);+constchar*osdep_pcap_geterr(osdep_pcap*pcap);+#endif
@@ -178,9 +178,24 @@ if not pcap_dep.found()# pcap got a pkg-config file only in 1.9.0pcap_dep=cc.find_library('pcap',required:false)endif-ifpcap_dep.found()andcc.has_header('pcap.h',dependencies:pcap_dep)-dpdk_conf.set('RTE_PORT_PCAP',1)-dpdk_extra_ldflags+='-lpcap'+ifis_windows+# npcap SDK can be installed anywhere+pcap_sdk=get_option('pcap_sdk')+ifpcap_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+ifpcap_dep.found()+dpdk_conf.set('RTE_PORT_PCAP',1)+dpdk_extra_ldflags+=pcap_ldflags+endif+else+ifpcap_dep.found()andcc.has_header('pcap.h',dependencies:pcap_dep)+dpdk_conf.set('RTE_PORT_PCAP',1)+dpdk_extra_ldflags+='-lpcap'+endifendif# for clang 32-bit compiles we need libatomic for 64-bit atomic ops
@@ -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,
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
@@ -98,4 +100,19 @@ rte_ns_to_timespec(uint64_t nsec)returnts;}+/* Point of time with microsecond precision. */+structrte_time_us{+int64_tsec;/**< Number of whole seconds. */+int64_tusec;/**< Fractional part of second in [0, 999999]. */+};++/**+*Getcurrentsystemtime.+*+*@paramnow+*Receivescurrentsystemtime.+*/+__rte_internal+voidrte_time_get_us(structrte_time_us*now);+#endif /* _RTE_TIME_H_ */
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')build=falsereason='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.csimilarity index 95%rename from drivers/net/pcap/rte_eth_pcap.crename to drivers/net/pcap/pcap_ethdev.cindex 176928da3..a102897e9 100644--- a/drivers/net/pcap/rte_eth_pcap.c+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -1191,84 +1182,20 @@ static inteth_pcap_update_mac(constchar*if_name,structrte_eth_dev*eth_dev,constunsignedintnuma_node){-#if defined(RTE_EXEC_ENV_LINUX)void*mac_addrs;-structifreqifr;-intif_fd=socket(AF_INET,SOCK_DGRAM,0);--if(if_fd==-1)-return-1;+structrte_ether_addrmac;-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);--return0;--#elif defined(RTE_EXEC_ENV_FREEBSD)-void*mac_addrs;-structif_msghdr*ifm;-structsockaddr_dl*sdl;-intmib[6];-size_tlen=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=(structif_msghdr*)buf;-sdl=(structsockaddr_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);-return0;-#else-return-1;-#endif}staticint
@@ -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){
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 <redacted>
---
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
@@ -13,6 +13,7 @@ if not dpdk_conf.has('RTE_PORT_PCAP')endifsources=files('pcap_ethdev.c',+'pcap_osdep.c','pcap_osdep_@0@.c'.format(exec_env),)ext_deps+=pcap_dep
@@ -470,39 +470,39 @@ open_single_iface(const char *iface, pcap_t **pcap)}staticint-open_single_tx_pcap(constchar*pcap_filename,pcap_dumper_t**dumper)+open_single_tx_pcap(constchar*pcap_filename,osdep_pcap_dumper**dumper){-pcap_t*tx_pcap;+osdep_pcap*tx_pcap;/*-*Weneedtocreateadummyemptypcap_ttouseit-*withpcap_dump_open().WecreatebigenoughanEthernet+*Weneedtocreateadummyemptyosdep_pcaptouseit+*withosdep_pcap_dump_open().WecreatebigenoughanEthernet*pcapholder.*/-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);return0;}staticint-open_single_rx_pcap(constchar*pcap_filename,pcap_t**pcap)+open_single_rx_pcap(constchar*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)}staticuint64_t-count_packets_in_pcap(pcap_t**pcap,structpcap_rx_queue*pcap_q)+count_packets_in_pcap(osdep_pcap**pcap,structpcap_rx_queue*pcap_q){-constu_char*packet;-structpcap_pkthdrheader;+constuint8_t*packet;+structosdep_pcap_pkthdrheader;uint64_tpcap_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;gotostatus_down;
@@ -14,4 +15,53 @@intosdep_iface_index_get(constchar*name);intosdep_iface_mac_get(constchar*name,structrte_ether_addr*mac);+/*+*OnWindows,libpcap(npcaporWinPcap)exposesWin32APIwhichclashes+*withsomeDPDKconstructs.Triviallibpcapwrapperswith"osdep_"prefix+*areprovidedtoisolatePMDcodefromWin32API.+*/++#define OSDEP_DLT_EN10MB 1++#define OSDEP_PCAP_ERRBUF_SIZE 256++#define OSDEP_PCAP_TSTAMP_PRECISION_NANO 1++/** Handle for an open packet capture. */+typedefstructosdep_pcap_typeosdep_pcap;++/** Handle for an open packet dump. */+typedefstructosdep_pcap_dumper_typeosdep_pcap_dumper;++structosdep_pcap_pkthdr{+structrte_time_usts;+uint32_tcaplen;+uint32_tlen;+};++enumosdep_pcap_direction{+OSDEP_PCAP_D_INOUT=0,+OSDEP_PCAP_D_IN,+OSDEP_PCAP_D_OUT+};++osdep_pcap*osdep_pcap_open_live(constchar*device,intsnaplen,+intpromisc,intto_ms,char*errbuf);+osdep_pcap*osdep_pcap_open_offline(constchar*fname,char*errbuf);+osdep_pcap*osdep_pcap_open_dead_with_tstamp_precision(intlinktype,+intsnaplen,unsignedintprecision);+constuint8_t*osdep_pcap_next(osdep_pcap*pcap,+structosdep_pcap_pkthdr*header);+intosdep_pcap_sendpacket(osdep_pcap*pcap,constuint8_t*buf,intsize);+voidosdep_pcap_close(osdep_pcap*pcap);++osdep_pcap_dumper*osdep_pcap_dump_open(osdep_pcap*pcap,constchar*fname);+voidosdep_pcap_dump(uint8_t*user,conststructosdep_pcap_pkthdr*header,+constuint8_t*sp);+intosdep_pcap_dump_flush(osdep_pcap_dumper*p);+voidosdep_pcap_dump_close(osdep_pcap_dumper*p);++intosdep_pcap_setdirection(osdep_pcap*pcap,enumosdep_pcap_directiondir);+constchar*osdep_pcap_geterr(osdep_pcap*pcap);+#endif
@@ -178,9 +178,24 @@ if not pcap_dep.found()# pcap got a pkg-config file only in 1.9.0pcap_dep=cc.find_library('pcap',required:false)endif-ifpcap_dep.found()andcc.has_header('pcap.h',dependencies:pcap_dep)-dpdk_conf.set('RTE_PORT_PCAP',1)-dpdk_extra_ldflags+='-lpcap'+ifis_windows+# npcap SDK can be installed anywhere+pcap_sdk=get_option('pcap_sdk')+ifpcap_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+ifpcap_dep.found()+dpdk_conf.set('RTE_PORT_PCAP',1)+dpdk_extra_ldflags+=pcap_ldflags+endif+else+ifpcap_dep.found()andcc.has_header('pcap.h',dependencies:pcap_dep)+dpdk_conf.set('RTE_PORT_PCAP',1)+dpdk_extra_ldflags+='-lpcap'+endifendif# for clang 32-bit compiles we need libatomic for 64-bit atomic ops
@@ -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,
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 <redacted>
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 <redacted>
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 <redacted>
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..
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?
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.
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 <redacted>
From: Bruce Richardson <hidden> Date: 2021-02-25 16:33:52
On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
2021-02-25 15:02, Ferruh Yigit:
quoted
On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
quoted
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
On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
quoted
2021-02-25 15:02, Ferruh Yigit:
quoted
On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
quoted
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.
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.
From: Nick Connolly <hidden> Date: 2021-02-25 20:31:33
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
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?
From: Nick Connolly <hidden> Date: 2021-03-01 21:44:01
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
From: Nick Connolly <hidden> Date: 2021-03-01 22:31:41
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:
From: Nick Connolly <hidden> Date: 2021-03-01 22:36:05
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.
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.
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?
From: Nick Connolly <hidden> Date: 2021-03-02 11:22:49
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.
quoted
* 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.
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 <redacted>
Acked-by: Ferruh Yigit <redacted>
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.
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/
quoted
quoted
* 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.
quoted
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?
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/
quoted
quoted
quoted
* 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.
quoted
quoted
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. */
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
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 ...
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
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.
From: Thomas Monjalon <hidden> Date: 2021-03-16 09:16:35
25/02/2021 18:42, Dmitry Kozlyuk:
2021-02-25 16:33, Bruce Richardson:
quoted
On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
quoted
2021-02-25 15:02, Ferruh Yigit:
quoted
On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
quoted
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.
On Thu, Feb 25, 2021 at 07:04:38PM +0300, Dmitry Kozlyuk wrote:
quoted
2021-02-25 15:02, Ferruh Yigit:
quoted
On 2/14/2021 2:16 AM, Dmitry Kozlyuk wrote:
[...]
quoted
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.
quoted
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.
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.
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.
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:
quoted
On Sun, 14 Feb 2021 05:16:11 +0300
Dmitry Kozlyuk [off-list ref] wrote:
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.
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
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 <redacted>
---
.../windows/include/rte_os_internal.h | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')build=falsereason='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.csimilarity index 95%rename from drivers/net/pcap/rte_eth_pcap.crename to drivers/net/pcap/pcap_ethdev.cindex 28a5027315..1578de1204 100644--- a/drivers/net/pcap/rte_eth_pcap.c+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -1261,84 +1257,20 @@ static inteth_pcap_update_mac(constchar*if_name,structrte_eth_dev*eth_dev,constunsignedintnuma_node){-#if defined(RTE_EXEC_ENV_LINUX)void*mac_addrs;-structifreqifr;-intif_fd=socket(AF_INET,SOCK_DGRAM,0);--if(if_fd==-1)-return-1;+structrte_ether_addrmac;-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);--return0;--#elif defined(RTE_EXEC_ENV_FREEBSD)-void*mac_addrs;-structif_msghdr*ifm;-structsockaddr_dl*sdl;-intmib[6];-size_tlen=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=(structif_msghdr*)buf;-sdl=(structsockaddr_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);-return0;-#else-return-1;-#endif}staticint
@@ -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();
@@ -179,7 +179,8 @@ endifpcap_dep=dependency('libpcap',required:false,method:'pkg-config')ifnotpcap_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)endififpcap_dep.found()andcc.has_header('pcap.h',dependencies:pcap_dep)dpdk_conf.set('RTE_PORT_PCAP',1)
@@ -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 -------------
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
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.
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.
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
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 <redacted>
Acked-by: Jie Zhou <redacted>
Acked-by: Nick Connolly <redacted>
---
lib/librte_eal/windows/include/rte_os_shim.h | 32 ++++++++++++++++++++
1 file changed, 32 insertions(+)
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')build=falsereason='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.csimilarity index 95%rename from drivers/net/pcap/rte_eth_pcap.crename to drivers/net/pcap/pcap_ethdev.cindex 28a5027315..4ac594eeca 100644--- a/drivers/net/pcap/rte_eth_pcap.c+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -1261,84 +1256,20 @@ static inteth_pcap_update_mac(constchar*if_name,structrte_eth_dev*eth_dev,constunsignedintnuma_node){-#if defined(RTE_EXEC_ENV_LINUX)void*mac_addrs;-structifreqifr;-intif_fd=socket(AF_INET,SOCK_DGRAM,0);--if(if_fd==-1)-return-1;+structrte_ether_addrmac;-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);--return0;--#elif defined(RTE_EXEC_ENV_FREEBSD)-void*mac_addrs;-structif_msghdr*ifm;-structsockaddr_dl*sdl;-intmib[6];-size_tlen=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=(structif_msghdr*)buf;-sdl=(structsockaddr_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);-return0;-#else-return-1;-#endif}staticint
@@ -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();
Implement OS-dependent functions and enable build for Windows.
Account for different library name in Windows libpcap distributions.
Signed-off-by: Dmitry Kozlyuk <redacted>
---
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
@@ -182,13 +182,14 @@ endif# check for pcappcap_dep=dependency('libpcap',required:false,method:'pkg-config')+pcap_lib=is_windows?'wpcap':'pcap'ifnotpcap_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)endififpcap_dep.found()andcc.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
@@ -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 -------------
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.
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 <redacted>
Acked-by: Tyler Retzlaff <redacted>
quoted hunk
---
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
@@ -182,13 +182,14 @@ endif# check for pcappcap_dep=dependency('libpcap',required:false,method:'pkg-config')+pcap_lib=is_windows?'wpcap':'pcap'ifnotpcap_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)endififpcap_dep.found()andcc.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
@@ -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 -------------
From: Thomas Monjalon <hidden> Date: 2021-04-20 22:20:09
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.
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)
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");
^
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
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 <redacted>
Acked-by: Jie Zhou <redacted>
Acked-by: Nick Connolly <redacted>
---
lib/eal/freebsd/include/rte_os_shim.h | 17 ++++++++++++++
lib/eal/windows/include/rte_os_shim.h | 32 +++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
@@ -11,5 +11,8 @@ if not dpdk_conf.has('RTE_PORT_PCAP')build=falsereason='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.csimilarity index 95%rename from drivers/net/pcap/rte_eth_pcap.crename to drivers/net/pcap/pcap_ethdev.cindex ef50d088f3..5ff7339e97 100644--- a/drivers/net/pcap/rte_eth_pcap.c+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -1262,84 +1257,20 @@ static inteth_pcap_update_mac(constchar*if_name,structrte_eth_dev*eth_dev,constunsignedintnuma_node){-#if defined(RTE_EXEC_ENV_LINUX)void*mac_addrs;-structifreqifr;-intif_fd=socket(AF_INET,SOCK_DGRAM,0);--if(if_fd==-1)-return-1;+structrte_ether_addrmac;-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);--return0;--#elif defined(RTE_EXEC_ENV_FREEBSD)-void*mac_addrs;-structif_msghdr*ifm;-structsockaddr_dl*sdl;-intmib[6];-size_tlen=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=(structif_msghdr*)buf;-sdl=(structsockaddr_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);-return0;-#else-return-1;-#endif}staticint
@@ -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();
@@ -180,13 +180,14 @@ endif# check for pcappcap_dep=dependency('libpcap',required:false,method:'pkg-config')+pcap_lib=is_windows?'wpcap':'pcap'ifnotpcap_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)endififpcap_dep.found()andcc.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
@@ -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 -------------