xdptap - Basic Usage
May 30, 2025
Updated to include latest additions and the--xdp_skb
and--xdp_drv
command line options.
xdptap #
xdptap is an XDP based Ethernet analysis and monitoring security tool which allows to obtain insight and to record selected (or all) traffic for further analysis and evaluation.
Linux XDP in zero-copy mode allows packet processing at wire-speed up to 100GbE full duplex with specific drivers.
The Layers #
The xdptap application consists - somewhat simplified - of three layers:
flowchart TD a("xdptap") --- b("IXDP") --- c("libxdp/eBPF/NIC drivers")
xdptap #
The top layer, xdptap consists basically of command line option parsing, some RPCL
initial processing (as loading /etc/xdptap.rpcl
with load-if-present
and inserting some
variables like version.xdptap
).
The functionality of xdptap itself is represented by the IXDP callback function IXDPCallback()
and is simple and short:
|
|
IXDP #
The IXDP layer is responsible for XDP ring management operating with a set of interfaces in promiscuous mode. IXDP registers its specific set of RPCL functions (words) which allow to control and configure the IXDP packet processing layer.
All RPCL control mechanisms that are available with xdptap are in fact part of the IXDP layer.
Further information:
- IXDP - A libxdp wrapper API for zero-copy high speed packet processing applications
- IXDP Packet Flow explained
- RPCL - Reverse Polish Configuration (and Control) Language
libxdp/eBPF/NIC drivers #
libxdp
is a lightweight library that allows attaching multiple XDP programs to network interfaces and using AF_XDP sockets. It relies on libbpf
to process eBPF object files and supports freplace and kernel features for the XDP dispatcher.
- libxdp/IXDP - comments and resources
- IXDP - tested drivers
- libxdp - library for attaching XDP programs and using AF_XDP sockets
- Express Data Path (Wikipedia)
- eBPF (Wikipedia)
The xdptap
Command
#
The general usage information of the xdptap command is this:
$ xdptap -h
usage: xdptap [options] interface0 [interface1]
options:
-q|--queues <q> specify number of queues (default 1)
-r|--ringsize <r> specify ringsize (default 4096)
-i|--initfile <file> load specific initial RPCL file
-d|--daemon detach and run in background
-h|--help show usage
-v|--version show version
-c|--copyright show copyright
--xdp_skb force XDP_SKB mode
--xdp_drv force XDP_SKB mode
$ ▂
xdptap Options #
-q|–queues #
This option controls the number of queues that the IXDP layer operates withi over all interfaces. This parameter is equivalent to the number of threads, since IXDP runs with one thread per queue. The default is 1, which is fully sufficient to process packets bridging between two 10GbE interfaces.
-r|–ringsize #
The ringsize defaults to 4096 and can be changed with this option to another value. The NIC ring parameters are set to this value for RX and TX, also this value influences the IXDP ring and FIFO buffer dimensioning. There’s currently no NIC driver known which requires a different value, but it might be important for 40GbE and 100GbE NICs.
-i|–initfile #
Per default xdptap loads /etc/xdptap.rpcl
with load-if-present
. A different RPCL init
file can be specified with this option if desired.
-d|–daemon #
With this option specified, xdptap detaches itself and runs in background, registering
with xdptap
as identifier for the control
utility. When this option is not specified,
the xdptap
command ends in its RPCL main loop (with no line editing capabilities).
–xdp_skb #
Forces IXDP to operate AF_XDP in XDP_SKB mode.
–xdp_drv #
Forces IXDP to operate AF_XDP in XDP_DRV mode.
xdptap Modes #
Bridging Mode #
When xdptap is invoked with two interfaces, it runs in bridging mode, acting as a promiscuous mode bridge between those two interfaces.
Example:
$ sudo xdptap enp1s0f0 enp1s0f1 --daemon
xdptap going to background ...
$ ▂
Mirroring Mode #
When xdptap is invoked with just one interface, it runs in mirroring mode (sometimes this is also called “SPAN” by other software and vendors). When the provided interface is connected to a switch port, that has been configured for port mirroring it allows to inspect the traffic visible this way. xdptap ’s fault injection is not able to inject faults in this mode.
Example:
$ sudo xdptap enp1s0f0 --daemon
xdptap going to background ...
$ ▂
Control #
$ control -h
usage: control <identifier> control background process
control <identifier> status show background process status
control <identifier> stop terminate background process
control -h|--help show usage
control -v|--version show version
control -c|--copyright show copyright
$ ▂
Control Tasks #
control background process #
Invoking control
with an identifier connects to a running background daemon
which has registered itself with that identifier name. As soon as connected,
stdin/stdout/stderr of the background process are connected to the control
frontend which offers some line editing capabilities.
Any output that has been sent to stdout and stderr by the background process on startup is shown first as it would have appeared on screen.
Since xdptap runs RPCL as its main thread, this connects to the RPCL main
loop indicated by the ok
prompt.
Ctrl-D and Ctrl-C exit the control
frontend, additionally there’s and inactivity
timeout of 10 minutes.
Example:
$ sudo xdptap enp1s0f0 enp1s0f1 --daemon
xdptap going to background ...
$ sudo control xdptap
connected to xdptap PID 6617
IXDPSetup() SUCCESS ifc:2 nqueues:1 ringsize:4096 XDP_DEFAULT
IXDPStart() SUCCESS
ok ▂
show background process status #
This shows the background status and PID (if there’s a background process running with the specified identifier).
Example:
$ sudo control xdptap status
xdptap PID 6617 running
$ sudo control unknown status
unknown not running
$ ▂
terminate background process #
This allows to shutdown a running background process with increasing “force” in terms of signals.
Example:
$ sudo control xdptap stop
shutdown of xdptap PID 6617 complete
$ sudo control unknown stop
unknown not running
$ ▂
xdptap and RPCL #
Show Uptime #
The RPCL built-in word uptime-hr
allows to display the uptime of the RPCL
interpreter in a “human readable” format. With xdptap running in background,
this looks like this (effectively displaying the uptime of the xdptap background process):
$ sudo control xdptap
ok uptime-hr .
1d 22h 24m 52s
ok ▂
Show RPCL Variables #
Example: xdptap in Bridging Mode #
$ sudo control xdptap
ok .d
ixdp.configured_interfaces 2
ixdp.configured_queues 1
ixdp.configured_ringsize 4096
ixdp.interface.0.driver ixgbe
ixdp.interface.0.name enp1s0f0
ixdp.interface.1.driver ixgbe
ixdp.interface.1.name enp1s0f1
ixdp.version 1.97
rpcl.platform Debian12-amd64
rpcl.version 1.138
xdptap.version 1.4
ok ▂
Example: xdptap in Mirroring Mode #
$ sudo control xtptap
ok .d
ixdp.configured_interfaces 1
ixdp.configured_queues 1
ixdp.configured_ringsize 4096
ixdp.interface.0.driver ixgbe
ixdp.interface.0.name enp1s0f0
ixdp.version 1.97
rpcl.platform Debian12-amd64
rpcl.version 1.138
xdptap.version 1.4
ok ▂
The Drop Machash #
IXDP supports lockless hashtables of MAC addresses, defining just a set of MAC addresses (a specific MAC address is either a member of such a set - or not). One instance of this is the “Drop Machash”. which defines a set of MAC addresses that cause a packet to be dropped when either the source MAC address or the destination MAC address of an Ethernet packet is a member of the Drop Machash.
This question (member of the Drop Machash or not) is asked when the IXDP callback function decides to forward the packet to another or the same interface it has been received from. With xdptap , this functionality makes therefore only sense in bridging mode, where xdptap acts as a bridge between two interfaces.
drop.hash.insert
#
add specific MAC address to drop ( mac - )
Example:
$ sudo control xdptap
ok a0:36:9f:21:4b:90 drop.hash.insert
ok f0:b2:b9:15:07:ca drop.hash.insert
ok drop.hash.show
a0:36:9f:21:4b:90 Intel Corporate
f0:b2:b9:15:07:ca Intel Corporate
ok ▂
To specify addresses always to be dropped, just include the desireddrop.hash.insert
commands in/etc/xdptap.rpcl
.
drop.hash.reset
#
reset drop machash to 0 elements ( - )
This clears the drop machash.
Example:
$ sudo control xdptap
ok drop.hash.show
a0:36:9f:21:4b:90 Intel Corporate
f0:b2:b9:15:07:ca Intel Corporate
ok drop.hash.reset
ok drop.hash.show
ok ▂
drop.hash.show
#
show user defined drop machash ( - )
Example:
$ sudo control xdptap
ok drop.hash.show
a0:36:9f:21:4b:90 Intel Corporate
f0:b2:b9:15:07:ca Intel Corporate
ok ▂
Interface Statistics and Counters #
if.drivers
#
show interfaces and drivers ( - )
Example:
ok if.drivers
0 enp1s0f0 ixgbe
1 enp1s0f1 ixgbe
ok ▂
Here xdptap is operating in bridging mode since it has been started with two interfaces.
if.etype.show
#
show rx Ethertype and VLAN statistics for interface ( i - )
Example:
ok if.drivers
0 enp2s0 igc
1 enp3s0 igc
ok 0 if.etype.show
0 0x0008 802.3 size e8:fd:f8:5d:fe:4a 1 Shanghai High-Flying Electronics Technology Co., Ltd
0 0x0800 IPv4 32:3a:fd:84:56:64 12866 Locally Administered Address (LAA)
0 0x0806 ARP 00:e2:69:89:51:e4 935
0 0x8100 802.1q 00:3e:e1:c0:f0:9c 24 Apple, Inc.
10 VID 00:3e:e1:c0:f0:9c 24 Apple, Inc.
0 0x86dd IPv6 00:3e:e1:c0:f0:9c 2881 Apple, Inc.
0 0x8899 RRCP 24:d7:9c:e4:3e:e9 700 Cisco Systems, Inc
0 0x88cc LLDP 56:e6:36:5f:17:a8 92 Locally Administered Address (LAA)
1 0x0800 IPv4 00:3e:e1:c0:f0:9c 12 Apple, Inc.
1 0x86dd IPv6 00:3e:e1:c0:f0:9c 12 Apple, Inc.
ok ▂
There are six columns in a
if.etype.show
output:
- The first column is the VLAN level, where IXDP descends up to 4 levels for
0x8100
and0x88a8
type of VLANs.- The second column is the Ethertype that has been seen (or the VLAN Id (VID) for
0x8100
and0x88a8
).- The third column is a textual desciption of the Ethertype.
- The fourth column is the Ethernet address that has most recently encountered sending a packet. This may be helpful to determine MAC addresses that are communicating in wrong or unexpected VLANs.
- The fifth column is the atomic counter counting the occurences of packets of that type.
- The sixth column is the manufacturer information of the MAC address in column four.
if.mac.show
#
show rx mac statistics for interface ( i - )
Example:
ok if.drivers
0 enp2s0 igc
1 enp3s0 igc
ok 0 if.mac.show
9a:88:c6:d1:3d:4a 97 Locally Administered Address (LAA)
3e:10:d5:14:22:7e 66 Locally Administered Address (LAA)
24:d7:9c:e4:3e:e9 21 Cisco Systems, Inc
00:11:32:d5:11:11 1 Synology Incorporated
52:54:00:9c:53:c1 1 Locally Administered Address (LAA)
00:3e:e1:c0:f0:9c 295 Apple, Inc.
56:e6:36:5f:17:a8 8 Locally Administered Address (LAA)
32:3a:fd:84:56:64 94 Locally Administered Address (LAA)
00:e2:69:89:51:e4 23
a0:52:72:1a:ca:41 1 Apple, Inc.
00:23:7d:86:71:ff 3 Hewlett Packard
ce:0e:14:15:67:bc 95 Locally Administered Address (LAA)
50:1e:2d:49:c2:24 206 StreamUnlimited Engineering GmbH
06:b6:2b:f1:08:fa 1 Locally Administered Address (LAA)
ee:0c:92:fe:f1:1c 1 Locally Administered Address (LAA)
32:3a:fd:86:36:3f 39 Locally Administered Address (LAA)
4e:3a:fd:86:36:41 1 Locally Administered Address (LAA)
38:10:d5:14:22:7c 1 AVM Audiovisuelles Marketing und Computersysteme GmbH
3c:2a:f4:07:f0:4b 1 Brother Industries, LTD.
00:11:32:d5:11:12 56 Synology Incorporated
ok ▂
This is from a freshly started xdptap in bridging mode, showing the MAC addresses and packet counts
on RX of interface 0. Since RPCL has the recent manufacturer database compiled in, the manufacturer
information is also shown. Locally administered addresses are additionally shown as such. If the manufacturer
is not known, the information field stays blank (as for 00:e2:69:89:51:e4
above).
if.qstats
#
show detailed queue/interface statistics ( queue interface - )
Example:
$ sudo control xdptap
$ 0 0 if.qstats
queue 0 interface 0 enp1s0f0 ixgbe fd 3
rx_packets_ctr 1
tx_packets_ctr 24
refill_packets_ctr 1
drop_packets_ctr 0
drop_fi_ctr 0
bitflip_injected_ctr 0
dup_injected_ctr 0
noif_packets_ctr 0
tap_packets_ctr 0
txbuffer_full_packets_ctr 0
txring_full_packets_ctr 0
completed_packets_ctr 24
xdp_options_zerocopy ACTIVE
rx_dropped 0
rx_invalid_descs 0
tx_invalid_descs 0
rx_ring_full 0
rx_fill_ring_empty_descs 2
tx_ring_empty_descs 6236833
$ ▂
The XDP statistic countersrx_fill_ring_empty_descs
andtx_ring_empty_descs
are shown as they are, but we regard both values as meaningless (they aren’t documented, but existent).
if.stats
#
show summary statistics of all interfaces ( - )
Example:
ok if.drivers
0 enp1s0f0 ixgbe
1 enp1s0f1 ixgbe
ok if.stats
0 enp1s0f0 ixgbe queues:1 ZEROCOPY
rx 1
tx 19
drop 0
noif 0
err 0
RX tap enabled
TX tap disabled
fault injection disabled
drop probability 0 (0.000%)
bitflip probability 0 (0.000%)
dup probability 0 (0.000%)
dropped by FI 0
bitflipped by FI 0
duplicated by FI 0
1 enp1s0f1 ixgbe queues:1 ZEROCOPY
rx 38
tx 1
drop 19
noif 0
err 0
RX tap enabled
TX tap disabled
fault injection disabled
drop probability 0 (0.000%)
bitflip probability 0 (0.000%)
dup probability 0 (0.000%)
dropped by FI 0
bitflipped by FI 0
duplicated by FI 0
ok ▂
/etc/xdptap.rpcl
#
/etc/xdptap.rpcl
is the default xdptap configuration file which is loaded at
startup if present (the location can be different as specified with -i|--initfile
).
One thing that is useful in many cases is to change the RPCL interpreter prompt, see the description here: Changing the Prompt.