X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/cc375cfa6a73647560346fab3b6a49042d397c47..HEAD:/pcap-dpdk.c diff --git a/pcap-dpdk.c b/pcap-dpdk.c index 4513ffba..76de9b76 100644 --- a/pcap-dpdk.c +++ b/pcap-dpdk.c @@ -34,7 +34,7 @@ Description: Limitations: 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. +2. Only support link libdpdk.so dynamically, because the libdpdk.a will not work correctly. 3. Only support read operation, and packet injection has not been supported yet. Usage: @@ -50,12 +50,12 @@ sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/' $RTE_SDK 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 -Then launch the l2fwd with dynamic dirver support. For example: +Then launch the l2fwd with dynamic driver 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. -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 +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 export RTE_SDK={your DPDK base directory} export RTE_TARGET={your target name} @@ -70,14 +70,12 @@ mkdir -p build && cd build && cmake -DDPDK_DIR=$RTE_SDK/$RTE_TARGET ../ && make 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: +For example, the testprogs/capturetest could be launched by: env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so" ./capturetest -i dpdk:0 */ -#ifdef HAVE_CONFIG_H #include -#endif #include #include @@ -85,6 +83,7 @@ env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so #include #include #include +#include /* for INT_MAX */ #include #include @@ -272,7 +271,7 @@ static inline void calculate_timestamp(struct dpdk_ts_helper *helper,struct time timeradd(&(helper->start_time), &cur_time, ts); } -static uint32_t dpdk_gather_data(unsigned char *data, int len, struct rte_mbuf *mbuf) +static uint32_t dpdk_gather_data(unsigned char *data, uint32_t len, struct rte_mbuf *mbuf) { uint32_t total_len = 0; while (mbuf && (total_len+mbuf->data_len) < len ){ @@ -284,7 +283,7 @@ static uint32_t dpdk_gather_data(unsigned char *data, int len, struct rte_mbuf * } -static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){ +static int dpdk_read_with_timeout(pcap_t *p, struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){ struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv); int nb_rx = 0; int timeout_ms = p->opt.timeout; @@ -293,7 +292,7 @@ static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, struct rte_mbuf ** // In non-blocking mode, just read once, no matter how many packets are captured. nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt); }else{ - // In blocking mode, read many times until packets are captured or timeout or break_loop is setted. + // In blocking mode, read many times until packets are captured or timeout or break_loop is set. // if timeout_ms == 0, it may be blocked forever. while (timeout_ms == 0 || sleep_ms < timeout_ms){ nb_rx = (int)rte_eth_rx_burst(pd->portid, 0, pkts_burst, burst_cnt); @@ -321,7 +320,6 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *m; struct pcap_pkthdr pcap_header; - uint16_t portid = pd->portid; // In DPDK, pkt_len is sum of lengths for all segments. And data_len is for one segment uint32_t pkt_len = 0; uint32_t caplen = 0; @@ -332,26 +330,41 @@ 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; - if ( !PACKET_COUNT_IS_UNLIMITED(max_cnt) && max_cnt < MAX_PKT_BURST){ + /* + * This can conceivably process more than INT_MAX packets, + * which would overflow the packet count, causing it either + * to look like a negative number, and thus cause us to + * return a value that looks like an error, or overflow + * back into positive territory, and thus cause us to + * return a too-low count. + * + * Therefore, if the packet count is unlimited, we clip + * it at INT_MAX; this routine is not expected to + * process packets indefinitely, so that's not an issue. + */ + if (PACKET_COUNT_IS_UNLIMITED(max_cnt)) + max_cnt = INT_MAX; + + if (max_cnt < MAX_PKT_BURST){ burst_cnt = max_cnt; }else{ burst_cnt = MAX_PKT_BURST; } - while( PACKET_COUNT_IS_UNLIMITED(max_cnt) || pkt_cnt < max_cnt){ + while( pkt_cnt < max_cnt){ if (p->break_loop){ p->break_loop = 0; return PCAP_ERROR_BREAK; } // read once in non-blocking mode, or try many times waiting for timeout_ms. - // if timeout_ms == 0, it will be blocked until one packet arrives or break_loop is setted. - nb_rx = dpdk_read_with_timeout(p, portid, pkts_burst, burst_cnt); + // if timeout_ms == 0, it will be blocked until one packet arrives or break_loop is set. + nb_rx = dpdk_read_with_timeout(p, pkts_burst, burst_cnt); if (nb_rx == 0){ if (pd->nonblock){ RTE_LOG(DEBUG, USER1, "dpdk: no packets available in non-blocking mode.\n"); }else{ if (p->break_loop){ - RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is setted in blocking mode.\n"); + RTE_LOG(DEBUG, USER1, "dpdk: no packets available and break_loop is set in blocking mode.\n"); p->break_loop = 0; return PCAP_ERROR_BREAK; @@ -392,7 +405,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c } if (bp){ - if (p->fcode.bf_insns==NULL || pcap_filter(p->fcode.bf_insns, bp, pcap_header.len, pcap_header.caplen)){ + if (p->fcode.bf_insns==NULL || pcapint_filter(p->fcode.bf_insns, bp, pcap_header.len, pcap_header.caplen)){ cb(cb_arg, &pcap_header, bp); }else{ pd->bpf_drop++; @@ -412,7 +425,7 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c static int pcap_dpdk_inject(pcap_t *p, const void *buf _U_, int size _U_) { //not implemented yet - pcap_strlcpy(p->errbuf, + pcapint_strlcpy(p->errbuf, "dpdk error: Inject function has not been implemented yet", PCAP_ERRBUF_SIZE); return PCAP_ERROR; @@ -431,7 +444,7 @@ static void pcap_dpdk_close(pcap_t *p) } rte_eth_dev_stop(pd->portid); rte_eth_dev_close(pd->portid); - pcap_cleanup_live_common(p); + pcapint_cleanup_live_common(p); } static void nic_stats_display(struct pcap_dpdk *pd) @@ -514,8 +527,8 @@ static void eth_addr_str(ETHER_ADDR_TYPE *addrp, char* mac_str, int len) static uint16_t portid_by_device(char * device) { uint16_t ret = DPDK_PORTID_MAX; - int len = strlen(device); - int prefix_len = strlen(DPDK_PREFIX); + size_t len = strlen(device); + size_t prefix_len = strlen(DPDK_PREFIX); unsigned long ret_ul = 0L; char *pEnd; if (len<=prefix_len || strncmp(device, DPDK_PREFIX, prefix_len)) // check prefix dpdk: @@ -555,7 +568,7 @@ static int parse_dpdk_cfg(char* dpdk_cfg,char** dargv) skip_space=!skip_space; // skip normal char dargv[cnt++] = dpdk_cfg+i; } - if (!skip_space && dpdk_cfg[i]==' '){ // fint a space + if (!skip_space && dpdk_cfg[i]==' '){ // find a space dpdk_cfg[i]=0x00; // end of this opt skip_space=!skip_space; // skip space char } @@ -585,7 +598,7 @@ static int dpdk_pre_init(char * ebuf, int eaccess_not_fatal) char *dargv[DPDK_ARGC_MAX]; char *ptr_dpdk_cfg = NULL; int ret; - // globale var + // global var if (is_dpdk_pre_inited != 0) { // already inited; did that succeed? @@ -933,15 +946,15 @@ static int pcap_dpdk_activate(pcap_t *p) p->selectable_fd = p->fd; p->read_op = pcap_dpdk_dispatch; p->inject_op = pcap_dpdk_inject; - // using pcap_filter currently, though DPDK provides their own BPF function. Because DPDK BPF needs load a ELF file as a filter. - p->setfilter_op = install_bpf_program; + // using pcapint_filter currently, though DPDK provides their own BPF function. Because DPDK BPF needs load a ELF file as a filter. + p->setfilter_op = pcapint_install_bpf_program; p->setdirection_op = NULL; p->set_datalink_op = NULL; p->getnonblock_op = pcap_dpdk_getnonblock; p->setnonblock_op = pcap_dpdk_setnonblock; p->stats_op = pcap_dpdk_stats; p->cleanup_op = pcap_dpdk_close; - p->breakloop_op = pcap_breakloop_common; + p->breakloop_op = pcapint_breakloop_common; // set default timeout pd->required_select_timeout.tv_sec = 0; pd->required_select_timeout.tv_usec = DPDK_DEF_MIN_SLEEP_MS*1000; @@ -951,7 +964,7 @@ static int pcap_dpdk_activate(pcap_t *p) if (ret <= PCAP_ERROR) // all kinds of error code { - pcap_cleanup_live_common(p); + pcapint_cleanup_live_common(p); }else{ rte_eth_dev_get_name_by_port(portid,pd->pci_addr); RTE_LOG(INFO, USER1,"Port %d device: %s, MAC:%s, PCI:%s\n", portid, p->opt.device, pd->mac_addr, pd->pci_addr); @@ -963,7 +976,7 @@ static int pcap_dpdk_activate(pcap_t *p) return ret; } -// device name for dpdk shoud be in the form as dpdk:number, such as dpdk:0 +// device name for dpdk should be in the form as dpdk:number, such as dpdk:0 pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours) { pcap_t *p=NULL; @@ -973,7 +986,7 @@ pcap_t * pcap_dpdk_create(const char *device, char *ebuf, int *is_ours) if (! *is_ours) return NULL; //memset will happen - p = pcap_create_common(ebuf, sizeof(struct pcap_dpdk)); + p = PCAP_CREATE_COMMON(ebuf, struct pcap_dpdk); if (p == NULL) return NULL; @@ -1026,7 +1039,7 @@ int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) // PCI addr rte_eth_dev_get_name_by_port(i,pci_addr); snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr); - if (add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){ + if (pcapint_add_dev(devlistp, dpdk_name, 0, dpdk_desc, ebuf)==NULL){ ret = PCAP_ERROR; break; } @@ -1044,7 +1057,7 @@ int pcap_dpdk_findalldevs(pcap_if_list_t *devlistp, char *ebuf) * There are no regular interfaces, just DPDK interfaces. */ int -pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf) +pcapint_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf) { return (0); } @@ -1053,10 +1066,9 @@ pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf) * Attempts to open a regular interface fail. */ pcap_t * -pcap_create_interface(const char *device, char *errbuf) +pcapint_create_interface(const char *device, char *errbuf) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, - "This version of libpcap only supports DPDK"); + snprintf(errbuf, PCAP_ERRBUF_SIZE, PCAP_ENODEV_MESSAGE, "DPDK"); return NULL; }