X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/8bc08b5fb29041c441b0167842f1ed3d7cbf9be2..f0363d0cb7fc0e66ac9eac1b6512efe92fce89c5:/pcap-dpdk.c diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 824a5de0..4175a11d 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -33,19 +33,19 @@ Description: 3. The testprogs/capturetest provides 6.4Gbps/800,000 pps on Intel 10-Gigabit X540-AT2 with DPDK 18.11. Limitations: -1. By default DPDK support is no, unless you explicitly set --enable-dpdk with ./configure or -DDISABLE_DPDK=OFF with cmake. +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. 2. Only support link libdpdk.so dynamicly, because the libdpdk.a will not work correctly. 3. Only support read operation, and packet injection has not been supported yet. Usage: -1. compile DPDK as shared library and install.(https://github.com/DPDK/dpdk.git) +1. Compile DPDK as shared library and install.(https://github.com/DPDK/dpdk.git) You shall modify the file $RTE_SDK/$RTE_TARGET/.config and set: CONFIG_RTE_BUILD_SHARED_LIB=y By the following command: sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/' $RTE_SDK/$RTE_TARGET/.config -2. launch l2fwd that is one of DPDK examples correctly, and get device information. +2. Launch l2fwd that is one of DPDK examples correctly, and get device information. You shall learn how to bind nic with DPDK-compatible driver by $RTE_SDK/usertools/dpdk-devbind.py, such as igb_uio. And enable hugepages by dpdk-setup.sh @@ -53,22 +53,22 @@ And enable hugepages by dpdk-setup.sh Then launch the l2fwd with dynamic dirver support. For example: $RTE_SDK/examples/l2fwd/$RTE_TARGET/l2fwd -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so -- -p 0x1 -3. compile libpcap with dpdk options. +3. Compile libpcap with dpdk options. -In order to find inlucde and lib automatically, you shall export DPDK envionment variable which are used for compiling DPDK. +If DPDK has not been found automatically, you shall export DPDK envionment variable which are used for compiling DPDK. And then pass $RTE_SDK/$RTE_TARGET to --with-dpdk or -DDPDK_DIR export RTE_SDK={your DPDK base directory} export RTE_TARGET={your target name} -3.1 with configure +3.1 With configure -./configure --enable-dpdk --with-dpdk-includes=$RTE_SDK/$RTE_TARGET/include --with-dpdk-libraries=$RTE_SDK/$RTE_TARGET/lib && make -s all && make -s testprogs && make install +./configure --with-dpdk=$RTE_SDK/$RTE_TARGET && make -s all && make -s testprogs && make install -3.2 with cmake +3.2 With cmake -mkdir -p build && cd build && cmake -DDISABLE_DPDK=OFF -DDPDK_INC_DIR=$RTE_SDK/$RTE_TARGET/include -DDPDK_LIB_DIR=$RTE_SDK/$RTE_TARGET/lib" ../ && make -s all && make -s testprogs && make install +mkdir -p build && cd build && cmake -DDPDK_DIR=$RTE_SDK/$RTE_TARGET ../ && make -s all && make -s testprogs && make install -4. link your own program with libpcap, and use DPDK with the device name as dpdk:{portid}, such as dpdk:0. +4. Link your own program with libpcap, and use DPDK with the device name as dpdk:{portid}, such as dpdk:0. And you shall set DPDK configure options by environment variable DPDK_CFG For example, the testprogs/capturetest could be lanched by: @@ -158,9 +158,9 @@ struct pcap_dpdk{ pcap_t * orig; uint16_t portid; // portid of DPDK int must_clear_promisc; - uint64_t rx_pkts; uint64_t bpf_drop; int nonblock; + struct timeval required_select_timeout; struct timeval prev_ts; struct rte_eth_stats prev_stats; struct timeval curr_ts; @@ -235,7 +235,8 @@ static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, uint16_t queueid,s if (p->break_loop){ break; } - // sleep for a very short while, but do not block CPU. + // sleep for a very short while. + // block sleep is the only choice, since usleep() will impact performance dramatically. rte_delay_us_block(DPDK_DEF_MIN_SLEEP_MS*1000); sleep_ms += DPDK_DEF_MIN_SLEEP_MS; } @@ -264,7 +265,6 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c u_char *large_buffer=NULL; int timeout_ms = p->opt.timeout; - pd->rx_pkts = 0; if ( !PACKET_COUNT_IS_UNLIMITED(max_cnt) && max_cnt < MAX_PKT_BURST){ burst_cnt = max_cnt; }else{ @@ -273,7 +273,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c while( PACKET_COUNT_IS_UNLIMITED(max_cnt) || pkt_cnt < max_cnt){ if (p->break_loop){ - p->break_loop = 1; + p->break_loop = 0; return PCAP_ERROR_BREAK; } // read once in non-blocking mode, or try many times waiting for timeout_ms. @@ -285,7 +285,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c }else{ if (p->break_loop){ RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is setted in blocking mode.\n"); - p->break_loop = 1; + p->break_loop = 0; return PCAP_ERROR_BREAK; } @@ -339,8 +339,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c } } } - pd->rx_pkts = pkt_cnt; - return pd->rx_pkts; + return pkt_cnt; } static int pcap_dpdk_inject(pcap_t *p, const void *buf _U_, int size _U_) @@ -729,6 +728,10 @@ static int pcap_dpdk_activate(pcap_t *p) p->stats_op = pcap_dpdk_stats; p->cleanup_op = pcap_dpdk_close; p->breakloop_op = pcap_breakloop_common; + // set default timeout + pd->required_select_timeout.tv_sec = 0; + pd->required_select_timeout.tv_usec = DPDK_DEF_MIN_SLEEP_MS*1000; + p->required_select_timeout = &pd->required_select_timeout; ret = 0; // OK }while(0); @@ -767,7 +770,7 @@ pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours) int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) { int ret=0; - int nb_ports = 0; + unsigned int nb_ports = 0; char dpdk_name[DPDK_DEV_NAME_MAX]; char dpdk_desc[DPDK_DEV_DESC_MAX]; struct ether_addr eth_addr; @@ -790,8 +793,9 @@ int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) ret = PCAP_ERROR; break; } - for (int i=0; i