net/pcap: capture only ingress packets from Rx iface

Support rx of in direction packets only
Useful for apps that also tx to eth_pcap ports in order to not see them
echoed back in as rx when out direction is also captured

Example:
In case using rx_iface and sending *single* packet to eth1
it will loop forever as the when it is sent to tx_iface=eth1
it will be captured again on the rx_iface=eth1 and so on
  $RTE_TARGET/app/testpmd l 0-3 -n 4 \
	--vdev 'net_pcap0,rx_iface=eth1,tx_iface=eth1'
  …
  ---------------------- Forward statistics for port 0  ------------
  RX-packets: 758            RX-dropped: 0             RX-total: 758
  TX-packets: 758            TX-dropped: 0             TX-total: 758
  ------------------------------------------------------------------
While if using rx_iface_in it will not be captured on the way out and
be forwarded only once
  $RTE_TARGET/app/testpmd l 0-3 -n 4 \
	--vdev 'net_pcap0,rx_iface_in=eth1,tx_iface=eth1'
  …
  ---------------------- Forward statistics for port 0  ------------
  RX-packets: 1              RX-dropped: 0             RX-total: 1
  TX-packets: 1              TX-dropped: 0             TX-total: 1
  ------------------------------------------------------------------

Signed-off-by: Ido Goshen <ido@cgstowernetworks.com>
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Ido Goshen 2018-07-01 14:05:34 +03:00 committed by Ferruh Yigit
parent 8028142107
commit 53bf484034
2 changed files with 70 additions and 6 deletions

View File

@ -71,11 +71,19 @@ The different stream types are:
tx_pcap=/path/to/file.pcap
* rx_iface: Defines a reception stream based on a network interface name.
The driver reads packets coming from the given interface using the Linux kernel driver for that interface.
The driver reads packets from the given interface using the Linux kernel driver for that interface.
The driver captures both the incoming and outgoing packets on that interface.
The value is an interface name.
rx_iface=eth0
* rx_iface_in: Defines a reception stream based on a network interface name.
The driver reads packets from the given interface using the Linux kernel driver for that interface.
The driver captures only the incoming packets on that interface.
The value is an interface name.
rx_iface_in=eth0
* tx_iface: Defines a transmission stream based on a network interface name.
The driver sends packets to the given interface using the Linux kernel driver for that interface.
The value is an interface name.
@ -122,6 +130,21 @@ Forward packets through two network interfaces:
$RTE_TARGET/app/testpmd -l 0-3 -n 4 \
--vdev 'net_pcap0,iface=eth0' --vdev='net_pcap1;iface=eth1'
Enable 2 tx queues on a network interface:
.. code-block:: console
$RTE_TARGET/app/testpmd -l 0-3 -n 4 \
--vdev 'net_pcap0,rx_iface=eth1,tx_iface=eth1,tx_iface=eth1' \
-- --txq 2
Read only incoming packets from a network interface and write them back to the same network interface:
.. code-block:: console
$RTE_TARGET/app/testpmd -l 0-3 -n 4 \
--vdev 'net_pcap0,rx_iface_in=eth1,tx_iface=eth1'
Using libpcap-based PMD with the testpmd Application
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -26,6 +26,7 @@
#define ETH_PCAP_RX_PCAP_ARG "rx_pcap"
#define ETH_PCAP_TX_PCAP_ARG "tx_pcap"
#define ETH_PCAP_RX_IFACE_ARG "rx_iface"
#define ETH_PCAP_RX_IFACE_IN_ARG "rx_iface_in"
#define ETH_PCAP_TX_IFACE_ARG "tx_iface"
#define ETH_PCAP_IFACE_ARG "iface"
@ -83,6 +84,7 @@ static const char *valid_arguments[] = {
ETH_PCAP_RX_PCAP_ARG,
ETH_PCAP_TX_PCAP_ARG,
ETH_PCAP_RX_IFACE_ARG,
ETH_PCAP_RX_IFACE_IN_ARG,
ETH_PCAP_TX_IFACE_ARG,
ETH_PCAP_IFACE_ARG,
NULL
@ -739,6 +741,21 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
return 0;
}
static inline int
set_iface_direction(const char *iface, pcap_t *pcap,
pcap_direction_t direction)
{
const char *direction_str = (direction == PCAP_D_IN) ? "IN" : "OUT";
if (pcap_setdirection(pcap, direction) < 0) {
PMD_LOG(ERR, "Setting %s pcap direction %s failed - %s\n",
iface, direction_str, pcap_geterr(pcap));
return -1;
}
PMD_LOG(INFO, "Setting %s pcap direction %s\n",
iface, direction_str);
return 0;
}
static inline int
open_iface(const char *key, const char *value, void *extra_args)
{
@ -762,7 +779,29 @@ open_iface(const char *key, const char *value, void *extra_args)
static inline int
open_rx_iface(const char *key, const char *value, void *extra_args)
{
return open_iface(key, value, extra_args);
int ret = open_iface(key, value, extra_args);
if (ret < 0)
return ret;
if (strcmp(key, ETH_PCAP_RX_IFACE_IN_ARG) == 0) {
struct pmd_devargs *pmd = extra_args;
unsigned int qid = pmd->num_of_queue - 1;
set_iface_direction(pmd->queue[qid].name,
pmd->queue[qid].pcap,
PCAP_D_IN);
}
return 0;
}
static inline int
rx_iface_args_process(const char *key, const char *value, void *extra_args)
{
if (strcmp(key, ETH_PCAP_RX_IFACE_ARG) == 0 ||
strcmp(key, ETH_PCAP_RX_IFACE_IN_ARG) == 0)
return open_rx_iface(key, value, extra_args);
return 0;
}
/*
@ -965,12 +1004,13 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
is_rx_pcap = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG) ? 1 : 0;
pcaps.num_of_queue = 0;
if (is_rx_pcap)
if (is_rx_pcap) {
ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,
&open_rx_pcap, &pcaps);
else
ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_IFACE_ARG,
&open_rx_iface, &pcaps);
} else {
ret = rte_kvargs_process(kvlist, NULL,
&rx_iface_args_process, &pcaps);
}
if (ret < 0)
goto free_kvlist;
@ -1036,6 +1076,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_pcap,
ETH_PCAP_RX_PCAP_ARG "=<string> "
ETH_PCAP_TX_PCAP_ARG "=<string> "
ETH_PCAP_RX_IFACE_ARG "=<ifc> "
ETH_PCAP_RX_IFACE_IN_ARG "=<ifc> "
ETH_PCAP_TX_IFACE_ARG "=<ifc> "
ETH_PCAP_IFACE_ARG "=<ifc>");