net/tap: remote netdevice traffic capture
cover net/tap: remote netdevice traffic capture
This patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
Pascal Mazon (4):
net/tap: add remote netdevice traffic capture net/tap: reflect tap flags on the remote net/tap: use the remote MAC address if available net/tap: set MTU on the remote
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 212 ++++++++++++++++++--- drivers/net/tap/tap.h | 4 + drivers/net/tap/tap_flow.c | 414 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 631 insertions(+), 40 deletions(-)
Signature · 1 line
2.8.0.rc0
PATCH 1/4 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 78 +++++++- drivers/net/tap/tap.h | 3 + drivers/net/tap/tap_flow.c | 414 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 523 insertions(+), 13 deletions(-)
doc/guides/nics/tap.rst +17 -0
@@ -58,6 +58,23 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, then all packets with the tap PMD's local MAC coming +in on the remote netdevice will be redirected to the tap. +If the tap is in promiscuous mode, then all packets will be redirected. +In allmulti mode, all multicast packets will be redirected. +It is possible to add explicit rte_flow rules on the tap PMD to capture specific +traffic. For instance, in testpmd, the following rte_flow rule would capture +packets with the given MAC address from the remote, and send it to the tap RX +QUEUE 3:: + + testpmd> flow create 0 ingress pattern eth src is 02:03:04:05:06:07 / \ + end actions queue index 3 / end + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +76 -2
165 lines not on this page · raw message
drivers/net/tap/tap.h +3 -0
@@ -68,7 +68,10 @@ struct pmd_internals {uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ int if_index;/* IF_INDEX for the port */ +int remote_if_index;/* remote netdevice IF_INDEX */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +403 -11
520 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct rte_eth_dev *dev, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct rte_eth_dev *dev, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.8.0.rc0
PATCH 2/4 net/tap: reflect tap flags on the remote
In reply to Pascal MazonSynchronize PROMISC and ALLMULTI flags to the remote netdevice if possible.
Leave the IFF_UP flag as it is, however.
--- drivers/net/tap/rte_eth_tap.c | 36 +++++++++++++++++++++++------------- drivers/net/tap/tap.h | 1 + 2 files changed, 24 insertions(+), 13 deletions(-)
drivers/net/tap/rte_eth_tap.c +23 -13
@@ -249,7 +249,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) }static int -tap_link_set_flags (struct pmd_internals *pmd,short flags,int add) +tap_netdev_set_flags (const char *iface,short flags,int add) {struct ifreq ifr;int err, s;
@@ -266,11 +266,11 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , pmd->name); +snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , iface); err =ioctl (s,SIOCGIFFLAGS , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -288,6 +288,7 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)close (s);return 0 ; + } static int
@@ -296,7 +297,7 @@ tap_link_set_down(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_DOWN ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,0 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,0 ); } static int
@@ -305,7 +306,7 @@ tap_link_set_up(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_UP ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,1 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,1 ); } static int
@@ -476,9 +477,11 @@ tap_promisc_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =1 ; -tap_link_set_flags (pmd,IFF_PROMISC ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,1 ); + } } static void
@@ -487,9 +490,11 @@ tap_promisc_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =0 ; -tap_link_set_flags (pmd,IFF_PROMISC ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,0 ); + } } static void
@@ -498,9 +503,11 @@ tap_allmulti_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =1 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,1 ); + } } static void
@@ -509,9 +516,11 @@ tap_allmulti_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =0 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,0 ); + } } static void
@@ -924,6 +933,7 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)*/ pmd->nlsk_fd =nl_init ();if (strlen (remote_iface)) { +strncpy (pmd->remote_iface, remote_iface,RTE_ETH_NAME_MAX_LEN ); pmd->remote_if_index =if_nametoindex (remote_iface);if (!pmd->remote_if_index) RTE_LOG(ERR, PMD, "Could not find %s ifindex: "
drivers/net/tap/tap.h +1 -0
@@ -64,6 +64,7 @@ struct tx_queue {struct pmd_internals {char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ int nlsk_fd;/* Netlink socket fd */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */
Signature · 1 line
2.8.0.rc0
PATCH 3/4 net/tap: use the remote MAC address if available
In reply to Pascal MazonThe remote on a tap is most likely used with netdevices that are not under DPDK control. Outgoing traffic is supposed to use the source MAC address of the remote netdevice.
This commit synchronizes the MAC address of the local tap netdevice with the remote one.
Of course, it is still possible to change the tap MAC address, using standard DPDK APIs. It sets that MAC address on the tap PMD and redirect any packets matching that destination MAC to the tap PMD. It also tries setting the MAC address directly on the remote, if supported, through ioctl() calls.
--- drivers/net/tap/rte_eth_tap.c | 77 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-)
drivers/net/tap/rte_eth_tap.c +65 -12
@@ -523,6 +523,65 @@ tap_allmulti_disable(struct rte_eth_dev *dev) } } +static int +tap_netdev_set_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , + iface,strerror (errno)); +close (s); +return -1 ; + } +rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); + err =ioctl (s,SIOCSIFHWADDR , &ifr) ==-1 ; +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +return 0 ; +} + +static int +tap_netdev_get_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +rte_memcpy (mac_addr, ifr.ifr_hwaddr.sa_data,ETHER_ADDR_LEN ); +return 0 ; +} +static void tap_mac_remove(struct rte_eth_dev *dev __rte_unused, uint32_t index __rte_unused)
@@ -539,7 +598,6 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, {struct pmd_internals *internals = dev->data->dev_private;int fd = internals->rxq[0 ].fd; -struct ifreq ifr;if (index >RTE_PMD_TAP_MAX_MAC_ADDRS -1 ) { RTE_LOG(ERR, PMD,
@@ -559,19 +617,11 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, dev->data->name);return ; } -memset (&ifr,0 ,sizeof (struct ifreq )); -if (ioctl (fd,SIOCGIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , - dev->data->name,strerror (errno)); +if (tap_netdev_set_mac (internals->name, mac_addr) <0 )return ; - } -rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); -if (ioctl (fd,SIOCSIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , - dev->data->name,strerror (errno)); -return ; - }rte_memcpy (&dev->data->mac_addrs[index], mac_addr,ETHER_ADDR_LEN ); +if (internals->remote_if_index) +tap_netdev_set_mac (internals->remote_iface, mac_addr); } static void
@@ -939,6 +989,9 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)RTE_LOG (ERR ,PMD ,"Could not find %s ifindex: " "remote interface will remain unconfigured\n" , remote_iface); + else +/* Set the local mac address to the remote mac */ + tap_netdev_get_mac(remote_iface, &pmd->eth_addr); }return 0 ;
Signature · 1 line
2.8.0.rc0
PATCH 4/4 net/tap: set MTU on the remote
In reply to Pascal Mazon--- drivers/net/tap/rte_eth_tap.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/net/tap/rte_eth_tap.c +23 -6
@@ -823,9 +823,8 @@ tap_set_mc_addr_list(struct rte_eth_dev *dev __rte_unused, }static int -tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +tap_netdev_mtu_set (const char *iface,uint16_t mtu) { -struct pmd_internals *pmd = dev->data->dev_private;struct ifreq ifr;int err, s;
@@ -833,15 +832,15 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)if (s <0 ) {RTE_LOG (ERR ,PMD ,"Unable to get a socket for %s to set flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -strncpy (ifr.ifr_name, pmd->name,IFNAMSIZ ); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); err =ioctl (s,SIOCGIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device MTU: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -849,11 +848,29 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) err =ioctl (s,SIOCSIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to set %s mtu %d: %s\n" , - pmd->name, mtu,strerror (errno)); + iface, mtu,strerror (errno));close (s);return -1 ; }close (s); +return 0 ; +} + +static int +tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +{ +struct pmd_internals *pmd = dev->data->dev_private; +int err; + +/* First try to set mtu on the remote */ +if (pmd->remote_if_index) { + err =tap_netdev_mtu_set (pmd->remote_iface, mtu); +if (err <0 ) +return err; + } + err =tap_netdev_mtu_set (pmd->name, mtu); +if (err <0 ) +return err; dev->data->mtu = mtu;return 0 ; }
Signature · 1 line
2.8.0.rc0
Quoted 22 lines · Pascal Mazon
This patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
Pascal Mazon (4):
net/tap: add remote netdevice traffic capture
net/tap: reflect tap flags on the remote
net/tap: use the remote MAC address if available
net/tap: set MTU on the remote
Quoted 6 lines
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 212 ++++++++++++++++++--- drivers/net/tap/tap.h | 4 + drivers/net/tap/tap_flow.c | 414 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 631 insertions(+), 40 deletions(-)
Ah here is the tap.rst change, thanks.
Quoted 4 lines
Signature · 2 lines
-- 2.8.0.rc0
Regards,
Keith
v2 cover remote netdevice traffic capture
In reply to Pascal MazonThis patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
v2 changes:
- rebase on top of updated "net/tap: support flow API"
- fix implicit flow flush when closing the netdevices
Pascal Mazon (4):
net/tap: add remote netdevice traffic capture net/tap: reflect tap flags on the remote net/tap: use the remote MAC address if available net/tap: set MTU on the remote
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 213 ++++++++++++++++++--- drivers/net/tap/tap.h | 4 + drivers/net/tap/tap_flow.c | 418 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 635 insertions(+), 41 deletions(-)
Signature · 1 line
2.8.0.rc0
PATCH v2 1/4 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 79 +++++++- drivers/net/tap/tap.h | 2 + drivers/net/tap/tap_flow.c | 418 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 526 insertions(+), 14 deletions(-)
doc/guides/nics/tap.rst +17 -0
@@ -58,6 +58,23 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, then all packets with the tap PMD's local MAC coming +in on the remote netdevice will be redirected to the tap. +If the tap is in promiscuous mode, then all packets will be redirected. +In allmulti mode, all multicast packets will be redirected. +It is possible to add explicit rte_flow rules on the tap PMD to capture specific +traffic. For instance, in testpmd, the following rte_flow rule would capture +packets with the given MAC address from the remote, and send it to the tap RX +QUEUE 3:: + + testpmd> flow create 0 ingress pattern eth src is 02:03:04:05:06:07 / \ + end actions queue index 3 / end + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +77 -2
172 lines not on this page · raw message
drivers/net/tap/tap.h +2 -0
@@ -71,6 +71,8 @@ struct pmd_internals {int flower_support;/* 1 if kernel supports, else 0 */ int flower_vlan_support;/* 1 if kernel supports, else 0 */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +406 -12
527 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct rte_eth_dev *dev, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct rte_eth_dev *dev, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.8.0.rc0
PATCH v2 2/4 net/tap: reflect tap flags on the remote
In reply to Pascal MazonSynchronize PROMISC and ALLMULTI flags to the remote netdevice if possible.
Leave the IFF_UP flag as it is, however.
--- drivers/net/tap/rte_eth_tap.c | 36 +++++++++++++++++++++++------------- drivers/net/tap/tap.h | 2 ++ 2 files changed, 25 insertions(+), 13 deletions(-)
drivers/net/tap/rte_eth_tap.c +23 -13
@@ -254,7 +254,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) }static int -tap_link_set_flags (struct pmd_internals *pmd,short flags,int add) +tap_netdev_set_flags (const char *iface,short flags,int add) {struct ifreq ifr;int err, s;
@@ -271,11 +271,11 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , pmd->name); +snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , iface); err =ioctl (s,SIOCGIFFLAGS , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -293,6 +293,7 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)close (s);return 0 ; + } static int
@@ -301,7 +302,7 @@ tap_link_set_down(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_DOWN ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,0 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,0 ); } static int
@@ -310,7 +311,7 @@ tap_link_set_up(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_UP ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,1 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,1 ); } static int
@@ -482,9 +483,11 @@ tap_promisc_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =1 ; -tap_link_set_flags (pmd,IFF_PROMISC ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,1 ); + } } static void
@@ -493,9 +496,11 @@ tap_promisc_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =0 ; -tap_link_set_flags (pmd,IFF_PROMISC ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,0 ); + } } static void
@@ -504,9 +509,11 @@ tap_allmulti_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =1 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,1 ); + } } static void
@@ -515,9 +522,11 @@ tap_allmulti_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =0 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,0 ); + } } static void
@@ -962,6 +971,7 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)*/ pmd->nlsk_fd =nl_init ();if (strlen (remote_iface)) { +strncpy (pmd->remote_iface, remote_iface,RTE_ETH_NAME_MAX_LEN ); pmd->remote_if_index =if_nametoindex (remote_iface);if (!pmd->remote_if_index) RTE_LOG(ERR, PMD, "Could not find %s ifindex: "
drivers/net/tap/tap.h +2 -0
@@ -63,9 +63,11 @@ struct tx_queue { };struct pmd_internals { +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ +int remote_if_index;/* remote netdevice IF_INDEX */ int if_index;/* IF_INDEX for the port */ int nlsk_fd;/* Netlink socket fd */ int flower_support;/* 1 if kernel supports, else 0 */
Signature · 1 line
2.8.0.rc0
PATCH v2 3/4 net/tap: use the remote MAC address if available
In reply to Pascal MazonThe remote on a tap is most likely used with netdevices that are not under DPDK control. Outgoing traffic is supposed to use the source MAC address of the remote netdevice.
This commit synchronizes the MAC address of the local tap netdevice with the remote one.
Of course, it is still possible to change the tap MAC address, using standard DPDK APIs. It sets that MAC address on the tap PMD and redirect any packets matching that destination MAC to the tap PMD. It also tries setting the MAC address directly on the remote, if supported, through ioctl() calls.
--- drivers/net/tap/rte_eth_tap.c | 77 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-)
drivers/net/tap/rte_eth_tap.c +65 -12
@@ -529,6 +529,65 @@ tap_allmulti_disable(struct rte_eth_dev *dev) } } +static int +tap_netdev_set_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , + iface,strerror (errno)); +close (s); +return -1 ; + } +rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); + err =ioctl (s,SIOCSIFHWADDR , &ifr) ==-1 ; +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +return 0 ; +} + +static int +tap_netdev_get_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +rte_memcpy (mac_addr, ifr.ifr_hwaddr.sa_data,ETHER_ADDR_LEN ); +return 0 ; +} +static void tap_mac_remove(struct rte_eth_dev *dev __rte_unused, uint32_t index __rte_unused)
@@ -545,7 +604,6 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, {struct pmd_internals *internals = dev->data->dev_private;int fd = internals->rxq[0 ].fd; -struct ifreq ifr;if (index >RTE_PMD_TAP_MAX_MAC_ADDRS -1 ) { RTE_LOG(ERR, PMD,
@@ -565,19 +623,11 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, dev->data->name);return ; } -memset (&ifr,0 ,sizeof (struct ifreq )); -if (ioctl (fd,SIOCGIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , - dev->data->name,strerror (errno)); +if (tap_netdev_set_mac (internals->name, mac_addr) <0 )return ; - } -rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); -if (ioctl (fd,SIOCSIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , - dev->data->name,strerror (errno)); -return ; - }rte_memcpy (&dev->data->mac_addrs[index], mac_addr,ETHER_ADDR_LEN ); +if (internals->remote_if_index) +tap_netdev_set_mac (internals->remote_iface, mac_addr); } static void
@@ -977,6 +1027,9 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)RTE_LOG (ERR ,PMD ,"Could not find %s ifindex: " "remote interface will remain unconfigured\n" , remote_iface); + else +/* Set the local mac address to the remote mac */ + tap_netdev_get_mac(remote_iface, &pmd->eth_addr); }return 0 ;
Signature · 1 line
2.8.0.rc0
PATCH v2 4/4 net/tap: set MTU on the remote
In reply to Pascal Mazon--- drivers/net/tap/rte_eth_tap.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/net/tap/rte_eth_tap.c +23 -6
@@ -839,9 +839,8 @@ tap_set_mc_addr_list(struct rte_eth_dev *dev __rte_unused, }static int -tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +tap_netdev_mtu_set (const char *iface,uint16_t mtu) { -struct pmd_internals *pmd = dev->data->dev_private;struct ifreq ifr;int err, s;
@@ -849,15 +848,15 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)if (s <0 ) {RTE_LOG (ERR ,PMD ,"Unable to get a socket for %s to set flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , pmd->name); +snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , iface); err =ioctl (s,SIOCGIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device MTU: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -865,11 +864,29 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) err =ioctl (s,SIOCSIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to set %s mtu %d: %s\n" , - pmd->name, mtu,strerror (errno)); + iface, mtu,strerror (errno));close (s);return -1 ; }close (s); +return 0 ; +} + +static int +tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +{ +struct pmd_internals *pmd = dev->data->dev_private; +int err; + +/* First try to set mtu on the remote */ +if (pmd->remote_if_index) { + err =tap_netdev_mtu_set (pmd->remote_iface, mtu); +if (err <0 ) +return err; + } + err =tap_netdev_mtu_set (pmd->name, mtu); +if (err <0 ) +return err; dev->data->mtu = mtu;return 0 ; }
Signature · 1 line
2.8.0.rc0
v3 cover net/tap: remote netdevice traffic capture
In reply to Pascal MazonThis patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
v2 changes:
- rebase on top of updated "net/tap: support flow API"
- fix implicit flow flush when closing the netdevices
v3 changes:
- memset(0) for remote_iface in rte_pmd_tap_probe()
- use snprintf instead of strncpy to correctly handle terminating \0
Pascal Mazon (4):
net/tap: add remote netdevice traffic capture net/tap: reflect tap flags on the remote net/tap: use the remote MAC address if available net/tap: set MTU on the remote
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 215 +++++++++++++++++++--- drivers/net/tap/tap.h | 4 + drivers/net/tap/tap_flow.c | 418 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 637 insertions(+), 41 deletions(-)
Signature · 1 line
2.8.0.rc0
PATCH v3 1/4 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 80 +++++++- drivers/net/tap/tap.h | 2 + drivers/net/tap/tap_flow.c | 418 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 527 insertions(+), 14 deletions(-)
doc/guides/nics/tap.rst +17 -0
@@ -58,6 +58,23 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, then all packets with the tap PMD's local MAC coming +in on the remote netdevice will be redirected to the tap. +If the tap is in promiscuous mode, then all packets will be redirected. +In allmulti mode, all multicast packets will be redirected. +It is possible to add explicit rte_flow rules on the tap PMD to capture specific +traffic. For instance, in testpmd, the following rte_flow rule would capture +packets with the given MAC address from the remote, and send it to the tap RX +QUEUE 3:: + + testpmd> flow create 0 ingress pattern eth src is 02:03:04:05:06:07 / \ + end actions queue index 3 / end + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +78 -2
177 lines not on this page · raw message
drivers/net/tap/tap.h +2 -0
@@ -71,6 +71,8 @@ struct pmd_internals {int flower_support;/* 1 if kernel supports, else 0 */ int flower_vlan_support;/* 1 if kernel supports, else 0 */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +406 -12
527 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct rte_eth_dev *dev, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct rte_eth_dev *dev, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.8.0.rc0
PATCH v3 2/4 net/tap: reflect tap flags on the remote
In reply to Pascal MazonSynchronize PROMISC and ALLMULTI flags to the remote netdevice if possible.
Leave the IFF_UP flag as it is, however.
--- drivers/net/tap/rte_eth_tap.c | 37 ++++++++++++++++++++++++------------- drivers/net/tap/tap.h | 2 ++ 2 files changed, 26 insertions(+), 13 deletions(-)
drivers/net/tap/rte_eth_tap.c +24 -13
@@ -254,7 +254,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) }static int -tap_link_set_flags (struct pmd_internals *pmd,short flags,int add) +tap_netdev_set_flags (const char *iface,short flags,int add) {struct ifreq ifr;int err, s;
@@ -271,11 +271,11 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , pmd->name); +snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , iface); err =ioctl (s,SIOCGIFFLAGS , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -293,6 +293,7 @@ tap_link_set_flags(struct pmd_internals *pmd, short flags, int add)close (s);return 0 ; + } static int
@@ -301,7 +302,7 @@ tap_link_set_down(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_DOWN ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,0 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,0 ); } static int
@@ -310,7 +311,7 @@ tap_link_set_up(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->dev_link.link_status =ETH_LINK_UP ; -return tap_link_set_flags (pmd,IFF_UP |IFF_NOARP ,1 ); +return tap_netdev_set_flags (pmd->name,IFF_UP |IFF_NOARP ,1 ); } static int
@@ -482,9 +483,11 @@ tap_promisc_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =1 ; -tap_link_set_flags (pmd,IFF_PROMISC ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,1 ); + } } static void
@@ -493,9 +496,11 @@ tap_promisc_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->promiscuous =0 ; -tap_link_set_flags (pmd,IFF_PROMISC ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_PROMISC ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_PROMISC ); +tap_netdev_set_flags (pmd->remote_iface,IFF_PROMISC ,0 ); + } } static void
@@ -504,9 +509,11 @@ tap_allmulti_enable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =1 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,1 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,1 ); +if (pmd->remote_if_index) {tap_flow_implicit_create (pmd,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,1 ); + } } static void
@@ -515,9 +522,11 @@ tap_allmulti_disable(struct rte_eth_dev *dev)struct pmd_internals *pmd = dev->data->dev_private; dev->data->all_multicast =0 ; -tap_link_set_flags (pmd,IFF_ALLMULTI ,0 ); -if (pmd->remote_if_index) +tap_netdev_set_flags (pmd->name,IFF_ALLMULTI ,0 ); +if (pmd->remote_if_index) {tap_flow_implicit_destroy (dev,TAP_REMOTE_ALLMULTI ); +tap_netdev_set_flags (pmd->remote_iface,IFF_ALLMULTI ,0 ); + } } static void
@@ -962,6 +971,8 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)*/ pmd->nlsk_fd =nl_init ();if (strlen (remote_iface)) { +snprintf (pmd->remote_iface,RTE_ETH_NAME_MAX_LEN , +"%s" , remote_iface); pmd->remote_if_index =if_nametoindex (remote_iface);if (!pmd->remote_if_index) RTE_LOG(ERR, PMD, "Could not find %s ifindex: "
drivers/net/tap/tap.h +2 -0
@@ -63,9 +63,11 @@ struct tx_queue { };struct pmd_internals { +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ +int remote_if_index;/* remote netdevice IF_INDEX */ int if_index;/* IF_INDEX for the port */ int nlsk_fd;/* Netlink socket fd */ int flower_support;/* 1 if kernel supports, else 0 */
Signature · 1 line
2.8.0.rc0
PATCH v3 3/4 net/tap: use the remote MAC address if available
In reply to Pascal MazonThe remote on a tap is most likely used with netdevices that are not under DPDK control. Outgoing traffic is supposed to use the source MAC address of the remote netdevice.
This commit synchronizes the MAC address of the local tap netdevice with the remote one.
Of course, it is still possible to change the tap MAC address, using standard DPDK APIs. It sets that MAC address on the tap PMD and redirect any packets matching that destination MAC to the tap PMD. It also tries setting the MAC address directly on the remote, if supported, through ioctl() calls.
--- drivers/net/tap/rte_eth_tap.c | 77 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-)
drivers/net/tap/rte_eth_tap.c +65 -12
@@ -529,6 +529,65 @@ tap_allmulti_disable(struct rte_eth_dev *dev) } } +static int +tap_netdev_set_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , + iface,strerror (errno)); +close (s); +return -1 ; + } +rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); + err =ioctl (s,SIOCSIFHWADDR , &ifr) ==-1 ; +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +return 0 ; +} + +static int +tap_netdev_get_mac (const char *iface,struct ether_addr *mac_addr) +{ +struct ifreq ifr; +int err, s; + + s =socket (AF_INET ,SOCK_DGRAM ,0 ); +if (s <0 ) { +RTE_LOG (ERR ,PMD , +"Unable to get a socket to get MAC: %s\n" , +strerror (errno)); +return -1 ; + } +memset (&ifr,0 ,sizeof (ifr)); +strncpy (ifr.ifr_name, iface,IFNAMSIZ ); + err =ioctl (s,SIOCGIFHWADDR , &ifr); +close (s); +if (err <0 ) { +RTE_LOG (ERR ,PMD ,"%s: couldn't get MAC address (%s)\n" , + iface,strerror (errno)); +return -1 ; + } +rte_memcpy (mac_addr, ifr.ifr_hwaddr.sa_data,ETHER_ADDR_LEN ); +return 0 ; +} +static void tap_mac_remove(struct rte_eth_dev *dev __rte_unused, uint32_t index __rte_unused)
@@ -545,7 +604,6 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, {struct pmd_internals *internals = dev->data->dev_private;int fd = internals->rxq[0 ].fd; -struct ifreq ifr;if (index >RTE_PMD_TAP_MAX_MAC_ADDRS -1 ) { RTE_LOG(ERR, PMD,
@@ -565,19 +623,11 @@ tap_mac_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, dev->data->name);return ; } -memset (&ifr,0 ,sizeof (struct ifreq )); -if (ioctl (fd,SIOCGIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't get current MAC address (%s)\n" , - dev->data->name,strerror (errno)); +if (tap_netdev_set_mac (internals->name, mac_addr) <0 )return ; - } -rte_memcpy (ifr.ifr_hwaddr.sa_data, mac_addr,ETHER_ADDR_LEN ); -if (ioctl (fd,SIOCSIFHWADDR , &ifr) ==-1 ) { -RTE_LOG (ERR ,PMD ,"%s: couldn't set current MAC address (%s)\n" , - dev->data->name,strerror (errno)); -return ; - }rte_memcpy (&dev->data->mac_addrs[index], mac_addr,ETHER_ADDR_LEN ); +if (internals->remote_if_index) +tap_netdev_set_mac (internals->remote_iface, mac_addr); } static void
@@ -978,6 +1028,9 @@ eth_dev_tap_create(const char *name, char *tap_name, char *remote_iface)RTE_LOG (ERR ,PMD ,"Could not find %s ifindex: " "remote interface will remain unconfigured\n" , remote_iface); + else +/* Set the local mac address to the remote mac */ + tap_netdev_get_mac(remote_iface, &pmd->eth_addr); }return 0 ;
Signature · 1 line
2.8.0.rc0
PATCH v3 4/4 net/tap: set MTU on the remote
In reply to Pascal Mazon--- drivers/net/tap/rte_eth_tap.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/net/tap/rte_eth_tap.c +23 -6
@@ -839,9 +839,8 @@ tap_set_mc_addr_list(struct rte_eth_dev *dev __rte_unused, }static int -tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +tap_netdev_mtu_set (const char *iface,uint16_t mtu) { -struct pmd_internals *pmd = dev->data->dev_private;struct ifreq ifr;int err, s;
@@ -849,15 +848,15 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)if (s <0 ) {RTE_LOG (ERR ,PMD ,"Unable to get a socket for %s to set flags: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));return -1 ; }memset (&ifr,0 ,sizeof (ifr)); -snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , pmd->name); +snprintf (ifr.ifr_name,IFNAMSIZ ,"%s" , iface); err =ioctl (s,SIOCGIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to get %s device MTU: %s\n" , - pmd->name,strerror (errno)); + iface,strerror (errno));close (s);return -1 ; }
@@ -865,11 +864,29 @@ tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) err =ioctl (s,SIOCSIFMTU , &ifr);if (err <0 ) {RTE_LOG (WARNING ,PMD ,"Unable to set %s mtu %d: %s\n" , - pmd->name, mtu,strerror (errno)); + iface, mtu,strerror (errno));close (s);return -1 ; }close (s); +return 0 ; +} + +static int +tap_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +{ +struct pmd_internals *pmd = dev->data->dev_private; +int err; + +/* First try to set mtu on the remote */ +if (pmd->remote_if_index) { + err =tap_netdev_mtu_set (pmd->remote_iface, mtu); +if (err <0 ) +return err; + } + err =tap_netdev_mtu_set (pmd->name, mtu); +if (err <0 ) +return err; dev->data->mtu = mtu;return 0 ; }
Signature · 1 line
2.8.0.rc0
PATCH v4 1/1 net/tap: remote netdevice traffic capture
In reply to Pascal MazonThis patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
v2 changes:
- rebase on top of updated "net/tap: support flow API"
- fix implicit flow flush when closing the netdevices
v3 changes:
- memset(0) for remote_iface in rte_pmd_tap_probe()
- use snprintf instead of strncpy to correctly handle terminating \0
v4 changes:
- rebase on top of updated "net/tap: support flow API"
- use only a single patch now as MTU, MAC and flags can be easily managed with tap_ioctl()
Pascal Mazon (1):
net/tap: add remote netdevice traffic capture
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 575 insertions(+), 22 deletions(-)
Signature · 1 line
2.8.0.rc0
PATCH v4 1/1 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 575 insertions(+), 22 deletions(-)
doc/guides/nics/tap.rst +17 -0
@@ -58,6 +58,23 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, then all packets with the tap PMD's local MAC coming +in on the remote netdevice will be redirected to the tap. +If the tap is in promiscuous mode, then all packets will be redirected. +In allmulti mode, all multicast packets will be redirected. +It is possible to add explicit rte_flow rules on the tap PMD to capture specific +traffic. For instance, in testpmd, the following rte_flow rule would capture +packets with the given MAC address from the remote, and send it to the tap RX +QUEUE 3:: + + testpmd> flow create 0 ingress pattern eth src is 02:03:04:05:06:07 / \ + end actions queue index 3 / end + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +98 -3
218 lines not on this page · raw message
drivers/net/tap/rte_eth_tap.h +4 -0
@@ -63,15 +63,19 @@ struct tx_queue { };struct pmd_internals { +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ +int remote_if_index;/* remote netdevice IF_INDEX */ int if_index;/* IF_INDEX for the port */ int ioctl_sock;/* socket for ioctl calls */ int nlsk_fd;/* Netlink socket fd */ int flower_support;/* 1 if kernel supports, else 0 */ int flower_vlan_support;/* 1 if kernel supports, else 0 */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +432 -19
569 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <rte_eth_tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct pmd_internals *pmd, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.8.0.rc0
Re: [PATCH v4] net/tap: add remote netdevice traffic capture
Quoted 11 lines · Pascal Mazon
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Quoted 6 lines
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
Signed-off-by Pascal Mazon <[email protected]>Acked-by Olga Shern <[email protected]>
Quoted 7 lines
---
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 575 insertions(+), 22 deletions(-)
Regards,
Keith
PATCH v5 1/1 net/tap: remote netdevice traffic capture
In reply to Pascal MazonThis patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
v2 changes:
- rebase on top of updated "net/tap: support flow API"
- fix implicit flow flush when closing the netdevices
v3 changes:
- memset(0) for remote_iface in rte_pmd_tap_probe()
- use snprintf instead of strncpy to correctly handle terminating \0
v4 changes:
- rebase on top of updated "net/tap: support flow API"
- use only a single patch now as MTU, MAC and flags can be easily managed with tap_ioctl()
v5 changes:
- rebase after adrien's patches on Tx poll and Rx signaling
Pascal Mazon (1):
net/tap: add remote netdevice traffic capture
doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 575 insertions(+), 22 deletions(-)
Signature · 1 line
2.8.0.rc0
PATCH v5 1/1 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 17 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 575 insertions(+), 22 deletions(-)
doc/guides/nics/tap.rst +17 -0
@@ -58,6 +58,23 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, then all packets with the tap PMD's local MAC coming +in on the remote netdevice will be redirected to the tap. +If the tap is in promiscuous mode, then all packets will be redirected. +In allmulti mode, all multicast packets will be redirected. +It is possible to add explicit rte_flow rules on the tap PMD to capture specific +traffic. For instance, in testpmd, the following rte_flow rule would capture +packets with the given MAC address from the remote, and send it to the tap RX +QUEUE 3:: + + testpmd> flow create 0 ingress pattern eth src is 02:03:04:05:06:07 / \ + end actions queue index 3 / end + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +98 -3
218 lines not on this page · raw message
drivers/net/tap/rte_eth_tap.h +4 -0
@@ -64,15 +64,19 @@ struct tx_queue { };struct pmd_internals { +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ +int remote_if_index;/* remote netdevice IF_INDEX */ int if_index;/* IF_INDEX for the port */ int ioctl_sock;/* socket for ioctl calls */ int nlsk_fd;/* Netlink socket fd */ int flower_support;/* 1 if kernel supports, else 0 */ int flower_vlan_support;/* 1 if kernel supports, else 0 */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +432 -19
569 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <rte_eth_tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct pmd_internals *pmd, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.8.0.rc0
v6 cover net/tap: remote netdevice traffic capture
In reply to Pascal MazonThis patchset adds the special "remote" feature to the tap PMD, that actually enables capturing traffic from another netdevice. This is especially useful to get packets into the DPDK app, when the remote netdevice has no DPDK support.
The "remote" feature requires flow API support as flow rules will be configured on the remote netdevice for redirection, using the same mechanism.
This series applies on top of:
[PATCH 0/4] net/tap: support flow API
v6 changes:
- update documentation with use case
v5 changes:
- rebase after adrien's patches on Tx poll and Rx signaling
v4 changes:
- rebase on top of updated "net/tap: support flow API"
- use only a single patch now as MTU, MAC and flags can be easily managed with tap_ioctl()
v3 changes:
- memset(0) for remote_iface in rte_pmd_tap_probe()
- use snprintf instead of strncpy to correctly handle terminating \0
v2 changes:
- rebase on top of updated "net/tap: support flow API"
- fix implicit flow flush when closing the netdevices
Pascal Mazon (1):
net/tap: add remote netdevice traffic capture
doc/guides/nics/tap.rst | 16 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 574 insertions(+), 22 deletions(-)
Signature · 1 line
2.12.0.306.g4a9b9b3
PATCH v6 1/1 net/tap: add remote netdevice traffic capture
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
--- doc/guides/nics/tap.rst | 16 ++ drivers/net/tap/rte_eth_tap.c | 101 +++++++++- drivers/net/tap/rte_eth_tap.h | 4 + drivers/net/tap/tap_flow.c | 451 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/tap/tap_flow.h | 24 +++ 5 files changed, 574 insertions(+), 22 deletions(-)
doc/guides/nics/tap.rst +16 -0
@@ -58,6 +58,22 @@ needed, but the interface does not enforce that speed, for example:: --vdev=net_tap0,iface=foo0,speed=25000 +It is possible to specify a remote netdevice to capture packets from by adding +``remote=foo1``, for example:: + + --vdev=net_tap,iface=tap0,remote=foo1 + +If a ``remote`` is set, the tap MAC address will be set to match the remote one +just after netdevice creation. Using TC rules, traffic from the remote netdevice +will be redirected to the tap. If the tap is in promiscuous mode, then all +packets will be redirected. In allmulti mode, all multicast packets will be +redirected. + +Using the remote feature is especially useful for capturing traffic from a +netdevice that has no support in the DPDK. It is possible to add explicit +rte_flow rules on the tap PMD to capture specific traffic (see next section for +examples). + After the DPDK application is started you can send and receive packets on the interface using the standard rx_burst/tx_burst APIs in DPDK. From the host point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
drivers/net/tap/rte_eth_tap.c +98 -3
218 lines not on this page · raw message
drivers/net/tap/rte_eth_tap.h +4 -0
@@ -64,15 +64,19 @@ struct tx_queue { };struct pmd_internals { +char remote_iface[RTE_ETH_NAME_MAX_LEN ];/* Remote netdevice name */ char name[RTE_ETH_NAME_MAX_LEN ];/* Internal Tap device name */ uint16_t nb_queues;/* Number of queues supported */ struct ether_addr eth_addr;/* Mac address of the device port */ +int remote_if_index;/* remote netdevice IF_INDEX */ int if_index;/* IF_INDEX for the port */ int ioctl_sock;/* socket for ioctl calls */ int nlsk_fd;/* Netlink socket fd */ int flower_support;/* 1 if kernel supports, else 0 */ int flower_vlan_support;/* 1 if kernel supports, else 0 */ LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ +/* implicit rte_flow rules set when a remote device is active */ + LIST_HEAD(tap_implicit_flows, rte_flow) implicit_flows;struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES ];/* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES ];/* List of TX queues */ };
drivers/net/tap/tap_flow.c +432 -19
569 lines not on this page · raw message
drivers/net/tap/tap_flow.h +24 -0
@@ -36,6 +36,7 @@#include <rte_flow.h> #include <rte_flow_driver.h> +#include <rte_eth_tap.h> /** * In TC, priority 0 means we require the kernel to allocate one for us.
@@ -49,10 +50,33 @@#define GROUP_SHIFT 12#define MAX_GROUP GROUP_MASK +/** +* These index are actually in reversed order: their priority is processed +* by subtracting their value to the lowest priority (PRIORITY_MASK). +* Thus the first one will have the lowest priority in the end +* (but biggest value). +*/ +enum implicit_rule_index { +TAP_REMOTE_TX , +TAP_REMOTE_BROADCASTV6 , +TAP_REMOTE_BROADCAST , +TAP_REMOTE_ALLMULTI , +TAP_REMOTE_PROMISC , +TAP_REMOTE_LOCAL_MAC , +TAP_REMOTE_MAX_IDX , +}; +int tap_dev_filter_ctrl (struct rte_eth_dev *dev,enum rte_filter_type filter_type,enum rte_filter_op filter_op,void *arg);int tap_flow_flush (struct rte_eth_dev *dev,struct rte_flow_error *error); +int tap_flow_implicit_create (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_destroy (struct pmd_internals *pmd, +enum implicit_rule_index idx); +int tap_flow_implicit_flush (struct pmd_internals *pmd, +struct rte_flow_error *error); +#endif /* _TAP_FLOW_H_ */
Signature · 1 line
2.12.0.306.g4a9b9b3
Ferruh Yigit
AppliedRe: [PATCH v6 1/1] net/tap: add remote netdevice traffic capture
Quoted 8 lines · Pascal Mazon
By default, a tap netdevice is of no use when not fed by a separate process. The ability to automatically feed it from another netdevice allows applications to capture any kind of traffic normally destined to the kernel stack.
This patch implements this ability through a new optional "remote" parameter.
Quoted 7 lines
Packets matching filtering rules created with the flow API are matched on the remote device and redirected to the tap PMD, where the relevant action will be performed.
Signed-off-by Pascal Mazon <[email protected]>Acked-by Olga Shern <[email protected]>Acked-by Keith Wiles <[email protected]>
Applied to dpdk-next-net/master, thanks.