xdptap - Fault Injection: Dropping Packets
May 25, 2025
Motivation #
Nobody working at network and data center operations usually likes packet loss, even just a small percentage can have serious effects on overall quality, bandwidth and end user experience.
However, there are cases where it’s necessary to establish networking faults by purpose, to name a few:
- Testing protocol robustness
- Testing complete application and data center connectivity robustness
- Evaluating the possible impact of a faulty connection
- Tearing down bandwidth selectively for specific Layer 2 connections
- Testing network monitoring and automatic countermeasures
The unique xdptap feature of fault injection allows to establish several faults by purpose and at wire speed up to 100GbE. This article covers probably the most well known one: Packet loss.
Useful Preliminary Information #
These links may be useful to have a look at before:
- xdptap - Basic Usage
- xdptap - Collecting Packets
- IXDP Packet Flow explained
- RPCL - Reverse Polish Configuration (and Control) Language
Dropping Packets: IXDP and RPCL control #
The fault injection in general is located at step 6 in the IXDP packet processing flowchart. See also IXDP Packet Flow explained for more information about the other steps.
The decision where the packet has to be sent out has already been made in step 4 (for xdptap by the IXDP callback function representing a bridge).
flowchart TD a("1. packet from interface received") --> b("2. update MAC and Ethertype statistics") --> c("3. insert packet into TAP queue (if qualified)") --> d("4. user callback") d --> |drop by callback or unknown interface| d1("10. discard packet") --> d2[/"done"/] d --> |valid output interface| d3("5. check drop machash") d3 --> |drop by drop machash| d1("10. discard packet") d3 --> d4("6. fault injection (if qualified)") d4 --> |drop by fault injection| d1("10. discard packet") d4 --> d5("7. schedule packet for TX (with TAP queue insert, if qualified)") --> d2(["done (continue busy-polling from top)"])
For all settings that need to be active on xdptap startup it’s convenient to
include them in /etc/xdptap.rpcl
.
Show Summary Statistics and Counters #
if.stats #
show summary statistics of all interfaces ( - )
if.stats
generally displays interface statistics of all configured interfaces.
In the example below, it shows a freshly started xdptap in bridging mode, where
each interface of two is driven by the ixgbe
10GbE driver which implements XDP
zero-copy. queues:1
indicates that packet processing is handled by one single
thread and one combined queue, which is sufficient for 10GbE even on this small
testing machine.
The counters and settings related to packet dropping are highlighted in blue.
Example:
ok if.stats
0 enp1s0f0 ixgbe queues:1 ZEROCOPY
rx 0
tx 1
drop 0
noif 0
err 0
RX tap disabled
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 2
tx 0
drop 1
noif 0
err 0
RX tap disabled
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 ▂
Enabling and Disabling Fault Injection #
For xdptap, enabling fault injection determines the direction of packet flow where fault injection applies: When fault injection is enabled for both interfaces in bridging mode, the fault injection is active for both directions (with the propabilities as set).
fault.enable #
enable fault injection for interface ( interface - )
Example:
ok 0 fault.enable
ok ▂
fault.disable #
disable fault injection for interface ( interface - )
Example:
ok 0 fault.disable
ok ▂
Setting the Packet Drop Probability #
fault.drop.probability #
set FI drop probability in 1/100000 units ( probability interface - )
The fault.drop.probability
is interface specific and can be set in 1/100000 units.
The default value is 0 (0.000%).
Example:
ok 1000 0 fault.drop.probability # setting 1% for interface 0
ok if.stats
0 enp1s0f0 ixgbe queues:1 ZEROCOPY
rx 48
tx 2959
drop 0
noif 0
err 0
RX tap disabled
TX tap disabled
fault injection disabled
drop probability 1000 (1.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 5917
tx 48
drop 2958
noif 0
err 0
RX tap disabled
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 ▂
Restricting Fault Injection #
There are two atomic/lockless sets of MAC addresses that allow to tailor and restrict fault injection to specific MAC addresses and SRC/DST combinations:
fault.hash.dst
: contains 0 or more MAC destination addressesfault.hash.src
: contains 0 or more MAC source addresses
A packet qualifies for fault injection if the following pseudo code expression is true:
(the incoming interface is enabled for FI) &&
((fault.hash.src is empty) || (the packets SRC MAC address is a member of fault.hash.src)) &&
((fault.hash.dst is empty) || (the packets DST MAC address is a member of fault.hash.dst))
The following RPCL words control both sets (fault.hash.dst.show
and
fault.hash.src.show
additionally show vendor/OUI information when known):
fault.hash.dst.insert #
add specific MAC address to fault injection DST machash ( mac - )
fault.hash.dst.reset #
reset fault injection DST machash to 0 elements ( - )
fault.hash.dst.show #
show fault injection DST machash ( - )
fault.hash.src.insert #
add specific MAC address to fault injection SRC machash ( mac - )
fault.hash.src.reset #
reset fault injection SRC machash to 0 elements ( - )
fault.hash.src.show #
show fault injection SRC machash ( - )
Example:
ok fault.hash.dst.show
ok fault.hash.src.show
ok fault.hash.src.show
ok 11:11:11:11:11:11 fault.hash.dst.insert
ok 22:22:22:22:22:22 fault.hash.dst.insert
ok fault.hash.dst.show
11:11:11:11:11:11 Private
22:22:22:22:22:22 Locally Administered Address (LAA)
ok 33:33:33:33:33:33 fault.hash.src.insert
ok 44:44:44:44:44:44 fault.hash.src.insert
ok fault.hash.src.show
44:44:44:44:44:44
33:33:33:33:33:33
ok fault.hash.dst.reset
ok fault.hash.src.reset
ok fault.hash.dst.show
ok fault.hash.src.show
ok ▂