2 * Copyright (C) 2018 All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1. Pcap-dpdk provides libpcap the ability to use DPDK with the device name as dpdk:[portid], such as dpdk:0.
32 2. DPDK is a set of libraries and drivers for fast packet processing. (https://www.dpdk.org/)
35 1. By default enable_dpdk is no, unless you set inlcudes and lib dir
36 by --with-dpdk-includes= --with-dpdk-libraries=
37 2. Only support link libdpdk.so dynamicly, because the libdpdk.a will not work correctly.
38 3. Only support read operation, and packet injection has not been supported yet.
39 4. I have tested on DPDK v18.11.
41 1. compile DPDK as shared library and install.(https://github.com/DPDK/dpdk.git)
43 You shall modify the file $RTE_SDK/$RTE_TARGET/.config and set:
44 CONFIG_RTE_BUILD_SHARED_LIB=y
46 2. launch l2fwd that is one of DPDK examples correctly, and get device information.
48 You shall learn how to bind nic with DPDK-compatible driver by $RTE_SDK/usertools/dpdk-devbind.py, such as igb_uio.
49 And enable hugepages by dpdk-setup.sh
51 Then launch the l2fwd with dynamic dirver support. For example:
52 $RTE_SDK/examples/l2fwd/$RTE_TARGET/l2fwd -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so -- -p 0x1
54 3. compile libpcap with dpdk options.
56 you shall run the following command to generate a new configure
61 Then, run configure with dpdk options.
62 For Ubuntu, they are --with-dpdk-includes=/usr/local/include/dpdk/ --with-dpdk-libraries=/usr/local/lib
64 4. link your own program with libpcap, and use DPDK with the device name as dpdk[portid], such as dpdk:0.
65 And you shall set DPDK configure options by environment variable DPDK_CFG
66 For example, the testprogs/capturetest could be lanched by:
68 env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so" ./capturetest -i dpdk:0
70 The program will print the following message on my computer:
72 USER1: dpdk cfg: libpcap_dpdk --log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so
73 EAL: Detected 4 lcore(s)
74 EAL: Detected 1 NUMA nodes
75 EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
76 EAL: No free hugepages reported in hugepages-1048576kB
77 EAL: Probing VFIO support...
78 EAL: PCI device 0000:00:19.0 on NUMA socket -1
79 EAL: Invalid NUMA socket, default to 0
80 EAL: probe driver: 8086:1559 net_e1000_em
81 USER1: pcap_dpdk_activate device dpdk:0 portid 0, pci_addr: 0000:00:19.0
82 USER1: Port 0 Link Up. Speed 1000 Mbps - full-duplex
83 USER1: Port 0, MAC address: [MAC ADDR]
86 USER1: dpdk: lcoreid=0 runs for portid=0
103 #include <sys/time.h>
105 //header for calling dpdk
106 #include <rte_common.h>
108 #include <rte_malloc.h>
109 #include <rte_memory.h>
111 #include <rte_launch.h>
112 #include <rte_atomic.h>
113 #include <rte_cycles.h>
114 #include <rte_lcore.h>
115 #include <rte_per_lcore.h>
116 #include <rte_branch_prediction.h>
117 #include <rte_interrupts.h>
118 #include <rte_random.h>
119 #include <rte_debug.h>
120 #include <rte_ether.h>
121 #include <rte_ethdev.h>
122 #include <rte_mempool.h>
123 #include <rte_mbuf.h>
126 #include "pcap-int.h"
127 #include "pcap-dpdk.h"
129 #define DPDK_LIB_NAME "libpcap_dpdk"
130 #define DPDK_ARGC_MAX 64
131 #define DPDK_CFG_MAX_LEN 1024
132 #define DPDK_CFG_ENV_NAME "DPDK_CFG"
133 static char dpdk_cfg_buf
[DPDK_CFG_MAX_LEN
];
134 #define DPDK_PCI_ADDR_SIZE 16
135 #define DPDK_DEF_CFG "--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so"
136 #define DPDK_PREFIX "dpdk:"
137 #define MBUF_POOL_NAME "mbuf_pool"
138 #define DPDK_TX_BUF_NAME "tx_buffer"
139 //The number of elements in the mbuf pool.
140 #define DPDK_NB_MBUFS 8192U
141 #define MEMPOOL_CACHE_SIZE 256
142 #define MAX_PKT_BURST 32
143 // Configurable number of RX/TX ring descriptors
144 #define RTE_TEST_RX_DESC_DEFAULT 1024
145 #define RTE_TEST_TX_DESC_DEFAULT 1024
147 static uint16_t nb_rxd
= RTE_TEST_RX_DESC_DEFAULT
;
148 static uint16_t nb_txd
= RTE_TEST_TX_DESC_DEFAULT
;
150 #define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN
152 static struct rte_eth_dev_tx_buffer
*tx_buffer
;
154 struct dpdk_ts_helper
{
155 struct timeval start_time
;
156 uint64_t start_cycles
;
161 uint16_t portid
; // portid of DPDK
162 pcap_handler cb
; //callback and argument
165 int must_clear_promisc
;
166 int filter_in_userland
;
169 struct ether_addr eth_addr
;
170 struct rte_eth_stats stats
;
171 struct rte_mempool
* pktmbuf_pool
;
172 struct dpdk_ts_helper ts_helper
;
173 char pci_addr
[DPDK_PCI_ADDR_SIZE
];
174 unsigned char pcap_tmp_buf
[RTE_ETH_PCAP_SNAPLEN
];
175 volatile sig_atomic_t break_loop
;
178 static struct rte_eth_conf port_conf
= {
183 .mq_mode
= ETH_MQ_TX_NONE
,
187 static int dpdk_init_timer(struct pcap_dpdk
*pd
){
188 gettimeofday(&(pd
->ts_helper
.start_time
),NULL
);
189 pd
->ts_helper
.start_cycles
= rte_get_timer_cycles();
190 pd
->ts_helper
.hz
= rte_get_timer_hz();
191 if (pd
->ts_helper
.hz
== 0){
196 static inline void calculate_timestamp(struct dpdk_ts_helper
*helper
,struct timeval
*ts
)
200 struct timeval cur_time
;
201 cycles
= rte_get_timer_cycles() - helper
->start_cycles
;
202 cur_time
.tv_sec
= (time_t)(cycles
/helper
->hz
);
203 cur_time
.tv_usec
= (suseconds_t
)((cycles
%helper
->hz
)*1e6
/helper
->hz
);
204 timeradd(&(helper
->start_time
), &cur_time
, ts
);
207 static unsigned int dpdk_gather_data(unsigned char *data
, struct rte_mbuf
*mbuf
)
209 unsigned int total_len
= 0;
210 while (mbuf
&& (total_len
+mbuf
->data_len
) < RTE_ETH_PCAP_SNAPLEN
){
211 rte_memcpy(data
+total_len
, rte_pktmbuf_mtod(mbuf
,void *),mbuf
->data_len
);
212 total_len
+=mbuf
->data_len
;
218 static void pcap_dpdk_breakloop(pcap_t
*p
)
220 pcap_breakloop_common(p
);
221 struct pcap_dpdk
*pd
= (struct pcap_dpdk
*)(p
->priv
);
222 pd
->break_loop
= p
->break_loop
;
224 static void dpdk_dispatch_inter(void *dpdk_user
)
226 if (dpdk_user
== NULL
){
229 pcap_t
*p
= dpdk_user
;
230 struct pcap_dpdk
*pd
= (struct pcap_dpdk
*)(p
->priv
);
231 int max_cnt
= pd
->max_cnt
;
232 pcap_handler cb
= pd
->cb
;
233 u_char
*cb_arg
= pd
->cb_arg
;
235 struct rte_mbuf
*pkts_burst
[MAX_PKT_BURST
];
237 struct pcap_pkthdr pcap_header
;
238 uint16_t portid
= pd
->portid
;
239 unsigned lcore_id
= rte_lcore_id();
240 unsigned master_lcore_id
= rte_get_master_lcore();
241 uint16_t data_len
= 0;
244 unsigned int gather_len
=0;
248 if(lcore_id
== master_lcore_id
){
249 RTE_LOG(INFO
, USER1
, "dpdk: lcoreid=%u runs for portid=%u\n", lcore_id
, portid
);
251 RTE_LOG(INFO
, USER1
, "dpdk: lcore %u has nothing to do\n", lcore_id
);
253 //only use master lcore
254 if (lcore_id
!= master_lcore_id
){
257 while( max_cnt
==-1 || pkt_cnt
< max_cnt
){
261 nb_rx
= (int)rte_eth_rx_burst(portid
, 0, pkts_burst
, MAX_PKT_BURST
);
263 for ( i
= 0; i
< nb_rx
; i
++) {
265 calculate_timestamp(&(pd
->ts_helper
),&(pcap_header
.ts
));
266 data_len
= rte_pktmbuf_data_len(m
);
267 pcap_header
.caplen
= data_len
;
268 pcap_header
.len
= data_len
;
270 rte_prefetch0(rte_pktmbuf_mtod(m
, void *));
274 bp
= rte_pktmbuf_mtod(m
, u_char
*);
276 if (m
->pkt_len
<= ETHER_MAX_JUMBO_FRAME_LEN
)
278 gather_len
= dpdk_gather_data(pd
->pcap_tmp_buf
, m
);
279 bp
= pd
->pcap_tmp_buf
;
280 pcap_header
.caplen
= gather_len
;
281 pcap_header
.len
= gather_len
;
284 // why only free this pkt
291 if (pd
->filter_in_userland
&& p
->fcode
.bf_insns
!=NULL
)
293 if (!pcap_filter(p
->fcode
.bf_insns
, bp
, pcap_header
.len
, pcap_header
.caplen
)){
299 cb(cb_arg
, &pcap_header
, bp
);
306 pd
->rx_pkts
= pkt_cnt
;
308 static int launch_one_lcore(void *dpdk_user
)
310 dpdk_dispatch_inter(dpdk_user
);
313 static int pcap_dpdk_dispatch(pcap_t
*p
, int max_cnt
, pcap_handler cb
, u_char
*pcap_user
)
315 unsigned lcore_id
= 0;
316 struct pcap_dpdk
*pd
= (struct pcap_dpdk
*)(p
->priv
);
319 pd
->cb_arg
= pcap_user
;
320 pd
->max_cnt
= max_cnt
;
323 // launch_one_lcore func will be called on every lcore include master core.
324 rte_eal_mp_remote_launch(launch_one_lcore
, dpdk_user
, CALL_MASTER
);
325 RTE_LCORE_FOREACH_SLAVE(lcore_id
) {
326 if (rte_eal_wait_lcore(lcore_id
) < 0) {
333 static int pcap_dpdk_inject(pcap_t
*p
, const void *buf _U_
, int size _U_
)
335 //not implemented yet
336 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
337 errno
, "dpdk error: Inject function has not be implemented yet");
341 static void pcap_dpdk_close(pcap_t
*p
)
343 struct pcap_dpdk
*pd
= p
->priv
;
348 if (pd
->must_clear_promisc
)
350 rte_eth_promiscuous_disable(pd
->portid
);
352 rte_eth_dev_stop(pd
->portid
);
353 rte_eth_dev_close(pd
->portid
);
355 pcap_cleanup_live_common(p
);
358 static int pcap_dpdk_setfilter(pcap_t
*p
, struct bpf_program
*fp
)
360 //init bpf for dpdk, only support userspace bfp
361 struct pcap_dpdk
* pd
= p
->priv
;
363 ret
= install_bpf_program(p
, fp
);
365 pd
->filter_in_userland
= 1;
370 static void nic_stats_display(uint16_t portid
)
372 struct rte_eth_stats stats
;
373 rte_eth_stats_get(portid
, &stats
);
374 RTE_LOG(INFO
,USER1
, "portid:%d, RX-packets: %-10"PRIu64
" RX-errors: %-10"PRIu64
375 " RX-bytes: %-10"PRIu64
" RX-Imissed: %-10"PRIu64
"\n", portid
, stats
.ipackets
, stats
.ierrors
,
376 stats
.ibytes
,stats
.imissed
);
379 static int pcap_dpdk_stats(pcap_t
*p
, struct pcap_stat
*ps
)
381 struct pcap_dpdk
*pd
= p
->priv
;
382 rte_eth_stats_get(pd
->portid
,&(pd
->stats
));
383 ps
->ps_recv
= pd
->stats
.ipackets
;
384 ps
->ps_drop
= pd
->stats
.ierrors
;
385 ps
->ps_drop
+= pd
->bpf_drop
;
386 ps
->ps_ifdrop
= pd
->stats
.imissed
;
387 nic_stats_display(pd
->portid
);
391 static int pcap_dpdk_setnonblock(pcap_t
*p
, int fd _U_
){
392 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
393 errno
, "dpdk error: setnonblock not support");
397 static int pcap_dpdk_getnonblock(pcap_t
*p
){
398 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
399 errno
, "dpdk error: getnonblock not support");
403 static int check_link_status(uint16_t portid
, struct rte_eth_link
*plink
)
407 int max_check_time
= 2;
408 int check_interval
= 100; // 100ms
409 for (count
= 0; count
<= max_check_time
; count
++) {
410 memset(plink
, 0, sizeof(struct rte_eth_link
));
411 rte_eth_link_get_nowait(portid
, plink
);
412 if (plink
->link_status
== ETH_LINK_UP
)
417 rte_delay_ms(check_interval
);
423 // return portid by device name, otherwise return -1
424 static uint16_t portid_by_device(char * device
)
427 int len
= strlen(device
);
428 int prefix_len
= strlen(DPDK_PREFIX
);
429 unsigned long ret_ul
= 0L;
431 if (len
<=prefix_len
|| strncmp(device
, DPDK_PREFIX
, prefix_len
)) // check prefix dpdk:
435 if (device
[prefix_len
]>='0' && device
[prefix_len
]<='9')
437 ret_ul
= strtoul(&(device
[prefix_len
]), NULL
, 10);
438 ret
= (uint16_t)ret_ul
;
443 int parse_dpdk_cfg(char* dpdk_cfg
,char** dargv
)
446 memset(dargv
,0,sizeof(dargv
[0])*DPDK_ARGC_MAX
);
447 //current process name
450 RTE_LOG(INFO
, USER1
,"dpdk cfg: %s\n",dpdk_cfg
);
451 // find first non space char
452 // The last opt is NULL
453 for (i
=0;dpdk_cfg
[i
] && cnt
<DPDK_ARGC_MAX
-1;i
++){
454 if (skip_space
&& dpdk_cfg
[i
]!=0x20){ // not space
455 skip_space
=!skip_space
; // skip normal char
456 dargv
[cnt
++] = dpdk_cfg
+i
;
458 if (!skip_space
&& dpdk_cfg
[i
]==0x20){ // fint a space
459 dpdk_cfg
[i
]=0x00; // end of this opt
460 skip_space
=!skip_space
; // skip space char
466 static int pcap_dpdk_activate(pcap_t
*p
)
468 struct pcap_dpdk
*pd
= p
->priv
;
470 int ret
= PCAP_ERROR
;
473 unsigned nb_mbufs
= DPDK_NB_MBUFS
;
474 struct rte_eth_rxconf rxq_conf
;
475 struct rte_eth_txconf txq_conf
;
476 struct rte_eth_conf local_port_conf
= port_conf
;
477 struct rte_eth_dev_info dev_info
;
479 struct rte_eth_link link
;
487 rte_log_set_global_level(RTE_LOG_DEBUG
);
489 char * dargv
[DPDK_ARGC_MAX
];
490 char *ptr_dpdk_cfg
= getenv(DPDK_CFG_ENV_NAME
);
491 if (ptr_dpdk_cfg
== NULL
)
493 RTE_LOG(INFO
,USER1
,"env $DPDK_CFG is unset, so using default: %s\n",DPDK_DEF_CFG
);
494 ptr_dpdk_cfg
= DPDK_DEF_CFG
;
496 memset(dpdk_cfg_buf
,0,sizeof(dpdk_cfg_buf
));
497 snprintf(dpdk_cfg_buf
,DPDK_CFG_MAX_LEN
-1,"%s %s",DPDK_LIB_NAME
,ptr_dpdk_cfg
);
498 dargv_cnt
= parse_dpdk_cfg(dpdk_cfg_buf
,dargv
);
499 ret
= rte_eal_init(dargv_cnt
,dargv
);
502 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
503 errno
, "dpdk error: Init failed with device %s",
508 ret
= dpdk_init_timer(pd
);
511 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
512 errno
, "dpdk error: Init timer error with device %s",
518 nb_ports
= rte_eth_dev_count_avail();
521 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
522 errno
, "dpdk error: No Ethernet ports");
527 portid
= portid_by_device(p
->opt
.device
);
529 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
530 errno
, "dpdk error: portid is invalid. device %s",
536 if (portid
>= nb_ports
)
538 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
539 errno
, "dpdk error: portid(%u) is larger than nb_ports(%u)",
545 if (p
->snapshot
<= 0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
547 p
->snapshot
= MAXIMUM_SNAPLEN
;
549 // create the mbuf pool
550 pd
->pktmbuf_pool
= rte_pktmbuf_pool_create(MBUF_POOL_NAME
, nb_mbufs
,
551 MEMPOOL_CACHE_SIZE
, 0, RTE_MBUF_DEFAULT_BUF_SIZE
,
553 if (pd
->pktmbuf_pool
== NULL
)
555 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
556 errno
, "dpdk error: Cannot init mbuf pool");
561 rte_eth_dev_info_get(portid
, &dev_info
);
562 if (dev_info
.tx_offload_capa
& DEV_TX_OFFLOAD_MBUF_FAST_FREE
)
564 local_port_conf
.txmode
.offloads
|=DEV_TX_OFFLOAD_MBUF_FAST_FREE
;
566 // only support 1 queue
567 ret
= rte_eth_dev_configure(portid
, 1, 1, &local_port_conf
);
570 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
571 errno
, "dpdk error: Cannot configure device: err=%d, port=%u",
577 ret
= rte_eth_dev_adjust_nb_rx_tx_desc(portid
, &nb_rxd
, &nb_txd
);
580 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
581 errno
, "dpdk error: Cannot adjust number of descriptors: err=%d, port=%u",
587 rte_eth_macaddr_get(portid
, &(pd
->eth_addr
));
590 rxq_conf
= dev_info
.default_rxconf
;
591 rxq_conf
.offloads
= local_port_conf
.rxmode
.offloads
;
592 ret
= rte_eth_rx_queue_setup(portid
, 0, nb_rxd
,
593 rte_eth_dev_socket_id(portid
),
598 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
599 errno
, "dpdk error: rte_eth_rx_queue_setup:err=%d, port=%u",
606 txq_conf
= dev_info
.default_txconf
;
607 txq_conf
.offloads
= local_port_conf
.txmode
.offloads
;
608 ret
= rte_eth_tx_queue_setup(portid
, 0, nb_txd
,
609 rte_eth_dev_socket_id(portid
),
613 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
614 errno
, "dpdk error: rte_eth_tx_queue_setup:err=%d, port=%u",
619 // Initialize TX buffers
620 tx_buffer
= rte_zmalloc_socket(DPDK_TX_BUF_NAME
,
621 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST
), 0,
622 rte_eth_dev_socket_id(portid
));
623 if (tx_buffer
== NULL
)
625 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
626 errno
, "dpdk error: Cannot allocate buffer for tx on port %u", portid
);
630 rte_eth_tx_buffer_init(tx_buffer
, MAX_PKT_BURST
);
632 ret
= rte_eth_dev_start(portid
);
635 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
636 errno
, "dpdk error: rte_eth_dev_start:err=%d, port=%u",
642 pd
->must_clear_promisc
=1;
643 rte_eth_promiscuous_enable(portid
);
645 is_port_up
= check_link_status(portid
, &link
);
647 pcap_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
648 errno
, "dpdk error: link is down, port=%u",portid
);
653 rte_eth_stats_reset(pd
->portid
);
657 if (p
->snapshot
<=0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
659 p
->snapshot
= MAXIMUM_SNAPLEN
;
661 p
->linktype
= DLT_EN10MB
; // Ethernet, the 10MB is historical.
662 p
->selectable_fd
= p
->fd
;
663 p
->read_op
= pcap_dpdk_dispatch
;
664 p
->inject_op
= pcap_dpdk_inject
;
665 p
->setfilter_op
= pcap_dpdk_setfilter
;
666 p
->setdirection_op
= NULL
;
667 p
->set_datalink_op
= NULL
;
668 p
->getnonblock_op
= pcap_dpdk_getnonblock
;
669 p
->setnonblock_op
= pcap_dpdk_setnonblock
;
670 p
->stats_op
= pcap_dpdk_stats
;
671 p
->cleanup_op
= pcap_dpdk_close
;
672 p
->breakloop_op
= pcap_dpdk_breakloop
;
675 rte_eth_dev_get_name_by_port(portid
,pd
->pci_addr
);
676 RTE_LOG(INFO
, USER1
,"%s device %s portid %d, pci_addr: %s\n", __FUNCTION__
, p
->opt
.device
, portid
, pd
->pci_addr
);
677 RTE_LOG(INFO
, USER1
,"Port %d Link Up. Speed %u Mbps - %s\n",
678 portid
, link
.link_speed
,
679 (link
.link_duplex
== ETH_LINK_FULL_DUPLEX
) ?
680 ("full-duplex") : ("half-duplex\n"));
681 RTE_LOG(INFO
, USER1
,"Port %u, MAC address:", portid
);
682 for (int i
=0; i
<6; i
++)
686 fprintf(stderr
,"%02X",pd
->eth_addr
.addr_bytes
[i
]);
688 fprintf(stderr
,":%02X", pd
->eth_addr
.addr_bytes
[i
]);
691 fprintf(stderr
,"\n\n");
692 if (ret
== PCAP_ERROR
)
694 pcap_cleanup_live_common(p
);
699 // device name for dpdk shoud be in the form as dpdk:number, such as dpdk:0
700 pcap_t
* pcap_dpdk_create(const char *device
, char *ebuf
, int *is_ours
)
705 *is_ours
= !strncmp(device
, "dpdk:", 5);
709 p
= pcap_create_common(ebuf
, sizeof(struct pcap_dpdk
));
713 p
->activate_op
= pcap_dpdk_activate
;
717 int pcap_dpdk_findalldevs(pcap_if_list_t
*devlistp _U_
, char *err_str _U_
)