1*8b26181fSAndroid Build Coastguard Worker /*
2*8b26181fSAndroid Build Coastguard Worker * Copyright (C) 2018 jingle YANG. All rights reserved.
3*8b26181fSAndroid Build Coastguard Worker *
4*8b26181fSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
5*8b26181fSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
6*8b26181fSAndroid Build Coastguard Worker * are met:
7*8b26181fSAndroid Build Coastguard Worker *
8*8b26181fSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
9*8b26181fSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
10*8b26181fSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
11*8b26181fSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
12*8b26181fSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
13*8b26181fSAndroid Build Coastguard Worker *
14*8b26181fSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
15*8b26181fSAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*8b26181fSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*8b26181fSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*8b26181fSAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*8b26181fSAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*8b26181fSAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*8b26181fSAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*8b26181fSAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*8b26181fSAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*8b26181fSAndroid Build Coastguard Worker * SUCH DAMAGE.
25*8b26181fSAndroid Build Coastguard Worker */
26*8b26181fSAndroid Build Coastguard Worker
27*8b26181fSAndroid Build Coastguard Worker /*
28*8b26181fSAndroid Build Coastguard Worker Date: Dec 16, 2018
29*8b26181fSAndroid Build Coastguard Worker
30*8b26181fSAndroid Build Coastguard Worker Description:
31*8b26181fSAndroid Build Coastguard Worker 1. Pcap-dpdk provides libpcap the ability to use DPDK with the device name as dpdk:{portid}, such as dpdk:0.
32*8b26181fSAndroid Build Coastguard Worker 2. DPDK is a set of libraries and drivers for fast packet processing. (https://www.dpdk.org/)
33*8b26181fSAndroid Build Coastguard Worker 3. The testprogs/capturetest provides 6.4Gbps/800,000 pps on Intel 10-Gigabit X540-AT2 with DPDK 18.11.
34*8b26181fSAndroid Build Coastguard Worker
35*8b26181fSAndroid Build Coastguard Worker Limitations:
36*8b26181fSAndroid Build Coastguard Worker 1. DPDK support will be on if DPDK is available. Please set DIR for --with-dpdk[=DIR] with ./configure or -DDPDK_DIR[=DIR] with cmake if DPDK is installed manually.
37*8b26181fSAndroid Build Coastguard Worker 2. Only support link libdpdk.so dynamically, because the libdpdk.a will not work correctly.
38*8b26181fSAndroid Build Coastguard Worker 3. Only support read operation, and packet injection has not been supported yet.
39*8b26181fSAndroid Build Coastguard Worker
40*8b26181fSAndroid Build Coastguard Worker Usage:
41*8b26181fSAndroid Build Coastguard Worker 1. Compile DPDK as shared library and install.(https://github.com/DPDK/dpdk.git)
42*8b26181fSAndroid Build Coastguard Worker
43*8b26181fSAndroid Build Coastguard Worker You shall modify the file $RTE_SDK/$RTE_TARGET/.config and set:
44*8b26181fSAndroid Build Coastguard Worker CONFIG_RTE_BUILD_SHARED_LIB=y
45*8b26181fSAndroid Build Coastguard Worker By the following command:
46*8b26181fSAndroid Build Coastguard Worker sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/' $RTE_SDK/$RTE_TARGET/.config
47*8b26181fSAndroid Build Coastguard Worker
48*8b26181fSAndroid Build Coastguard Worker 2. Launch l2fwd that is one of DPDK examples correctly, and get device information.
49*8b26181fSAndroid Build Coastguard Worker
50*8b26181fSAndroid Build Coastguard Worker You shall learn how to bind nic with DPDK-compatible driver by $RTE_SDK/usertools/dpdk-devbind.py, such as igb_uio.
51*8b26181fSAndroid Build Coastguard Worker And enable hugepages by dpdk-setup.sh
52*8b26181fSAndroid Build Coastguard Worker
53*8b26181fSAndroid Build Coastguard Worker Then launch the l2fwd with dynamic driver support. For example:
54*8b26181fSAndroid Build Coastguard Worker $RTE_SDK/examples/l2fwd/$RTE_TARGET/l2fwd -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so -- -p 0x1
55*8b26181fSAndroid Build Coastguard Worker
56*8b26181fSAndroid Build Coastguard Worker 3. Compile libpcap with dpdk options.
57*8b26181fSAndroid Build Coastguard Worker
58*8b26181fSAndroid Build Coastguard Worker If DPDK has not been found automatically, you shall export DPDK environment variable which are used for compiling DPDK. And then pass $RTE_SDK/$RTE_TARGET to --with-dpdk or -DDPDK_DIR
59*8b26181fSAndroid Build Coastguard Worker
60*8b26181fSAndroid Build Coastguard Worker export RTE_SDK={your DPDK base directory}
61*8b26181fSAndroid Build Coastguard Worker export RTE_TARGET={your target name}
62*8b26181fSAndroid Build Coastguard Worker
63*8b26181fSAndroid Build Coastguard Worker 3.1 With configure
64*8b26181fSAndroid Build Coastguard Worker
65*8b26181fSAndroid Build Coastguard Worker ./configure --with-dpdk=$RTE_SDK/$RTE_TARGET && make -s all && make -s testprogs && make install
66*8b26181fSAndroid Build Coastguard Worker
67*8b26181fSAndroid Build Coastguard Worker 3.2 With cmake
68*8b26181fSAndroid Build Coastguard Worker
69*8b26181fSAndroid Build Coastguard Worker mkdir -p build && cd build && cmake -DDPDK_DIR=$RTE_SDK/$RTE_TARGET ../ && make -s all && make -s testprogs && make install
70*8b26181fSAndroid Build Coastguard Worker
71*8b26181fSAndroid Build Coastguard Worker 4. Link your own program with libpcap, and use DPDK with the device name as dpdk:{portid}, such as dpdk:0.
72*8b26181fSAndroid Build Coastguard Worker And you shall set DPDK configure options by environment variable DPDK_CFG
73*8b26181fSAndroid Build Coastguard Worker For example, the testprogs/capturetest could be lanched by:
74*8b26181fSAndroid Build Coastguard Worker
75*8b26181fSAndroid Build Coastguard Worker env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so" ./capturetest -i dpdk:0
76*8b26181fSAndroid Build Coastguard Worker */
77*8b26181fSAndroid Build Coastguard Worker
78*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
79*8b26181fSAndroid Build Coastguard Worker #include <config.h>
80*8b26181fSAndroid Build Coastguard Worker #endif
81*8b26181fSAndroid Build Coastguard Worker
82*8b26181fSAndroid Build Coastguard Worker #include <errno.h>
83*8b26181fSAndroid Build Coastguard Worker #include <netdb.h>
84*8b26181fSAndroid Build Coastguard Worker #include <stdio.h>
85*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
86*8b26181fSAndroid Build Coastguard Worker #include <string.h>
87*8b26181fSAndroid Build Coastguard Worker #include <unistd.h>
88*8b26181fSAndroid Build Coastguard Worker #include <limits.h> /* for INT_MAX */
89*8b26181fSAndroid Build Coastguard Worker #include <time.h>
90*8b26181fSAndroid Build Coastguard Worker
91*8b26181fSAndroid Build Coastguard Worker #include <sys/time.h>
92*8b26181fSAndroid Build Coastguard Worker
93*8b26181fSAndroid Build Coastguard Worker //header for calling dpdk
94*8b26181fSAndroid Build Coastguard Worker #include <rte_config.h>
95*8b26181fSAndroid Build Coastguard Worker #include <rte_common.h>
96*8b26181fSAndroid Build Coastguard Worker #include <rte_errno.h>
97*8b26181fSAndroid Build Coastguard Worker #include <rte_log.h>
98*8b26181fSAndroid Build Coastguard Worker #include <rte_malloc.h>
99*8b26181fSAndroid Build Coastguard Worker #include <rte_memory.h>
100*8b26181fSAndroid Build Coastguard Worker #include <rte_eal.h>
101*8b26181fSAndroid Build Coastguard Worker #include <rte_launch.h>
102*8b26181fSAndroid Build Coastguard Worker #include <rte_atomic.h>
103*8b26181fSAndroid Build Coastguard Worker #include <rte_cycles.h>
104*8b26181fSAndroid Build Coastguard Worker #include <rte_lcore.h>
105*8b26181fSAndroid Build Coastguard Worker #include <rte_per_lcore.h>
106*8b26181fSAndroid Build Coastguard Worker #include <rte_branch_prediction.h>
107*8b26181fSAndroid Build Coastguard Worker #include <rte_interrupts.h>
108*8b26181fSAndroid Build Coastguard Worker #include <rte_random.h>
109*8b26181fSAndroid Build Coastguard Worker #include <rte_debug.h>
110*8b26181fSAndroid Build Coastguard Worker #include <rte_ether.h>
111*8b26181fSAndroid Build Coastguard Worker #include <rte_ethdev.h>
112*8b26181fSAndroid Build Coastguard Worker #include <rte_mempool.h>
113*8b26181fSAndroid Build Coastguard Worker #include <rte_mbuf.h>
114*8b26181fSAndroid Build Coastguard Worker #include <rte_bus.h>
115*8b26181fSAndroid Build Coastguard Worker
116*8b26181fSAndroid Build Coastguard Worker #include "pcap-int.h"
117*8b26181fSAndroid Build Coastguard Worker #include "pcap-dpdk.h"
118*8b26181fSAndroid Build Coastguard Worker
119*8b26181fSAndroid Build Coastguard Worker /*
120*8b26181fSAndroid Build Coastguard Worker * Deal with API changes that break source compatibility.
121*8b26181fSAndroid Build Coastguard Worker */
122*8b26181fSAndroid Build Coastguard Worker
123*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_STRUCT_RTE_ETHER_ADDR
124*8b26181fSAndroid Build Coastguard Worker #define ETHER_ADDR_TYPE struct rte_ether_addr
125*8b26181fSAndroid Build Coastguard Worker #else
126*8b26181fSAndroid Build Coastguard Worker #define ETHER_ADDR_TYPE struct ether_addr
127*8b26181fSAndroid Build Coastguard Worker #endif
128*8b26181fSAndroid Build Coastguard Worker
129*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEF_LOG_LEV RTE_LOG_ERR
130*8b26181fSAndroid Build Coastguard Worker //
131*8b26181fSAndroid Build Coastguard Worker // This is set to 0 if we haven't initialized DPDK yet, 1 if we've
132*8b26181fSAndroid Build Coastguard Worker // successfully initialized it, a negative value, which is the negative
133*8b26181fSAndroid Build Coastguard Worker // of the rte_errno from rte_eal_init(), if we tried to initialize it
134*8b26181fSAndroid Build Coastguard Worker // and got an error.
135*8b26181fSAndroid Build Coastguard Worker //
136*8b26181fSAndroid Build Coastguard Worker static int is_dpdk_pre_inited=0;
137*8b26181fSAndroid Build Coastguard Worker #define DPDK_LIB_NAME "libpcap_dpdk"
138*8b26181fSAndroid Build Coastguard Worker #define DPDK_DESC "Data Plane Development Kit (DPDK) Interface"
139*8b26181fSAndroid Build Coastguard Worker #define DPDK_ERR_PERM_MSG "permission denied, DPDK needs root permission"
140*8b26181fSAndroid Build Coastguard Worker #define DPDK_ARGC_MAX 64
141*8b26181fSAndroid Build Coastguard Worker #define DPDK_CFG_MAX_LEN 1024
142*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEV_NAME_MAX 32
143*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEV_DESC_MAX 512
144*8b26181fSAndroid Build Coastguard Worker #define DPDK_CFG_ENV_NAME "DPDK_CFG"
145*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEF_MIN_SLEEP_MS 1
146*8b26181fSAndroid Build Coastguard Worker static char dpdk_cfg_buf[DPDK_CFG_MAX_LEN];
147*8b26181fSAndroid Build Coastguard Worker #define DPDK_MAC_ADDR_SIZE 32
148*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEF_MAC_ADDR "00:00:00:00:00:00"
149*8b26181fSAndroid Build Coastguard Worker #define DPDK_PCI_ADDR_SIZE 16
150*8b26181fSAndroid Build Coastguard Worker #define DPDK_DEF_CFG "--log-level=error -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so"
151*8b26181fSAndroid Build Coastguard Worker #define DPDK_PREFIX "dpdk:"
152*8b26181fSAndroid Build Coastguard Worker #define DPDK_PORTID_MAX 65535U
153*8b26181fSAndroid Build Coastguard Worker #define MBUF_POOL_NAME "mbuf_pool"
154*8b26181fSAndroid Build Coastguard Worker #define DPDK_TX_BUF_NAME "tx_buffer"
155*8b26181fSAndroid Build Coastguard Worker //The number of elements in the mbuf pool.
156*8b26181fSAndroid Build Coastguard Worker #define DPDK_NB_MBUFS 8192U
157*8b26181fSAndroid Build Coastguard Worker #define MEMPOOL_CACHE_SIZE 256
158*8b26181fSAndroid Build Coastguard Worker #define MAX_PKT_BURST 32
159*8b26181fSAndroid Build Coastguard Worker // Configurable number of RX/TX ring descriptors
160*8b26181fSAndroid Build Coastguard Worker #define RTE_TEST_RX_DESC_DEFAULT 1024
161*8b26181fSAndroid Build Coastguard Worker #define RTE_TEST_TX_DESC_DEFAULT 1024
162*8b26181fSAndroid Build Coastguard Worker
163*8b26181fSAndroid Build Coastguard Worker static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
164*8b26181fSAndroid Build Coastguard Worker static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
165*8b26181fSAndroid Build Coastguard Worker
166*8b26181fSAndroid Build Coastguard Worker #ifdef RTE_ETHER_MAX_JUMBO_FRAME_LEN
167*8b26181fSAndroid Build Coastguard Worker #define RTE_ETH_PCAP_SNAPLEN RTE_ETHER_MAX_JUMBO_FRAME_LEN
168*8b26181fSAndroid Build Coastguard Worker #else
169*8b26181fSAndroid Build Coastguard Worker #define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN
170*8b26181fSAndroid Build Coastguard Worker #endif
171*8b26181fSAndroid Build Coastguard Worker
172*8b26181fSAndroid Build Coastguard Worker static struct rte_eth_dev_tx_buffer *tx_buffer;
173*8b26181fSAndroid Build Coastguard Worker
174*8b26181fSAndroid Build Coastguard Worker struct dpdk_ts_helper{
175*8b26181fSAndroid Build Coastguard Worker struct timeval start_time;
176*8b26181fSAndroid Build Coastguard Worker uint64_t start_cycles;
177*8b26181fSAndroid Build Coastguard Worker uint64_t hz;
178*8b26181fSAndroid Build Coastguard Worker };
179*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk{
180*8b26181fSAndroid Build Coastguard Worker pcap_t * orig;
181*8b26181fSAndroid Build Coastguard Worker uint16_t portid; // portid of DPDK
182*8b26181fSAndroid Build Coastguard Worker int must_clear_promisc;
183*8b26181fSAndroid Build Coastguard Worker uint64_t bpf_drop;
184*8b26181fSAndroid Build Coastguard Worker int nonblock;
185*8b26181fSAndroid Build Coastguard Worker struct timeval required_select_timeout;
186*8b26181fSAndroid Build Coastguard Worker struct timeval prev_ts;
187*8b26181fSAndroid Build Coastguard Worker struct rte_eth_stats prev_stats;
188*8b26181fSAndroid Build Coastguard Worker struct timeval curr_ts;
189*8b26181fSAndroid Build Coastguard Worker struct rte_eth_stats curr_stats;
190*8b26181fSAndroid Build Coastguard Worker uint64_t pps;
191*8b26181fSAndroid Build Coastguard Worker uint64_t bps;
192*8b26181fSAndroid Build Coastguard Worker struct rte_mempool * pktmbuf_pool;
193*8b26181fSAndroid Build Coastguard Worker struct dpdk_ts_helper ts_helper;
194*8b26181fSAndroid Build Coastguard Worker ETHER_ADDR_TYPE eth_addr;
195*8b26181fSAndroid Build Coastguard Worker char mac_addr[DPDK_MAC_ADDR_SIZE];
196*8b26181fSAndroid Build Coastguard Worker char pci_addr[DPDK_PCI_ADDR_SIZE];
197*8b26181fSAndroid Build Coastguard Worker unsigned char pcap_tmp_buf[RTE_ETH_PCAP_SNAPLEN];
198*8b26181fSAndroid Build Coastguard Worker };
199*8b26181fSAndroid Build Coastguard Worker
200*8b26181fSAndroid Build Coastguard Worker static struct rte_eth_conf port_conf = {
201*8b26181fSAndroid Build Coastguard Worker .rxmode = {
202*8b26181fSAndroid Build Coastguard Worker .split_hdr_size = 0,
203*8b26181fSAndroid Build Coastguard Worker },
204*8b26181fSAndroid Build Coastguard Worker .txmode = {
205*8b26181fSAndroid Build Coastguard Worker .mq_mode = ETH_MQ_TX_NONE,
206*8b26181fSAndroid Build Coastguard Worker },
207*8b26181fSAndroid Build Coastguard Worker };
208*8b26181fSAndroid Build Coastguard Worker
209*8b26181fSAndroid Build Coastguard Worker static void dpdk_fmt_errmsg_for_rte_errno(char *, size_t, int,
210*8b26181fSAndroid Build Coastguard Worker PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
211*8b26181fSAndroid Build Coastguard Worker
212*8b26181fSAndroid Build Coastguard Worker /*
213*8b26181fSAndroid Build Coastguard Worker * Generate an error message based on a format, arguments, and an
214*8b26181fSAndroid Build Coastguard Worker * rte_errno, with a message for the rte_errno after the formatted output.
215*8b26181fSAndroid Build Coastguard Worker */
dpdk_fmt_errmsg_for_rte_errno(char * errbuf,size_t errbuflen,int errnum,const char * fmt,...)216*8b26181fSAndroid Build Coastguard Worker static void dpdk_fmt_errmsg_for_rte_errno(char *errbuf, size_t errbuflen,
217*8b26181fSAndroid Build Coastguard Worker int errnum, const char *fmt, ...)
218*8b26181fSAndroid Build Coastguard Worker {
219*8b26181fSAndroid Build Coastguard Worker va_list ap;
220*8b26181fSAndroid Build Coastguard Worker size_t msglen;
221*8b26181fSAndroid Build Coastguard Worker char *p;
222*8b26181fSAndroid Build Coastguard Worker size_t errbuflen_remaining;
223*8b26181fSAndroid Build Coastguard Worker
224*8b26181fSAndroid Build Coastguard Worker va_start(ap, fmt);
225*8b26181fSAndroid Build Coastguard Worker vsnprintf(errbuf, errbuflen, fmt, ap);
226*8b26181fSAndroid Build Coastguard Worker va_end(ap);
227*8b26181fSAndroid Build Coastguard Worker msglen = strlen(errbuf);
228*8b26181fSAndroid Build Coastguard Worker
229*8b26181fSAndroid Build Coastguard Worker /*
230*8b26181fSAndroid Build Coastguard Worker * Do we have enough space to append ": "?
231*8b26181fSAndroid Build Coastguard Worker * Including the terminating '\0', that's 3 bytes.
232*8b26181fSAndroid Build Coastguard Worker */
233*8b26181fSAndroid Build Coastguard Worker if (msglen + 3 > errbuflen) {
234*8b26181fSAndroid Build Coastguard Worker /* No - just give them what we've produced. */
235*8b26181fSAndroid Build Coastguard Worker return;
236*8b26181fSAndroid Build Coastguard Worker }
237*8b26181fSAndroid Build Coastguard Worker p = errbuf + msglen;
238*8b26181fSAndroid Build Coastguard Worker errbuflen_remaining = errbuflen - msglen;
239*8b26181fSAndroid Build Coastguard Worker *p++ = ':';
240*8b26181fSAndroid Build Coastguard Worker *p++ = ' ';
241*8b26181fSAndroid Build Coastguard Worker *p = '\0';
242*8b26181fSAndroid Build Coastguard Worker msglen += 2;
243*8b26181fSAndroid Build Coastguard Worker errbuflen_remaining -= 2;
244*8b26181fSAndroid Build Coastguard Worker
245*8b26181fSAndroid Build Coastguard Worker /*
246*8b26181fSAndroid Build Coastguard Worker * Now append the string for the error code.
247*8b26181fSAndroid Build Coastguard Worker * rte_strerror() is thread-safe, at least as of dpdk 18.11,
248*8b26181fSAndroid Build Coastguard Worker * unlike strerror() - it uses strerror_r() rather than strerror()
249*8b26181fSAndroid Build Coastguard Worker * for UN*X errno values, and prints to what I assume is a per-thread
250*8b26181fSAndroid Build Coastguard Worker * buffer (based on the "PER_LCORE" in "RTE_DEFINE_PER_LCORE" used
251*8b26181fSAndroid Build Coastguard Worker * to declare the buffers statically) for DPDK errors.
252*8b26181fSAndroid Build Coastguard Worker */
253*8b26181fSAndroid Build Coastguard Worker snprintf(p, errbuflen_remaining, "%s", rte_strerror(errnum));
254*8b26181fSAndroid Build Coastguard Worker }
255*8b26181fSAndroid Build Coastguard Worker
dpdk_init_timer(struct pcap_dpdk * pd)256*8b26181fSAndroid Build Coastguard Worker static int dpdk_init_timer(struct pcap_dpdk *pd){
257*8b26181fSAndroid Build Coastguard Worker gettimeofday(&(pd->ts_helper.start_time),NULL);
258*8b26181fSAndroid Build Coastguard Worker pd->ts_helper.start_cycles = rte_get_timer_cycles();
259*8b26181fSAndroid Build Coastguard Worker pd->ts_helper.hz = rte_get_timer_hz();
260*8b26181fSAndroid Build Coastguard Worker if (pd->ts_helper.hz == 0){
261*8b26181fSAndroid Build Coastguard Worker return -1;
262*8b26181fSAndroid Build Coastguard Worker }
263*8b26181fSAndroid Build Coastguard Worker return 0;
264*8b26181fSAndroid Build Coastguard Worker }
calculate_timestamp(struct dpdk_ts_helper * helper,struct timeval * ts)265*8b26181fSAndroid Build Coastguard Worker static inline void calculate_timestamp(struct dpdk_ts_helper *helper,struct timeval *ts)
266*8b26181fSAndroid Build Coastguard Worker {
267*8b26181fSAndroid Build Coastguard Worker uint64_t cycles;
268*8b26181fSAndroid Build Coastguard Worker // delta
269*8b26181fSAndroid Build Coastguard Worker struct timeval cur_time;
270*8b26181fSAndroid Build Coastguard Worker cycles = rte_get_timer_cycles() - helper->start_cycles;
271*8b26181fSAndroid Build Coastguard Worker cur_time.tv_sec = (time_t)(cycles/helper->hz);
272*8b26181fSAndroid Build Coastguard Worker cur_time.tv_usec = (suseconds_t)((cycles%helper->hz)*1e6/helper->hz);
273*8b26181fSAndroid Build Coastguard Worker timeradd(&(helper->start_time), &cur_time, ts);
274*8b26181fSAndroid Build Coastguard Worker }
275*8b26181fSAndroid Build Coastguard Worker
dpdk_gather_data(unsigned char * data,uint32_t len,struct rte_mbuf * mbuf)276*8b26181fSAndroid Build Coastguard Worker static uint32_t dpdk_gather_data(unsigned char *data, uint32_t len, struct rte_mbuf *mbuf)
277*8b26181fSAndroid Build Coastguard Worker {
278*8b26181fSAndroid Build Coastguard Worker uint32_t total_len = 0;
279*8b26181fSAndroid Build Coastguard Worker while (mbuf && (total_len+mbuf->data_len) < len ){
280*8b26181fSAndroid Build Coastguard Worker rte_memcpy(data+total_len, rte_pktmbuf_mtod(mbuf,void *),mbuf->data_len);
281*8b26181fSAndroid Build Coastguard Worker total_len+=mbuf->data_len;
282*8b26181fSAndroid Build Coastguard Worker mbuf=mbuf->next;
283*8b26181fSAndroid Build Coastguard Worker }
284*8b26181fSAndroid Build Coastguard Worker return total_len;
285*8b26181fSAndroid Build Coastguard Worker }
286*8b26181fSAndroid Build Coastguard Worker
287*8b26181fSAndroid Build Coastguard Worker
dpdk_read_with_timeout(pcap_t * p,struct rte_mbuf ** pkts_burst,const uint16_t burst_cnt)288*8b26181fSAndroid Build Coastguard Worker static int dpdk_read_with_timeout(pcap_t *p, struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){
289*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
290*8b26181fSAndroid Build Coastguard Worker int nb_rx = 0;
291*8b26181fSAndroid Build Coastguard Worker int timeout_ms = p->opt.timeout;
292*8b26181fSAndroid Build Coastguard Worker int sleep_ms = 0;
293*8b26181fSAndroid Build Coastguard Worker if (pd->nonblock){
294*8b26181fSAndroid Build Coastguard Worker // In non-blocking mode, just read once, no matter how many packets are captured.
295*8b26181fSAndroid Build Coastguard Worker nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt);
296*8b26181fSAndroid Build Coastguard Worker }else{
297*8b26181fSAndroid Build Coastguard Worker // In blocking mode, read many times until packets are captured or timeout or break_loop is set.
298*8b26181fSAndroid Build Coastguard Worker // if timeout_ms == 0, it may be blocked forever.
299*8b26181fSAndroid Build Coastguard Worker while (timeout_ms == 0 || sleep_ms < timeout_ms){
300*8b26181fSAndroid Build Coastguard Worker nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt);
301*8b26181fSAndroid Build Coastguard Worker if (nb_rx){ // got packets within timeout_ms
302*8b26181fSAndroid Build Coastguard Worker break;
303*8b26181fSAndroid Build Coastguard Worker }else{ // no packet arrives at this round.
304*8b26181fSAndroid Build Coastguard Worker if (p->break_loop){
305*8b26181fSAndroid Build Coastguard Worker break;
306*8b26181fSAndroid Build Coastguard Worker }
307*8b26181fSAndroid Build Coastguard Worker // sleep for a very short while.
308*8b26181fSAndroid Build Coastguard Worker // block sleep is the only choice, since usleep() will impact performance dramatically.
309*8b26181fSAndroid Build Coastguard Worker rte_delay_us_block(DPDK_DEF_MIN_SLEEP_MS*1000);
310*8b26181fSAndroid Build Coastguard Worker sleep_ms += DPDK_DEF_MIN_SLEEP_MS;
311*8b26181fSAndroid Build Coastguard Worker }
312*8b26181fSAndroid Build Coastguard Worker }
313*8b26181fSAndroid Build Coastguard Worker }
314*8b26181fSAndroid Build Coastguard Worker return nb_rx;
315*8b26181fSAndroid Build Coastguard Worker }
316*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_dispatch(pcap_t * p,int max_cnt,pcap_handler cb,u_char * cb_arg)317*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *cb_arg)
318*8b26181fSAndroid Build Coastguard Worker {
319*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
320*8b26181fSAndroid Build Coastguard Worker int burst_cnt = 0;
321*8b26181fSAndroid Build Coastguard Worker int nb_rx = 0;
322*8b26181fSAndroid Build Coastguard Worker struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
323*8b26181fSAndroid Build Coastguard Worker struct rte_mbuf *m;
324*8b26181fSAndroid Build Coastguard Worker struct pcap_pkthdr pcap_header;
325*8b26181fSAndroid Build Coastguard Worker // In DPDK, pkt_len is sum of lengths for all segments. And data_len is for one segment
326*8b26181fSAndroid Build Coastguard Worker uint32_t pkt_len = 0;
327*8b26181fSAndroid Build Coastguard Worker uint32_t caplen = 0;
328*8b26181fSAndroid Build Coastguard Worker u_char *bp = NULL;
329*8b26181fSAndroid Build Coastguard Worker int i=0;
330*8b26181fSAndroid Build Coastguard Worker unsigned int gather_len =0;
331*8b26181fSAndroid Build Coastguard Worker int pkt_cnt = 0;
332*8b26181fSAndroid Build Coastguard Worker u_char *large_buffer=NULL;
333*8b26181fSAndroid Build Coastguard Worker int timeout_ms = p->opt.timeout;
334*8b26181fSAndroid Build Coastguard Worker
335*8b26181fSAndroid Build Coastguard Worker /*
336*8b26181fSAndroid Build Coastguard Worker * This can conceivably process more than INT_MAX packets,
337*8b26181fSAndroid Build Coastguard Worker * which would overflow the packet count, causing it either
338*8b26181fSAndroid Build Coastguard Worker * to look like a negative number, and thus cause us to
339*8b26181fSAndroid Build Coastguard Worker * return a value that looks like an error, or overflow
340*8b26181fSAndroid Build Coastguard Worker * back into positive territory, and thus cause us to
341*8b26181fSAndroid Build Coastguard Worker * return a too-low count.
342*8b26181fSAndroid Build Coastguard Worker *
343*8b26181fSAndroid Build Coastguard Worker * Therefore, if the packet count is unlimited, we clip
344*8b26181fSAndroid Build Coastguard Worker * it at INT_MAX; this routine is not expected to
345*8b26181fSAndroid Build Coastguard Worker * process packets indefinitely, so that's not an issue.
346*8b26181fSAndroid Build Coastguard Worker */
347*8b26181fSAndroid Build Coastguard Worker if (PACKET_COUNT_IS_UNLIMITED(max_cnt))
348*8b26181fSAndroid Build Coastguard Worker max_cnt = INT_MAX;
349*8b26181fSAndroid Build Coastguard Worker
350*8b26181fSAndroid Build Coastguard Worker if (max_cnt < MAX_PKT_BURST){
351*8b26181fSAndroid Build Coastguard Worker burst_cnt = max_cnt;
352*8b26181fSAndroid Build Coastguard Worker }else{
353*8b26181fSAndroid Build Coastguard Worker burst_cnt = MAX_PKT_BURST;
354*8b26181fSAndroid Build Coastguard Worker }
355*8b26181fSAndroid Build Coastguard Worker
356*8b26181fSAndroid Build Coastguard Worker while( pkt_cnt < max_cnt){
357*8b26181fSAndroid Build Coastguard Worker if (p->break_loop){
358*8b26181fSAndroid Build Coastguard Worker p->break_loop = 0;
359*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR_BREAK;
360*8b26181fSAndroid Build Coastguard Worker }
361*8b26181fSAndroid Build Coastguard Worker // read once in non-blocking mode, or try many times waiting for timeout_ms.
362*8b26181fSAndroid Build Coastguard Worker // if timeout_ms == 0, it will be blocked until one packet arrives or break_loop is set.
363*8b26181fSAndroid Build Coastguard Worker nb_rx = dpdk_read_with_timeout(p, pkts_burst, burst_cnt);
364*8b26181fSAndroid Build Coastguard Worker if (nb_rx == 0){
365*8b26181fSAndroid Build Coastguard Worker if (pd->nonblock){
366*8b26181fSAndroid Build Coastguard Worker RTE_LOG(DEBUG, USER1, "dpdk: no packets available in non-blocking mode.\n");
367*8b26181fSAndroid Build Coastguard Worker }else{
368*8b26181fSAndroid Build Coastguard Worker if (p->break_loop){
369*8b26181fSAndroid Build Coastguard Worker RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is set in blocking mode.\n");
370*8b26181fSAndroid Build Coastguard Worker p->break_loop = 0;
371*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR_BREAK;
372*8b26181fSAndroid Build Coastguard Worker
373*8b26181fSAndroid Build Coastguard Worker }
374*8b26181fSAndroid Build Coastguard Worker RTE_LOG(DEBUG, USER1, "dpdk: no packets available for timeout %d ms in blocking mode.\n", timeout_ms);
375*8b26181fSAndroid Build Coastguard Worker }
376*8b26181fSAndroid Build Coastguard Worker // break if dpdk reads 0 packet, no matter in blocking(timeout) or non-blocking mode.
377*8b26181fSAndroid Build Coastguard Worker break;
378*8b26181fSAndroid Build Coastguard Worker }
379*8b26181fSAndroid Build Coastguard Worker pkt_cnt += nb_rx;
380*8b26181fSAndroid Build Coastguard Worker for ( i = 0; i < nb_rx; i++) {
381*8b26181fSAndroid Build Coastguard Worker m = pkts_burst[i];
382*8b26181fSAndroid Build Coastguard Worker calculate_timestamp(&(pd->ts_helper),&(pcap_header.ts));
383*8b26181fSAndroid Build Coastguard Worker pkt_len = rte_pktmbuf_pkt_len(m);
384*8b26181fSAndroid Build Coastguard Worker // caplen = min(pkt_len, p->snapshot);
385*8b26181fSAndroid Build Coastguard Worker // caplen will not be changed, no matter how long the rte_pktmbuf
386*8b26181fSAndroid Build Coastguard Worker caplen = pkt_len < (uint32_t)p->snapshot ? pkt_len: (uint32_t)p->snapshot;
387*8b26181fSAndroid Build Coastguard Worker pcap_header.caplen = caplen;
388*8b26181fSAndroid Build Coastguard Worker pcap_header.len = pkt_len;
389*8b26181fSAndroid Build Coastguard Worker // volatile prefetch
390*8b26181fSAndroid Build Coastguard Worker rte_prefetch0(rte_pktmbuf_mtod(m, void *));
391*8b26181fSAndroid Build Coastguard Worker bp = NULL;
392*8b26181fSAndroid Build Coastguard Worker if (m->nb_segs == 1)
393*8b26181fSAndroid Build Coastguard Worker {
394*8b26181fSAndroid Build Coastguard Worker bp = rte_pktmbuf_mtod(m, u_char *);
395*8b26181fSAndroid Build Coastguard Worker }else{
396*8b26181fSAndroid Build Coastguard Worker // use fast buffer pcap_tmp_buf if pkt_len is small, no need to call malloc and free
397*8b26181fSAndroid Build Coastguard Worker if ( pkt_len <= RTE_ETH_PCAP_SNAPLEN)
398*8b26181fSAndroid Build Coastguard Worker {
399*8b26181fSAndroid Build Coastguard Worker gather_len = dpdk_gather_data(pd->pcap_tmp_buf, RTE_ETH_PCAP_SNAPLEN, m);
400*8b26181fSAndroid Build Coastguard Worker bp = pd->pcap_tmp_buf;
401*8b26181fSAndroid Build Coastguard Worker }else{
402*8b26181fSAndroid Build Coastguard Worker // need call free later
403*8b26181fSAndroid Build Coastguard Worker large_buffer = (u_char *)malloc(caplen*sizeof(u_char));
404*8b26181fSAndroid Build Coastguard Worker gather_len = dpdk_gather_data(large_buffer, caplen, m);
405*8b26181fSAndroid Build Coastguard Worker bp = large_buffer;
406*8b26181fSAndroid Build Coastguard Worker }
407*8b26181fSAndroid Build Coastguard Worker
408*8b26181fSAndroid Build Coastguard Worker }
409*8b26181fSAndroid Build Coastguard Worker if (bp){
410*8b26181fSAndroid Build Coastguard Worker if (p->fcode.bf_insns==NULL || pcap_filter(p->fcode.bf_insns, bp, pcap_header.len, pcap_header.caplen)){
411*8b26181fSAndroid Build Coastguard Worker cb(cb_arg, &pcap_header, bp);
412*8b26181fSAndroid Build Coastguard Worker }else{
413*8b26181fSAndroid Build Coastguard Worker pd->bpf_drop++;
414*8b26181fSAndroid Build Coastguard Worker }
415*8b26181fSAndroid Build Coastguard Worker }
416*8b26181fSAndroid Build Coastguard Worker //free all pktmbuf
417*8b26181fSAndroid Build Coastguard Worker rte_pktmbuf_free(m);
418*8b26181fSAndroid Build Coastguard Worker if (large_buffer){
419*8b26181fSAndroid Build Coastguard Worker free(large_buffer);
420*8b26181fSAndroid Build Coastguard Worker large_buffer=NULL;
421*8b26181fSAndroid Build Coastguard Worker }
422*8b26181fSAndroid Build Coastguard Worker }
423*8b26181fSAndroid Build Coastguard Worker }
424*8b26181fSAndroid Build Coastguard Worker return pkt_cnt;
425*8b26181fSAndroid Build Coastguard Worker }
426*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_inject(pcap_t * p,const void * buf _U_,int size _U_)427*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_inject(pcap_t *p, const void *buf _U_, int size _U_)
428*8b26181fSAndroid Build Coastguard Worker {
429*8b26181fSAndroid Build Coastguard Worker //not implemented yet
430*8b26181fSAndroid Build Coastguard Worker pcap_strlcpy(p->errbuf,
431*8b26181fSAndroid Build Coastguard Worker "dpdk error: Inject function has not been implemented yet",
432*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE);
433*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR;
434*8b26181fSAndroid Build Coastguard Worker }
435*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_close(pcap_t * p)436*8b26181fSAndroid Build Coastguard Worker static void pcap_dpdk_close(pcap_t *p)
437*8b26181fSAndroid Build Coastguard Worker {
438*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = p->priv;
439*8b26181fSAndroid Build Coastguard Worker if (pd==NULL)
440*8b26181fSAndroid Build Coastguard Worker {
441*8b26181fSAndroid Build Coastguard Worker return;
442*8b26181fSAndroid Build Coastguard Worker }
443*8b26181fSAndroid Build Coastguard Worker if (pd->must_clear_promisc)
444*8b26181fSAndroid Build Coastguard Worker {
445*8b26181fSAndroid Build Coastguard Worker rte_eth_promiscuous_disable(pd->portid);
446*8b26181fSAndroid Build Coastguard Worker }
447*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_stop(pd->portid);
448*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_close(pd->portid);
449*8b26181fSAndroid Build Coastguard Worker pcap_cleanup_live_common(p);
450*8b26181fSAndroid Build Coastguard Worker }
451*8b26181fSAndroid Build Coastguard Worker
nic_stats_display(struct pcap_dpdk * pd)452*8b26181fSAndroid Build Coastguard Worker static void nic_stats_display(struct pcap_dpdk *pd)
453*8b26181fSAndroid Build Coastguard Worker {
454*8b26181fSAndroid Build Coastguard Worker uint16_t portid = pd->portid;
455*8b26181fSAndroid Build Coastguard Worker struct rte_eth_stats stats;
456*8b26181fSAndroid Build Coastguard Worker rte_eth_stats_get(portid, &stats);
457*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO,USER1, "portid:%d, RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64
458*8b26181fSAndroid Build Coastguard Worker " RX-bytes: %-10"PRIu64" RX-Imissed: %-10"PRIu64"\n", portid, stats.ipackets, stats.ierrors,
459*8b26181fSAndroid Build Coastguard Worker stats.ibytes,stats.imissed);
460*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO,USER1, "portid:%d, RX-PPS: %-10"PRIu64" RX-Mbps: %.2lf\n", portid, pd->pps, pd->bps/1e6f );
461*8b26181fSAndroid Build Coastguard Worker }
462*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_stats(pcap_t * p,struct pcap_stat * ps)463*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_stats(pcap_t *p, struct pcap_stat *ps)
464*8b26181fSAndroid Build Coastguard Worker {
465*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = p->priv;
466*8b26181fSAndroid Build Coastguard Worker calculate_timestamp(&(pd->ts_helper), &(pd->curr_ts));
467*8b26181fSAndroid Build Coastguard Worker rte_eth_stats_get(pd->portid,&(pd->curr_stats));
468*8b26181fSAndroid Build Coastguard Worker if (ps){
469*8b26181fSAndroid Build Coastguard Worker ps->ps_recv = pd->curr_stats.ipackets;
470*8b26181fSAndroid Build Coastguard Worker ps->ps_drop = pd->curr_stats.ierrors;
471*8b26181fSAndroid Build Coastguard Worker ps->ps_drop += pd->bpf_drop;
472*8b26181fSAndroid Build Coastguard Worker ps->ps_ifdrop = pd->curr_stats.imissed;
473*8b26181fSAndroid Build Coastguard Worker }
474*8b26181fSAndroid Build Coastguard Worker uint64_t delta_pkt = pd->curr_stats.ipackets - pd->prev_stats.ipackets;
475*8b26181fSAndroid Build Coastguard Worker struct timeval delta_tm;
476*8b26181fSAndroid Build Coastguard Worker timersub(&(pd->curr_ts),&(pd->prev_ts), &delta_tm);
477*8b26181fSAndroid Build Coastguard Worker uint64_t delta_usec = delta_tm.tv_sec*1e6+delta_tm.tv_usec;
478*8b26181fSAndroid Build Coastguard Worker uint64_t delta_bit = (pd->curr_stats.ibytes-pd->prev_stats.ibytes)*8;
479*8b26181fSAndroid Build Coastguard Worker RTE_LOG(DEBUG, USER1, "delta_usec: %-10"PRIu64" delta_pkt: %-10"PRIu64" delta_bit: %-10"PRIu64"\n", delta_usec, delta_pkt, delta_bit);
480*8b26181fSAndroid Build Coastguard Worker pd->pps = (uint64_t)(delta_pkt*1e6f/delta_usec);
481*8b26181fSAndroid Build Coastguard Worker pd->bps = (uint64_t)(delta_bit*1e6f/delta_usec);
482*8b26181fSAndroid Build Coastguard Worker nic_stats_display(pd);
483*8b26181fSAndroid Build Coastguard Worker pd->prev_stats = pd->curr_stats;
484*8b26181fSAndroid Build Coastguard Worker pd->prev_ts = pd->curr_ts;
485*8b26181fSAndroid Build Coastguard Worker return 0;
486*8b26181fSAndroid Build Coastguard Worker }
487*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_setnonblock(pcap_t * p,int nonblock)488*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_setnonblock(pcap_t *p, int nonblock){
489*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
490*8b26181fSAndroid Build Coastguard Worker pd->nonblock = nonblock;
491*8b26181fSAndroid Build Coastguard Worker return 0;
492*8b26181fSAndroid Build Coastguard Worker }
493*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_getnonblock(pcap_t * p)494*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_getnonblock(pcap_t *p){
495*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
496*8b26181fSAndroid Build Coastguard Worker return pd->nonblock;
497*8b26181fSAndroid Build Coastguard Worker }
check_link_status(uint16_t portid,struct rte_eth_link * plink)498*8b26181fSAndroid Build Coastguard Worker static int check_link_status(uint16_t portid, struct rte_eth_link *plink)
499*8b26181fSAndroid Build Coastguard Worker {
500*8b26181fSAndroid Build Coastguard Worker // wait up to 9 seconds to get link status
501*8b26181fSAndroid Build Coastguard Worker rte_eth_link_get(portid, plink);
502*8b26181fSAndroid Build Coastguard Worker return plink->link_status == ETH_LINK_UP;
503*8b26181fSAndroid Build Coastguard Worker }
eth_addr_str(ETHER_ADDR_TYPE * addrp,char * mac_str,int len)504*8b26181fSAndroid Build Coastguard Worker static void eth_addr_str(ETHER_ADDR_TYPE *addrp, char* mac_str, int len)
505*8b26181fSAndroid Build Coastguard Worker {
506*8b26181fSAndroid Build Coastguard Worker int offset=0;
507*8b26181fSAndroid Build Coastguard Worker if (addrp == NULL){
508*8b26181fSAndroid Build Coastguard Worker snprintf(mac_str, len-1, DPDK_DEF_MAC_ADDR);
509*8b26181fSAndroid Build Coastguard Worker return;
510*8b26181fSAndroid Build Coastguard Worker }
511*8b26181fSAndroid Build Coastguard Worker for (int i=0; i<6; i++)
512*8b26181fSAndroid Build Coastguard Worker {
513*8b26181fSAndroid Build Coastguard Worker if (offset >= len)
514*8b26181fSAndroid Build Coastguard Worker { // buffer overflow
515*8b26181fSAndroid Build Coastguard Worker return;
516*8b26181fSAndroid Build Coastguard Worker }
517*8b26181fSAndroid Build Coastguard Worker if (i==0)
518*8b26181fSAndroid Build Coastguard Worker {
519*8b26181fSAndroid Build Coastguard Worker snprintf(mac_str+offset, len-1-offset, "%02X",addrp->addr_bytes[i]);
520*8b26181fSAndroid Build Coastguard Worker offset+=2; // FF
521*8b26181fSAndroid Build Coastguard Worker }else{
522*8b26181fSAndroid Build Coastguard Worker snprintf(mac_str+offset, len-1-offset, ":%02X", addrp->addr_bytes[i]);
523*8b26181fSAndroid Build Coastguard Worker offset+=3; // :FF
524*8b26181fSAndroid Build Coastguard Worker }
525*8b26181fSAndroid Build Coastguard Worker }
526*8b26181fSAndroid Build Coastguard Worker return;
527*8b26181fSAndroid Build Coastguard Worker }
528*8b26181fSAndroid Build Coastguard Worker // return portid by device name, otherwise return -1
portid_by_device(char * device)529*8b26181fSAndroid Build Coastguard Worker static uint16_t portid_by_device(char * device)
530*8b26181fSAndroid Build Coastguard Worker {
531*8b26181fSAndroid Build Coastguard Worker uint16_t ret = DPDK_PORTID_MAX;
532*8b26181fSAndroid Build Coastguard Worker int len = strlen(device);
533*8b26181fSAndroid Build Coastguard Worker int prefix_len = strlen(DPDK_PREFIX);
534*8b26181fSAndroid Build Coastguard Worker unsigned long ret_ul = 0L;
535*8b26181fSAndroid Build Coastguard Worker char *pEnd;
536*8b26181fSAndroid Build Coastguard Worker if (len<=prefix_len || strncmp(device, DPDK_PREFIX, prefix_len)) // check prefix dpdk:
537*8b26181fSAndroid Build Coastguard Worker {
538*8b26181fSAndroid Build Coastguard Worker return ret;
539*8b26181fSAndroid Build Coastguard Worker }
540*8b26181fSAndroid Build Coastguard Worker //check all chars are digital
541*8b26181fSAndroid Build Coastguard Worker for (int i=prefix_len; device[i]; i++){
542*8b26181fSAndroid Build Coastguard Worker if (device[i]<'0' || device[i]>'9'){
543*8b26181fSAndroid Build Coastguard Worker return ret;
544*8b26181fSAndroid Build Coastguard Worker }
545*8b26181fSAndroid Build Coastguard Worker }
546*8b26181fSAndroid Build Coastguard Worker ret_ul = strtoul(&(device[prefix_len]), &pEnd, 10);
547*8b26181fSAndroid Build Coastguard Worker if (pEnd == &(device[prefix_len]) || *pEnd != '\0'){
548*8b26181fSAndroid Build Coastguard Worker return ret;
549*8b26181fSAndroid Build Coastguard Worker }
550*8b26181fSAndroid Build Coastguard Worker // too large for portid
551*8b26181fSAndroid Build Coastguard Worker if (ret_ul >= DPDK_PORTID_MAX){
552*8b26181fSAndroid Build Coastguard Worker return ret;
553*8b26181fSAndroid Build Coastguard Worker }
554*8b26181fSAndroid Build Coastguard Worker ret = (uint16_t)ret_ul;
555*8b26181fSAndroid Build Coastguard Worker return ret;
556*8b26181fSAndroid Build Coastguard Worker }
557*8b26181fSAndroid Build Coastguard Worker
parse_dpdk_cfg(char * dpdk_cfg,char ** dargv)558*8b26181fSAndroid Build Coastguard Worker static int parse_dpdk_cfg(char* dpdk_cfg,char** dargv)
559*8b26181fSAndroid Build Coastguard Worker {
560*8b26181fSAndroid Build Coastguard Worker int cnt=0;
561*8b26181fSAndroid Build Coastguard Worker memset(dargv,0,sizeof(dargv[0])*DPDK_ARGC_MAX);
562*8b26181fSAndroid Build Coastguard Worker //current process name
563*8b26181fSAndroid Build Coastguard Worker int skip_space = 1;
564*8b26181fSAndroid Build Coastguard Worker int i=0;
565*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO, USER1,"dpdk cfg: %s\n",dpdk_cfg);
566*8b26181fSAndroid Build Coastguard Worker // find first non space char
567*8b26181fSAndroid Build Coastguard Worker // The last opt is NULL
568*8b26181fSAndroid Build Coastguard Worker for (i=0;dpdk_cfg[i] && cnt<DPDK_ARGC_MAX-1;i++){
569*8b26181fSAndroid Build Coastguard Worker if (skip_space && dpdk_cfg[i]!=' '){ // not space
570*8b26181fSAndroid Build Coastguard Worker skip_space=!skip_space; // skip normal char
571*8b26181fSAndroid Build Coastguard Worker dargv[cnt++] = dpdk_cfg+i;
572*8b26181fSAndroid Build Coastguard Worker }
573*8b26181fSAndroid Build Coastguard Worker if (!skip_space && dpdk_cfg[i]==' '){ // fint a space
574*8b26181fSAndroid Build Coastguard Worker dpdk_cfg[i]=0x00; // end of this opt
575*8b26181fSAndroid Build Coastguard Worker skip_space=!skip_space; // skip space char
576*8b26181fSAndroid Build Coastguard Worker }
577*8b26181fSAndroid Build Coastguard Worker }
578*8b26181fSAndroid Build Coastguard Worker dargv[cnt]=NULL;
579*8b26181fSAndroid Build Coastguard Worker return cnt;
580*8b26181fSAndroid Build Coastguard Worker }
581*8b26181fSAndroid Build Coastguard Worker
582*8b26181fSAndroid Build Coastguard Worker // only called once
583*8b26181fSAndroid Build Coastguard Worker // Returns:
584*8b26181fSAndroid Build Coastguard Worker //
585*8b26181fSAndroid Build Coastguard Worker // 1 on success;
586*8b26181fSAndroid Build Coastguard Worker //
587*8b26181fSAndroid Build Coastguard Worker // 0 if "the EAL cannot initialize on this system", which we treat as
588*8b26181fSAndroid Build Coastguard Worker // meaning "DPDK isn't available";
589*8b26181fSAndroid Build Coastguard Worker //
590*8b26181fSAndroid Build Coastguard Worker // a PCAP_ERROR_ code for other errors.
591*8b26181fSAndroid Build Coastguard Worker //
592*8b26181fSAndroid Build Coastguard Worker // If eaccess_not_fatal is non-zero, treat "a permissions issue" the way
593*8b26181fSAndroid Build Coastguard Worker // we treat "the EAL cannot initialize on this system". We use that
594*8b26181fSAndroid Build Coastguard Worker // when trying to find DPDK devices, as we don't want to fail to return
595*8b26181fSAndroid Build Coastguard Worker // *any* devices just because we can't support DPDK; when we're trying
596*8b26181fSAndroid Build Coastguard Worker // to open a device, we need to return a permissions error in that case.
dpdk_pre_init(char * ebuf,int eaccess_not_fatal)597*8b26181fSAndroid Build Coastguard Worker static int dpdk_pre_init(char * ebuf, int eaccess_not_fatal)
598*8b26181fSAndroid Build Coastguard Worker {
599*8b26181fSAndroid Build Coastguard Worker int dargv_cnt=0;
600*8b26181fSAndroid Build Coastguard Worker char *dargv[DPDK_ARGC_MAX];
601*8b26181fSAndroid Build Coastguard Worker char *ptr_dpdk_cfg = NULL;
602*8b26181fSAndroid Build Coastguard Worker int ret;
603*8b26181fSAndroid Build Coastguard Worker // globale var
604*8b26181fSAndroid Build Coastguard Worker if (is_dpdk_pre_inited != 0)
605*8b26181fSAndroid Build Coastguard Worker {
606*8b26181fSAndroid Build Coastguard Worker // already inited; did that succeed?
607*8b26181fSAndroid Build Coastguard Worker if (is_dpdk_pre_inited < 0)
608*8b26181fSAndroid Build Coastguard Worker {
609*8b26181fSAndroid Build Coastguard Worker // failed
610*8b26181fSAndroid Build Coastguard Worker goto error;
611*8b26181fSAndroid Build Coastguard Worker }
612*8b26181fSAndroid Build Coastguard Worker else
613*8b26181fSAndroid Build Coastguard Worker {
614*8b26181fSAndroid Build Coastguard Worker // succeeded
615*8b26181fSAndroid Build Coastguard Worker return 1;
616*8b26181fSAndroid Build Coastguard Worker }
617*8b26181fSAndroid Build Coastguard Worker }
618*8b26181fSAndroid Build Coastguard Worker // init EAL
619*8b26181fSAndroid Build Coastguard Worker ptr_dpdk_cfg = getenv(DPDK_CFG_ENV_NAME);
620*8b26181fSAndroid Build Coastguard Worker // set default log level to debug
621*8b26181fSAndroid Build Coastguard Worker rte_log_set_global_level(DPDK_DEF_LOG_LEV);
622*8b26181fSAndroid Build Coastguard Worker if (ptr_dpdk_cfg == NULL)
623*8b26181fSAndroid Build Coastguard Worker {
624*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO,USER1,"env $DPDK_CFG is unset, so using default: %s\n",DPDK_DEF_CFG);
625*8b26181fSAndroid Build Coastguard Worker ptr_dpdk_cfg = DPDK_DEF_CFG;
626*8b26181fSAndroid Build Coastguard Worker }
627*8b26181fSAndroid Build Coastguard Worker memset(dpdk_cfg_buf,0,sizeof(dpdk_cfg_buf));
628*8b26181fSAndroid Build Coastguard Worker snprintf(dpdk_cfg_buf,DPDK_CFG_MAX_LEN-1,"%s %s",DPDK_LIB_NAME,ptr_dpdk_cfg);
629*8b26181fSAndroid Build Coastguard Worker dargv_cnt = parse_dpdk_cfg(dpdk_cfg_buf,dargv);
630*8b26181fSAndroid Build Coastguard Worker ret = rte_eal_init(dargv_cnt,dargv);
631*8b26181fSAndroid Build Coastguard Worker if (ret == -1)
632*8b26181fSAndroid Build Coastguard Worker {
633*8b26181fSAndroid Build Coastguard Worker // Indicate that we've called rte_eal_init() by setting
634*8b26181fSAndroid Build Coastguard Worker // is_dpdk_pre_inited to the negative of the error code,
635*8b26181fSAndroid Build Coastguard Worker // and process the error.
636*8b26181fSAndroid Build Coastguard Worker is_dpdk_pre_inited = -rte_errno;
637*8b26181fSAndroid Build Coastguard Worker goto error;
638*8b26181fSAndroid Build Coastguard Worker }
639*8b26181fSAndroid Build Coastguard Worker // init succeeded, so we do not need to do it again later.
640*8b26181fSAndroid Build Coastguard Worker is_dpdk_pre_inited = 1;
641*8b26181fSAndroid Build Coastguard Worker return 1;
642*8b26181fSAndroid Build Coastguard Worker
643*8b26181fSAndroid Build Coastguard Worker error:
644*8b26181fSAndroid Build Coastguard Worker switch (-is_dpdk_pre_inited)
645*8b26181fSAndroid Build Coastguard Worker {
646*8b26181fSAndroid Build Coastguard Worker case EACCES:
647*8b26181fSAndroid Build Coastguard Worker // This "indicates a permissions issue.".
648*8b26181fSAndroid Build Coastguard Worker RTE_LOG(ERR, USER1, "%s\n", DPDK_ERR_PERM_MSG);
649*8b26181fSAndroid Build Coastguard Worker // If we were told to treat this as just meaning
650*8b26181fSAndroid Build Coastguard Worker // DPDK isn't available, do so.
651*8b26181fSAndroid Build Coastguard Worker if (eaccess_not_fatal)
652*8b26181fSAndroid Build Coastguard Worker return 0;
653*8b26181fSAndroid Build Coastguard Worker // Otherwise report a fatal error.
654*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
655*8b26181fSAndroid Build Coastguard Worker "DPDK requires that it run as root");
656*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR_PERM_DENIED;
657*8b26181fSAndroid Build Coastguard Worker
658*8b26181fSAndroid Build Coastguard Worker case EAGAIN:
659*8b26181fSAndroid Build Coastguard Worker // This "indicates either a bus or system
660*8b26181fSAndroid Build Coastguard Worker // resource was not available, setup may
661*8b26181fSAndroid Build Coastguard Worker // be attempted again."
662*8b26181fSAndroid Build Coastguard Worker // There's no such error in pcap, so I'm
663*8b26181fSAndroid Build Coastguard Worker // not sure what we should do here.
664*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
665*8b26181fSAndroid Build Coastguard Worker "Bus or system resource was not available");
666*8b26181fSAndroid Build Coastguard Worker break;
667*8b26181fSAndroid Build Coastguard Worker
668*8b26181fSAndroid Build Coastguard Worker case EALREADY:
669*8b26181fSAndroid Build Coastguard Worker // This "indicates that the rte_eal_init
670*8b26181fSAndroid Build Coastguard Worker // function has already been called, and
671*8b26181fSAndroid Build Coastguard Worker // cannot be called again."
672*8b26181fSAndroid Build Coastguard Worker // That's not an error; set the "we've
673*8b26181fSAndroid Build Coastguard Worker // been here before" flag and return
674*8b26181fSAndroid Build Coastguard Worker // success.
675*8b26181fSAndroid Build Coastguard Worker is_dpdk_pre_inited = 1;
676*8b26181fSAndroid Build Coastguard Worker return 1;
677*8b26181fSAndroid Build Coastguard Worker
678*8b26181fSAndroid Build Coastguard Worker case EFAULT:
679*8b26181fSAndroid Build Coastguard Worker // This "indicates the tailq configuration
680*8b26181fSAndroid Build Coastguard Worker // name was not found in memory configuration."
681*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
682*8b26181fSAndroid Build Coastguard Worker "The tailq configuration name was not found in the memory configuration");
683*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR;
684*8b26181fSAndroid Build Coastguard Worker
685*8b26181fSAndroid Build Coastguard Worker case EINVAL:
686*8b26181fSAndroid Build Coastguard Worker // This "indicates invalid parameters were
687*8b26181fSAndroid Build Coastguard Worker // passed as argv/argc." Those came from
688*8b26181fSAndroid Build Coastguard Worker // the configuration file.
689*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
690*8b26181fSAndroid Build Coastguard Worker "The configuration file has invalid parameters");
691*8b26181fSAndroid Build Coastguard Worker break;
692*8b26181fSAndroid Build Coastguard Worker
693*8b26181fSAndroid Build Coastguard Worker case ENOMEM:
694*8b26181fSAndroid Build Coastguard Worker // This "indicates failure likely caused by
695*8b26181fSAndroid Build Coastguard Worker // an out-of-memory condition."
696*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
697*8b26181fSAndroid Build Coastguard Worker "Out of memory");
698*8b26181fSAndroid Build Coastguard Worker break;
699*8b26181fSAndroid Build Coastguard Worker
700*8b26181fSAndroid Build Coastguard Worker case ENODEV:
701*8b26181fSAndroid Build Coastguard Worker // This "indicates memory setup issues."
702*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
703*8b26181fSAndroid Build Coastguard Worker "An error occurred setting up memory");
704*8b26181fSAndroid Build Coastguard Worker break;
705*8b26181fSAndroid Build Coastguard Worker
706*8b26181fSAndroid Build Coastguard Worker case ENOTSUP:
707*8b26181fSAndroid Build Coastguard Worker // This "indicates that the EAL cannot
708*8b26181fSAndroid Build Coastguard Worker // initialize on this system." We treat
709*8b26181fSAndroid Build Coastguard Worker // that as meaning DPDK isn't available
710*8b26181fSAndroid Build Coastguard Worker // on this machine, rather than as a
711*8b26181fSAndroid Build Coastguard Worker // fatal error, and let our caller decide
712*8b26181fSAndroid Build Coastguard Worker // whether that's a fatal error (if trying
713*8b26181fSAndroid Build Coastguard Worker // to activate a DPDK device) or not (if
714*8b26181fSAndroid Build Coastguard Worker // trying to enumerate devices).
715*8b26181fSAndroid Build Coastguard Worker return 0;
716*8b26181fSAndroid Build Coastguard Worker
717*8b26181fSAndroid Build Coastguard Worker case EPROTO:
718*8b26181fSAndroid Build Coastguard Worker // This "indicates that the PCI bus is
719*8b26181fSAndroid Build Coastguard Worker // either not present, or is not readable
720*8b26181fSAndroid Build Coastguard Worker // by the eal." Does "the PCI bus is not
721*8b26181fSAndroid Build Coastguard Worker // present" mean "this machine has no PCI
722*8b26181fSAndroid Build Coastguard Worker // bus", which strikes me as a "not available"
723*8b26181fSAndroid Build Coastguard Worker // case? If so, should "is not readable by
724*8b26181fSAndroid Build Coastguard Worker // the EAL" also something we should treat
725*8b26181fSAndroid Build Coastguard Worker // as a "not available" case? If not, we
726*8b26181fSAndroid Build Coastguard Worker // can't distinguish between the two, so
727*8b26181fSAndroid Build Coastguard Worker // we're stuck.
728*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
729*8b26181fSAndroid Build Coastguard Worker "PCI bus is not present or not readable by the EAL");
730*8b26181fSAndroid Build Coastguard Worker break;
731*8b26181fSAndroid Build Coastguard Worker
732*8b26181fSAndroid Build Coastguard Worker case ENOEXEC:
733*8b26181fSAndroid Build Coastguard Worker // This "indicates that a service core
734*8b26181fSAndroid Build Coastguard Worker // failed to launch successfully."
735*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
736*8b26181fSAndroid Build Coastguard Worker "A service core failed to launch successfully");
737*8b26181fSAndroid Build Coastguard Worker break;
738*8b26181fSAndroid Build Coastguard Worker
739*8b26181fSAndroid Build Coastguard Worker default:
740*8b26181fSAndroid Build Coastguard Worker //
741*8b26181fSAndroid Build Coastguard Worker // That's not in the list of errors in
742*8b26181fSAndroid Build Coastguard Worker // the documentation; let it be reported
743*8b26181fSAndroid Build Coastguard Worker // as an error.
744*8b26181fSAndroid Build Coastguard Worker //
745*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(ebuf,
746*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -is_dpdk_pre_inited,
747*8b26181fSAndroid Build Coastguard Worker "dpdk error: dpdk_pre_init failed");
748*8b26181fSAndroid Build Coastguard Worker break;
749*8b26181fSAndroid Build Coastguard Worker }
750*8b26181fSAndroid Build Coastguard Worker // Error.
751*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR;
752*8b26181fSAndroid Build Coastguard Worker }
753*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_activate(pcap_t * p)754*8b26181fSAndroid Build Coastguard Worker static int pcap_dpdk_activate(pcap_t *p)
755*8b26181fSAndroid Build Coastguard Worker {
756*8b26181fSAndroid Build Coastguard Worker struct pcap_dpdk *pd = p->priv;
757*8b26181fSAndroid Build Coastguard Worker pd->orig = p;
758*8b26181fSAndroid Build Coastguard Worker int ret = PCAP_ERROR;
759*8b26181fSAndroid Build Coastguard Worker uint16_t nb_ports=0;
760*8b26181fSAndroid Build Coastguard Worker uint16_t portid= DPDK_PORTID_MAX;
761*8b26181fSAndroid Build Coastguard Worker unsigned nb_mbufs = DPDK_NB_MBUFS;
762*8b26181fSAndroid Build Coastguard Worker struct rte_eth_rxconf rxq_conf;
763*8b26181fSAndroid Build Coastguard Worker struct rte_eth_txconf txq_conf;
764*8b26181fSAndroid Build Coastguard Worker struct rte_eth_conf local_port_conf = port_conf;
765*8b26181fSAndroid Build Coastguard Worker struct rte_eth_dev_info dev_info;
766*8b26181fSAndroid Build Coastguard Worker int is_port_up = 0;
767*8b26181fSAndroid Build Coastguard Worker struct rte_eth_link link;
768*8b26181fSAndroid Build Coastguard Worker do{
769*8b26181fSAndroid Build Coastguard Worker //init EAL; fail if we have insufficient permission
770*8b26181fSAndroid Build Coastguard Worker char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
771*8b26181fSAndroid Build Coastguard Worker ret = dpdk_pre_init(dpdk_pre_init_errbuf, 0);
772*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
773*8b26181fSAndroid Build Coastguard Worker {
774*8b26181fSAndroid Build Coastguard Worker // This returns a negative value on an error.
775*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
776*8b26181fSAndroid Build Coastguard Worker "Can't open device %s: %s",
777*8b26181fSAndroid Build Coastguard Worker p->opt.device, dpdk_pre_init_errbuf);
778*8b26181fSAndroid Build Coastguard Worker // ret is set to the correct error
779*8b26181fSAndroid Build Coastguard Worker break;
780*8b26181fSAndroid Build Coastguard Worker }
781*8b26181fSAndroid Build Coastguard Worker if (ret == 0)
782*8b26181fSAndroid Build Coastguard Worker {
783*8b26181fSAndroid Build Coastguard Worker // This means DPDK isn't available on this machine.
784*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
785*8b26181fSAndroid Build Coastguard Worker "Can't open device %s: DPDK is not available on this machine",
786*8b26181fSAndroid Build Coastguard Worker p->opt.device);
787*8b26181fSAndroid Build Coastguard Worker return PCAP_ERROR_NO_SUCH_DEVICE;
788*8b26181fSAndroid Build Coastguard Worker }
789*8b26181fSAndroid Build Coastguard Worker
790*8b26181fSAndroid Build Coastguard Worker ret = dpdk_init_timer(pd);
791*8b26181fSAndroid Build Coastguard Worker if (ret<0)
792*8b26181fSAndroid Build Coastguard Worker {
793*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
794*8b26181fSAndroid Build Coastguard Worker "dpdk error: Init timer is zero with device %s",
795*8b26181fSAndroid Build Coastguard Worker p->opt.device);
796*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
797*8b26181fSAndroid Build Coastguard Worker break;
798*8b26181fSAndroid Build Coastguard Worker }
799*8b26181fSAndroid Build Coastguard Worker
800*8b26181fSAndroid Build Coastguard Worker nb_ports = rte_eth_dev_count_avail();
801*8b26181fSAndroid Build Coastguard Worker if (nb_ports == 0)
802*8b26181fSAndroid Build Coastguard Worker {
803*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
804*8b26181fSAndroid Build Coastguard Worker "dpdk error: No Ethernet ports");
805*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
806*8b26181fSAndroid Build Coastguard Worker break;
807*8b26181fSAndroid Build Coastguard Worker }
808*8b26181fSAndroid Build Coastguard Worker
809*8b26181fSAndroid Build Coastguard Worker portid = portid_by_device(p->opt.device);
810*8b26181fSAndroid Build Coastguard Worker if (portid == DPDK_PORTID_MAX){
811*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
812*8b26181fSAndroid Build Coastguard Worker "dpdk error: portid is invalid. device %s",
813*8b26181fSAndroid Build Coastguard Worker p->opt.device);
814*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR_NO_SUCH_DEVICE;
815*8b26181fSAndroid Build Coastguard Worker break;
816*8b26181fSAndroid Build Coastguard Worker }
817*8b26181fSAndroid Build Coastguard Worker
818*8b26181fSAndroid Build Coastguard Worker pd->portid = portid;
819*8b26181fSAndroid Build Coastguard Worker
820*8b26181fSAndroid Build Coastguard Worker if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
821*8b26181fSAndroid Build Coastguard Worker {
822*8b26181fSAndroid Build Coastguard Worker p->snapshot = MAXIMUM_SNAPLEN;
823*8b26181fSAndroid Build Coastguard Worker }
824*8b26181fSAndroid Build Coastguard Worker // create the mbuf pool
825*8b26181fSAndroid Build Coastguard Worker pd->pktmbuf_pool = rte_pktmbuf_pool_create(MBUF_POOL_NAME, nb_mbufs,
826*8b26181fSAndroid Build Coastguard Worker MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
827*8b26181fSAndroid Build Coastguard Worker rte_socket_id());
828*8b26181fSAndroid Build Coastguard Worker if (pd->pktmbuf_pool == NULL)
829*8b26181fSAndroid Build Coastguard Worker {
830*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
831*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, rte_errno,
832*8b26181fSAndroid Build Coastguard Worker "dpdk error: Cannot init mbuf pool");
833*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
834*8b26181fSAndroid Build Coastguard Worker break;
835*8b26181fSAndroid Build Coastguard Worker }
836*8b26181fSAndroid Build Coastguard Worker // config dev
837*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_info_get(portid, &dev_info);
838*8b26181fSAndroid Build Coastguard Worker if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
839*8b26181fSAndroid Build Coastguard Worker {
840*8b26181fSAndroid Build Coastguard Worker local_port_conf.txmode.offloads |=DEV_TX_OFFLOAD_MBUF_FAST_FREE;
841*8b26181fSAndroid Build Coastguard Worker }
842*8b26181fSAndroid Build Coastguard Worker // only support 1 queue
843*8b26181fSAndroid Build Coastguard Worker ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
844*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
845*8b26181fSAndroid Build Coastguard Worker {
846*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
847*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -ret,
848*8b26181fSAndroid Build Coastguard Worker "dpdk error: Cannot configure device: port=%u",
849*8b26181fSAndroid Build Coastguard Worker portid);
850*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
851*8b26181fSAndroid Build Coastguard Worker break;
852*8b26181fSAndroid Build Coastguard Worker }
853*8b26181fSAndroid Build Coastguard Worker // adjust rx tx
854*8b26181fSAndroid Build Coastguard Worker ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
855*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
856*8b26181fSAndroid Build Coastguard Worker {
857*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
858*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -ret,
859*8b26181fSAndroid Build Coastguard Worker "dpdk error: Cannot adjust number of descriptors: port=%u",
860*8b26181fSAndroid Build Coastguard Worker portid);
861*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
862*8b26181fSAndroid Build Coastguard Worker break;
863*8b26181fSAndroid Build Coastguard Worker }
864*8b26181fSAndroid Build Coastguard Worker // get MAC addr
865*8b26181fSAndroid Build Coastguard Worker rte_eth_macaddr_get(portid, &(pd->eth_addr));
866*8b26181fSAndroid Build Coastguard Worker eth_addr_str(&(pd->eth_addr), pd->mac_addr, DPDK_MAC_ADDR_SIZE-1);
867*8b26181fSAndroid Build Coastguard Worker
868*8b26181fSAndroid Build Coastguard Worker // init one RX queue
869*8b26181fSAndroid Build Coastguard Worker rxq_conf = dev_info.default_rxconf;
870*8b26181fSAndroid Build Coastguard Worker rxq_conf.offloads = local_port_conf.rxmode.offloads;
871*8b26181fSAndroid Build Coastguard Worker ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
872*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_socket_id(portid),
873*8b26181fSAndroid Build Coastguard Worker &rxq_conf,
874*8b26181fSAndroid Build Coastguard Worker pd->pktmbuf_pool);
875*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
876*8b26181fSAndroid Build Coastguard Worker {
877*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
878*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -ret,
879*8b26181fSAndroid Build Coastguard Worker "dpdk error: rte_eth_rx_queue_setup:port=%u",
880*8b26181fSAndroid Build Coastguard Worker portid);
881*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
882*8b26181fSAndroid Build Coastguard Worker break;
883*8b26181fSAndroid Build Coastguard Worker }
884*8b26181fSAndroid Build Coastguard Worker
885*8b26181fSAndroid Build Coastguard Worker // init one TX queue
886*8b26181fSAndroid Build Coastguard Worker txq_conf = dev_info.default_txconf;
887*8b26181fSAndroid Build Coastguard Worker txq_conf.offloads = local_port_conf.txmode.offloads;
888*8b26181fSAndroid Build Coastguard Worker ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
889*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_socket_id(portid),
890*8b26181fSAndroid Build Coastguard Worker &txq_conf);
891*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
892*8b26181fSAndroid Build Coastguard Worker {
893*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
894*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -ret,
895*8b26181fSAndroid Build Coastguard Worker "dpdk error: rte_eth_tx_queue_setup:port=%u",
896*8b26181fSAndroid Build Coastguard Worker portid);
897*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
898*8b26181fSAndroid Build Coastguard Worker break;
899*8b26181fSAndroid Build Coastguard Worker }
900*8b26181fSAndroid Build Coastguard Worker // Initialize TX buffers
901*8b26181fSAndroid Build Coastguard Worker tx_buffer = rte_zmalloc_socket(DPDK_TX_BUF_NAME,
902*8b26181fSAndroid Build Coastguard Worker RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
903*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_socket_id(portid));
904*8b26181fSAndroid Build Coastguard Worker if (tx_buffer == NULL)
905*8b26181fSAndroid Build Coastguard Worker {
906*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
907*8b26181fSAndroid Build Coastguard Worker "dpdk error: Cannot allocate buffer for tx on port %u", portid);
908*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
909*8b26181fSAndroid Build Coastguard Worker break;
910*8b26181fSAndroid Build Coastguard Worker }
911*8b26181fSAndroid Build Coastguard Worker rte_eth_tx_buffer_init(tx_buffer, MAX_PKT_BURST);
912*8b26181fSAndroid Build Coastguard Worker // Start device
913*8b26181fSAndroid Build Coastguard Worker ret = rte_eth_dev_start(portid);
914*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
915*8b26181fSAndroid Build Coastguard Worker {
916*8b26181fSAndroid Build Coastguard Worker dpdk_fmt_errmsg_for_rte_errno(p->errbuf,
917*8b26181fSAndroid Build Coastguard Worker PCAP_ERRBUF_SIZE, -ret,
918*8b26181fSAndroid Build Coastguard Worker "dpdk error: rte_eth_dev_start:port=%u",
919*8b26181fSAndroid Build Coastguard Worker portid);
920*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
921*8b26181fSAndroid Build Coastguard Worker break;
922*8b26181fSAndroid Build Coastguard Worker }
923*8b26181fSAndroid Build Coastguard Worker // set promiscuous mode
924*8b26181fSAndroid Build Coastguard Worker if (p->opt.promisc){
925*8b26181fSAndroid Build Coastguard Worker pd->must_clear_promisc=1;
926*8b26181fSAndroid Build Coastguard Worker rte_eth_promiscuous_enable(portid);
927*8b26181fSAndroid Build Coastguard Worker }
928*8b26181fSAndroid Build Coastguard Worker // check link status
929*8b26181fSAndroid Build Coastguard Worker is_port_up = check_link_status(portid, &link);
930*8b26181fSAndroid Build Coastguard Worker if (!is_port_up){
931*8b26181fSAndroid Build Coastguard Worker snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
932*8b26181fSAndroid Build Coastguard Worker "dpdk error: link is down, port=%u",portid);
933*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR_IFACE_NOT_UP;
934*8b26181fSAndroid Build Coastguard Worker break;
935*8b26181fSAndroid Build Coastguard Worker }
936*8b26181fSAndroid Build Coastguard Worker // reset statistics
937*8b26181fSAndroid Build Coastguard Worker rte_eth_stats_reset(pd->portid);
938*8b26181fSAndroid Build Coastguard Worker calculate_timestamp(&(pd->ts_helper), &(pd->prev_ts));
939*8b26181fSAndroid Build Coastguard Worker rte_eth_stats_get(pd->portid,&(pd->prev_stats));
940*8b26181fSAndroid Build Coastguard Worker // format pcap_t
941*8b26181fSAndroid Build Coastguard Worker pd->portid = portid;
942*8b26181fSAndroid Build Coastguard Worker p->fd = pd->portid;
943*8b26181fSAndroid Build Coastguard Worker if (p->snapshot <=0 || p->snapshot> MAXIMUM_SNAPLEN)
944*8b26181fSAndroid Build Coastguard Worker {
945*8b26181fSAndroid Build Coastguard Worker p->snapshot = MAXIMUM_SNAPLEN;
946*8b26181fSAndroid Build Coastguard Worker }
947*8b26181fSAndroid Build Coastguard Worker p->linktype = DLT_EN10MB; // Ethernet, the 10MB is historical.
948*8b26181fSAndroid Build Coastguard Worker p->selectable_fd = p->fd;
949*8b26181fSAndroid Build Coastguard Worker p->read_op = pcap_dpdk_dispatch;
950*8b26181fSAndroid Build Coastguard Worker p->inject_op = pcap_dpdk_inject;
951*8b26181fSAndroid Build Coastguard Worker // using pcap_filter currently, though DPDK provides their own BPF function. Because DPDK BPF needs load a ELF file as a filter.
952*8b26181fSAndroid Build Coastguard Worker p->setfilter_op = install_bpf_program;
953*8b26181fSAndroid Build Coastguard Worker p->setdirection_op = NULL;
954*8b26181fSAndroid Build Coastguard Worker p->set_datalink_op = NULL;
955*8b26181fSAndroid Build Coastguard Worker p->getnonblock_op = pcap_dpdk_getnonblock;
956*8b26181fSAndroid Build Coastguard Worker p->setnonblock_op = pcap_dpdk_setnonblock;
957*8b26181fSAndroid Build Coastguard Worker p->stats_op = pcap_dpdk_stats;
958*8b26181fSAndroid Build Coastguard Worker p->cleanup_op = pcap_dpdk_close;
959*8b26181fSAndroid Build Coastguard Worker p->breakloop_op = pcap_breakloop_common;
960*8b26181fSAndroid Build Coastguard Worker // set default timeout
961*8b26181fSAndroid Build Coastguard Worker pd->required_select_timeout.tv_sec = 0;
962*8b26181fSAndroid Build Coastguard Worker pd->required_select_timeout.tv_usec = DPDK_DEF_MIN_SLEEP_MS*1000;
963*8b26181fSAndroid Build Coastguard Worker p->required_select_timeout = &pd->required_select_timeout;
964*8b26181fSAndroid Build Coastguard Worker ret = 0; // OK
965*8b26181fSAndroid Build Coastguard Worker }while(0);
966*8b26181fSAndroid Build Coastguard Worker
967*8b26181fSAndroid Build Coastguard Worker if (ret <= PCAP_ERROR) // all kinds of error code
968*8b26181fSAndroid Build Coastguard Worker {
969*8b26181fSAndroid Build Coastguard Worker pcap_cleanup_live_common(p);
970*8b26181fSAndroid Build Coastguard Worker }else{
971*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_get_name_by_port(portid,pd->pci_addr);
972*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO, USER1,"Port %d device: %s, MAC:%s, PCI:%s\n", portid, p->opt.device, pd->mac_addr, pd->pci_addr);
973*8b26181fSAndroid Build Coastguard Worker RTE_LOG(INFO, USER1,"Port %d Link Up. Speed %u Mbps - %s\n",
974*8b26181fSAndroid Build Coastguard Worker portid, link.link_speed,
975*8b26181fSAndroid Build Coastguard Worker (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
976*8b26181fSAndroid Build Coastguard Worker ("full-duplex") : ("half-duplex\n"));
977*8b26181fSAndroid Build Coastguard Worker }
978*8b26181fSAndroid Build Coastguard Worker return ret;
979*8b26181fSAndroid Build Coastguard Worker }
980*8b26181fSAndroid Build Coastguard Worker
981*8b26181fSAndroid Build Coastguard Worker // device name for dpdk should be in the form as dpdk:number, such as dpdk:0
pcap_dpdk_create(const char * device,char * ebuf,int * is_ours)982*8b26181fSAndroid Build Coastguard Worker pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours)
983*8b26181fSAndroid Build Coastguard Worker {
984*8b26181fSAndroid Build Coastguard Worker pcap_t *p=NULL;
985*8b26181fSAndroid Build Coastguard Worker *is_ours = 0;
986*8b26181fSAndroid Build Coastguard Worker
987*8b26181fSAndroid Build Coastguard Worker *is_ours = !strncmp(device, "dpdk:", 5);
988*8b26181fSAndroid Build Coastguard Worker if (! *is_ours)
989*8b26181fSAndroid Build Coastguard Worker return NULL;
990*8b26181fSAndroid Build Coastguard Worker //memset will happen
991*8b26181fSAndroid Build Coastguard Worker p = PCAP_CREATE_COMMON(ebuf, struct pcap_dpdk);
992*8b26181fSAndroid Build Coastguard Worker
993*8b26181fSAndroid Build Coastguard Worker if (p == NULL)
994*8b26181fSAndroid Build Coastguard Worker return NULL;
995*8b26181fSAndroid Build Coastguard Worker p->activate_op = pcap_dpdk_activate;
996*8b26181fSAndroid Build Coastguard Worker return p;
997*8b26181fSAndroid Build Coastguard Worker }
998*8b26181fSAndroid Build Coastguard Worker
pcap_dpdk_findalldevs(pcap_if_list_t * devlistp,char * ebuf)999*8b26181fSAndroid Build Coastguard Worker int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf)
1000*8b26181fSAndroid Build Coastguard Worker {
1001*8b26181fSAndroid Build Coastguard Worker int ret=0;
1002*8b26181fSAndroid Build Coastguard Worker unsigned int nb_ports = 0;
1003*8b26181fSAndroid Build Coastguard Worker char dpdk_name[DPDK_DEV_NAME_MAX];
1004*8b26181fSAndroid Build Coastguard Worker char dpdk_desc[DPDK_DEV_DESC_MAX];
1005*8b26181fSAndroid Build Coastguard Worker ETHER_ADDR_TYPE eth_addr;
1006*8b26181fSAndroid Build Coastguard Worker char mac_addr[DPDK_MAC_ADDR_SIZE];
1007*8b26181fSAndroid Build Coastguard Worker char pci_addr[DPDK_PCI_ADDR_SIZE];
1008*8b26181fSAndroid Build Coastguard Worker do{
1009*8b26181fSAndroid Build Coastguard Worker // init EAL; return "DPDK not available" if we
1010*8b26181fSAndroid Build Coastguard Worker // have insufficient permission
1011*8b26181fSAndroid Build Coastguard Worker char dpdk_pre_init_errbuf[PCAP_ERRBUF_SIZE];
1012*8b26181fSAndroid Build Coastguard Worker ret = dpdk_pre_init(dpdk_pre_init_errbuf, 1);
1013*8b26181fSAndroid Build Coastguard Worker if (ret < 0)
1014*8b26181fSAndroid Build Coastguard Worker {
1015*8b26181fSAndroid Build Coastguard Worker // This returns a negative value on an error.
1016*8b26181fSAndroid Build Coastguard Worker snprintf(ebuf, PCAP_ERRBUF_SIZE,
1017*8b26181fSAndroid Build Coastguard Worker "Can't look for DPDK devices: %s",
1018*8b26181fSAndroid Build Coastguard Worker dpdk_pre_init_errbuf);
1019*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
1020*8b26181fSAndroid Build Coastguard Worker break;
1021*8b26181fSAndroid Build Coastguard Worker }
1022*8b26181fSAndroid Build Coastguard Worker if (ret == 0)
1023*8b26181fSAndroid Build Coastguard Worker {
1024*8b26181fSAndroid Build Coastguard Worker // This means DPDK isn't available on this machine.
1025*8b26181fSAndroid Build Coastguard Worker // That just means "don't return any devices".
1026*8b26181fSAndroid Build Coastguard Worker break;
1027*8b26181fSAndroid Build Coastguard Worker }
1028*8b26181fSAndroid Build Coastguard Worker nb_ports = rte_eth_dev_count_avail();
1029*8b26181fSAndroid Build Coastguard Worker if (nb_ports == 0)
1030*8b26181fSAndroid Build Coastguard Worker {
1031*8b26181fSAndroid Build Coastguard Worker // That just means "don't return any devices".
1032*8b26181fSAndroid Build Coastguard Worker ret = 0;
1033*8b26181fSAndroid Build Coastguard Worker break;
1034*8b26181fSAndroid Build Coastguard Worker }
1035*8b26181fSAndroid Build Coastguard Worker for (unsigned int i=0; i<nb_ports; i++){
1036*8b26181fSAndroid Build Coastguard Worker snprintf(dpdk_name, DPDK_DEV_NAME_MAX-1,
1037*8b26181fSAndroid Build Coastguard Worker "%s%u", DPDK_PREFIX, i);
1038*8b26181fSAndroid Build Coastguard Worker // mac addr
1039*8b26181fSAndroid Build Coastguard Worker rte_eth_macaddr_get(i, ð_addr);
1040*8b26181fSAndroid Build Coastguard Worker eth_addr_str(ð_addr,mac_addr,DPDK_MAC_ADDR_SIZE);
1041*8b26181fSAndroid Build Coastguard Worker // PCI addr
1042*8b26181fSAndroid Build Coastguard Worker rte_eth_dev_get_name_by_port(i,pci_addr);
1043*8b26181fSAndroid Build Coastguard Worker snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr);
1044*8b26181fSAndroid Build Coastguard Worker if (add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){
1045*8b26181fSAndroid Build Coastguard Worker ret = PCAP_ERROR;
1046*8b26181fSAndroid Build Coastguard Worker break;
1047*8b26181fSAndroid Build Coastguard Worker }
1048*8b26181fSAndroid Build Coastguard Worker }
1049*8b26181fSAndroid Build Coastguard Worker }while(0);
1050*8b26181fSAndroid Build Coastguard Worker return ret;
1051*8b26181fSAndroid Build Coastguard Worker }
1052*8b26181fSAndroid Build Coastguard Worker
1053*8b26181fSAndroid Build Coastguard Worker #ifdef DPDK_ONLY
1054*8b26181fSAndroid Build Coastguard Worker /*
1055*8b26181fSAndroid Build Coastguard Worker * This libpcap build supports only DPDK, not regular network interfaces.
1056*8b26181fSAndroid Build Coastguard Worker */
1057*8b26181fSAndroid Build Coastguard Worker
1058*8b26181fSAndroid Build Coastguard Worker /*
1059*8b26181fSAndroid Build Coastguard Worker * There are no regular interfaces, just DPDK interfaces.
1060*8b26181fSAndroid Build Coastguard Worker */
1061*8b26181fSAndroid Build Coastguard Worker int
pcap_platform_finddevs(pcap_if_list_t * devlistp _U_,char * errbuf)1062*8b26181fSAndroid Build Coastguard Worker pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
1063*8b26181fSAndroid Build Coastguard Worker {
1064*8b26181fSAndroid Build Coastguard Worker return (0);
1065*8b26181fSAndroid Build Coastguard Worker }
1066*8b26181fSAndroid Build Coastguard Worker
1067*8b26181fSAndroid Build Coastguard Worker /*
1068*8b26181fSAndroid Build Coastguard Worker * Attempts to open a regular interface fail.
1069*8b26181fSAndroid Build Coastguard Worker */
1070*8b26181fSAndroid Build Coastguard Worker pcap_t *
pcap_create_interface(const char * device,char * errbuf)1071*8b26181fSAndroid Build Coastguard Worker pcap_create_interface(const char *device, char *errbuf)
1072*8b26181fSAndroid Build Coastguard Worker {
1073*8b26181fSAndroid Build Coastguard Worker snprintf(errbuf, PCAP_ERRBUF_SIZE,
1074*8b26181fSAndroid Build Coastguard Worker "This version of libpcap only supports DPDK");
1075*8b26181fSAndroid Build Coastguard Worker return NULL;
1076*8b26181fSAndroid Build Coastguard Worker }
1077*8b26181fSAndroid Build Coastguard Worker
1078*8b26181fSAndroid Build Coastguard Worker /*
1079*8b26181fSAndroid Build Coastguard Worker * Libpcap version string.
1080*8b26181fSAndroid Build Coastguard Worker */
1081*8b26181fSAndroid Build Coastguard Worker const char *
pcap_lib_version(void)1082*8b26181fSAndroid Build Coastguard Worker pcap_lib_version(void)
1083*8b26181fSAndroid Build Coastguard Worker {
1084*8b26181fSAndroid Build Coastguard Worker return (PCAP_VERSION_STRING " (DPDK-only)");
1085*8b26181fSAndroid Build Coastguard Worker }
1086*8b26181fSAndroid Build Coastguard Worker #endif
1087