developers for inclusion in libpcap, not only does that make it more
likely that it will be available in the libpcap provided by operating
system vendors (such as Linux distributions), but it also means that we
-will attempt to update it to handle future changes to this interface.
+will attempt to update it to handle future changes to this interface.
If we add new capabilities, we may have to ask you how to provide those
additional capabilities if you're using an underlying mechanism for
which we have neither the source code nor the documentation.
If it *is* one of those devices, it should call pcap_create_common,
passing to it the error message buffer as the first argument and the
-size of the per-opened instance data structure as the second argument.
+size of the per-opened instance data structure as the second argument.
If it fails, it will return NULL; you must return NULL in this case.
If it succeeds, the pcap_t pointed to by the return value has been
cleanup_op
called if the activate routine fails or pcap_close() is
- called
+ called
and must also set the linktype member to the DLT_ value for the device.
pcap_filter(), passing it the fcode.bf_insns member of the pcap_t, the
raw packet data, the on-the-wire length of the packet, and the captured
length of the packet, and only passing the packet to the callback
-routine, and counting it, if pcap_filter() returns a non-zero value.
+routine, and counting it, if pcap_filter() returns a non-zero value.
(If the flag is not set, all packets should be passed to the callback
routine and counted, as the filtering is being done by the mechanism
used by the module.) If install_bpf_program() returns a negative value,
handle that.
The setdirection routine is passed a pointer to the pcap_t and a
-pcap_direction_t indicating which packet directions should be accepted.
+pcap_direction_t indicating which packet directions should be accepted.
If the module can't arrange to handle only incoming packets or only
outgoing packets, it can set the pointer to the setdirection routine to
NULL, and calls to pcap_setdirection() will fail with an error message
Description:
1. Pcap-dpdk provides libpcap the ability to use DPDK with the device name as dpdk:{portid}, such as dpdk:0.
-2. DPDK is a set of libraries and drivers for fast packet processing. (https://www.dpdk.org/)
+2. DPDK is a set of libraries and drivers for fast packet processing. (https://www.dpdk.org/)
3. The testprogs/capturetest provides 6.4Gbps/800,000 pps on Intel 10-Gigabit X540-AT2 with DPDK 18.11.
Limitations:
3.2 With cmake
-mkdir -p build && cd build && cmake -DDPDK_DIR=$RTE_SDK/$RTE_TARGET ../ && 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.
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 lanched by:
env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so -dlibrte_mempool_ring.so" ./capturetest -i dpdk:0
*/
#define DPDK_LIB_NAME "libpcap_dpdk"
#define DPDK_DESC "Data Plane Development Kit (DPDK) Interface"
#define DPDK_ERR_PERM_MSG "permission denied, DPDK needs root permission"
-#define DPDK_ARGC_MAX 64
+#define DPDK_ARGC_MAX 64
#define DPDK_CFG_MAX_LEN 1024
#define DPDK_DEV_NAME_MAX 32
-#define DPDK_DEV_DESC_MAX 512
+#define DPDK_DEV_DESC_MAX 512
#define DPDK_CFG_ENV_NAME "DPDK_CFG"
#define DPDK_DEF_MIN_SLEEP_MS 1
static char dpdk_cfg_buf[DPDK_CFG_MAX_LEN];
//The number of elements in the mbuf pool.
#define DPDK_NB_MBUFS 8192U
#define MEMPOOL_CACHE_SIZE 256
-#define MAX_PKT_BURST 32
+#define MAX_PKT_BURST 32
// Configurable number of RX/TX ring descriptors
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 1024
pd->ts_helper.start_cycles = rte_get_timer_cycles();
pd->ts_helper.hz = rte_get_timer_hz();
if (pd->ts_helper.hz == 0){
- return -1;
+ return -1;
}
return 0;
}
static int dpdk_read_with_timeout(pcap_t *p, uint16_t portid, uint16_t queueid,struct rte_mbuf **pkts_burst, const uint16_t burst_cnt){
struct pcap_dpdk *pd = (struct pcap_dpdk*)(p->priv);
- int nb_rx = 0;
+ int nb_rx = 0;
int timeout_ms = p->opt.timeout;
int sleep_ms = 0;
if (pd->nonblock){
// In non-blocking mode, just read once, no mater 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 setted.
// 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);
if (nb_rx){ // got packets within timeout_ms
- break;
+ break;
}else{ // no packet arrives at this round.
if (p->break_loop){
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, 0, pkts_burst, burst_cnt);
- if (nb_rx == 0){
+ if (nb_rx == 0){
if (pd->nonblock){
RTE_LOG(DEBUG, USER1, "dpdk: no packets available in non-blocking mode.\n");
}else{
RTE_LOG(DEBUG, USER1, "dpdk: no packets available for timeout %d ms in blocking mode.\n", timeout_ms);
}
// break if dpdk reads 0 packet, no matter in blocking(timeout) or non-blocking mode.
- break;
+ break;
}
pkt_cnt += nb_rx;
for ( i = 0; i < nb_rx; i++) {
pkt_len = rte_pktmbuf_pkt_len(m);
// caplen = min(pkt_len, p->snapshot);
// caplen will not be changed, no matter how long the rte_pktmbuf
- caplen = pkt_len < p->snapshot ? pkt_len: p->snapshot;
+ caplen = pkt_len < p->snapshot ? pkt_len: p->snapshot;
pcap_header.caplen = caplen;
- pcap_header.len = pkt_len;
+ pcap_header.len = pkt_len;
// volatile prefetch
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
bp = NULL;
{
gather_len = dpdk_gather_data(pd->pcap_tmp_buf, RTE_ETH_PCAP_SNAPLEN, m);
bp = pd->pcap_tmp_buf;
- }else{
+ }else{
// need call free later
large_buffer = (u_char *)malloc(caplen*sizeof(u_char));
- gather_len = dpdk_gather_data(large_buffer, caplen, m);
+ gather_len = dpdk_gather_data(large_buffer, caplen, m);
bp = large_buffer;
}
-
+
}
if (bp){
if (p->fcode.bf_insns==NULL || pcap_filter(p->fcode.bf_insns, bp, pcap_header.len, pcap_header.caplen)){
large_buffer=NULL;
}
}
- }
+ }
return pkt_cnt;
}
if (pd==NULL)
{
return;
- }
+ }
if (pd->must_clear_promisc)
{
rte_eth_promiscuous_disable(pd->portid);
rte_eth_dev_stop(pd->portid);
rte_eth_dev_close(pd->portid);
pcap_cleanup_live_common(p);
-}
+}
static void nic_stats_display(struct pcap_dpdk *pd)
{
// return portid by device name, otherwise return -1
static uint16_t portid_by_device(char * device)
{
- uint16_t ret = DPDK_PORTID_MAX;
+ uint16_t ret = DPDK_PORTID_MAX;
int len = strlen(device);
int prefix_len = strlen(DPDK_PREFIX);
unsigned long ret_ul = 0L;
//check all chars are digital
for (int i=prefix_len; device[i]; i++){
if (device[i]<'0' || device[i]>'9'){
- return ret;
+ return ret;
}
}
ret_ul = strtoul(&(device[prefix_len]), &pEnd, 10);
return ret;
}
// too large for portid
- if (ret_ul >= DPDK_PORTID_MAX){
+ if (ret_ul >= DPDK_PORTID_MAX){
return ret;
}
ret = (uint16_t)ret_ul;
static int parse_dpdk_cfg(char* dpdk_cfg,char** dargv)
{
int cnt=0;
- memset(dargv,0,sizeof(dargv[0])*DPDK_ARGC_MAX);
+ memset(dargv,0,sizeof(dargv[0])*DPDK_ARGC_MAX);
//current process name
int skip_space = 1;
int i=0;
int dargv_cnt=0;
char *dargv[DPDK_ARGC_MAX];
char *ptr_dpdk_cfg = NULL;
- int ret = PCAP_ERROR;
+ int ret = PCAP_ERROR;
// globale var
if (is_dpdk_pre_inited)
{
errno, "dpdk error: %s",
DPDK_ERR_PERM_MSG);
ret = PCAP_ERROR_PERM_DENIED;
- return ret;
+ return ret;
}
// init EAL
ptr_dpdk_cfg = getenv(DPDK_CFG_ENV_NAME);
{
p->snapshot = MAXIMUM_SNAPLEN;
}
- // create the mbuf pool
+ // create the mbuf pool
pd->pktmbuf_pool = rte_pktmbuf_pool_create(MBUF_POOL_NAME, nb_mbufs,
MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
rte_socket_id());
errno, "dpdk error: Cannot configure device: err=%d, port=%u",
ret, portid);
ret = PCAP_ERROR;
- break;
+ break;
}
// adjust rx tx
ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, &nb_txd);
errno, "dpdk error: Cannot adjust number of descriptors: err=%d, port=%u",
ret, portid);
ret = PCAP_ERROR;
- break;
+ break;
}
// get MAC addr
rte_eth_macaddr_get(portid, &(pd->eth_addr));
errno, "dpdk error: rte_eth_rx_queue_setup:err=%d, port=%u",
ret, portid);
ret = PCAP_ERROR;
- break;
+ break;
}
- // init one TX queue
+ // init one TX queue
txq_conf = dev_info.default_txconf;
txq_conf.offloads = local_port_conf.txmode.offloads;
ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
errno, "dpdk error: rte_eth_tx_queue_setup:err=%d, port=%u",
ret, portid);
ret = PCAP_ERROR;
- break;
+ break;
}
- // Initialize TX buffers
+ // Initialize TX buffers
tx_buffer = rte_zmalloc_socket(DPDK_TX_BUF_NAME,
RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
rte_eth_dev_socket_id(portid));
pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "dpdk error: Cannot allocate buffer for tx on port %u", portid);
ret = PCAP_ERROR;
- break;
+ break;
}
rte_eth_tx_buffer_init(tx_buffer, MAX_PKT_BURST);
// Start device
// reset statistics
rte_eth_stats_reset(pd->portid);
calculate_timestamp(&(pd->ts_helper), &(pd->prev_ts));
- rte_eth_stats_get(pd->portid,&(pd->prev_stats));
- // format pcap_t
+ rte_eth_stats_get(pd->portid,&(pd->prev_stats));
+ // format pcap_t
pd->portid = portid;
- p->fd = pd->portid;
+ p->fd = pd->portid;
if (p->snapshot <=0 || p->snapshot> MAXIMUM_SNAPLEN)
{
p->snapshot = MAXIMUM_SNAPLEN;
return NULL;
//memset will happen
p = pcap_create_common(ebuf, sizeof(struct pcap_dpdk));
-
+
if (p == NULL)
return NULL;
p->activate_op = pcap_dpdk_activate;
for (unsigned int i=0; i<nb_ports; i++){
pcap_snprintf(dpdk_name, DPDK_DEV_NAME_MAX-1,
"%s%u", DPDK_PREFIX, i);
- // mac addr
+ // mac addr
rte_eth_macaddr_get(i, ð_addr);
- eth_addr_str(ð_addr,mac_addr,DPDK_MAC_ADDR_SIZE);
+ eth_addr_str(ð_addr,mac_addr,DPDK_MAC_ADDR_SIZE);
// PCI addr
rte_eth_dev_get_name_by_port(i,pci_addr);
pcap_snprintf(dpdk_desc,DPDK_DEV_DESC_MAX-1,"%s %s, MAC:%s, PCI:%s", DPDK_DESC, dpdk_name, mac_addr, pci_addr);
ret = PCAP_ERROR;
break;
}
- }
- }while(0);
+ }
+ }while(0);
return ret;
}