A suite of network diagnostic tools developed by Baidu's physical network black-box monitoring team, including:
- bitflip: Detects packet loss and bit-flip errors in large-scale physical networks.
- bitflip6: IPv6 variant of bitflip for IPv6 network diagnostics.
- baize: Configuration-driven continuous network quality monitoring tool for long-term deployment.
- kuiniu: GPU NIC interconnect probing tool for AI training clusters — symmetric RoCEv2/UDP probing across GPU pairs, with role=both single-process dual-role deployment.
- lidar: TCP SYN probing tool for network reachability detection — no server-side deployment required.
- mping: Multi-target ICMP Echo ping tool with CIDR expansion, DNS resolution, hardware timestamping, and packet corruption detection.
- mping6: IPv6 variant of mping for ICMPv6 Echo probing with packet corruption detection.
- evr: VXLAN-based EVR device probing tool — embeds the real EVR src IP in the payload so reflected probes can be matched back without a 5-tuple key.
- traceroute: Hop-by-hop path probing tool with ICMP/UDP/TCP probes, concurrent multi-TTL and multi-target probing, and per-hop RTT/loss stats — no server-side deployment required. All packet encode/decode goes through goscapy.
Produced by Baidu System Department
curl -fsSL https://nettools.rpcx.io/install.sh | sh
Or install to a specific directory:
BINDIR=~/.local/bin curl -fsSL https://nettools.rpcx.io/install.sh | sh
Or build from source:
make build

A high-frequency UDP probing tool for network bit-flip (packet corruption) and packet loss detection. Supports unidirectional loss and corruption detection — both client-side (round-trip) and server-side (one-way from client to server).
How it works: The client sends a large volume of UDP packets per second to the server, which echoes them back unchanged. Both sides independently detect issues:
By comparing client-side and server-side loss, you can determine whether loss occurs on the forward path (client → server) or the return path (server → client).
Build:
make build
Run server (on the remote host):
# Simplest — auto-detects local IP
./bitflip
# With explicit IP
./bitflip -r server -s <server_ip> -c <client_ip>
Run client (on the local host):
# -c auto-detected if empty, -s is required
./bitflip -r client -s <server_ip>
# With explicit IPs
./bitflip -r client -c <client_ip> -s <server_ip>
| Short | Long | Default | Description |
|---|---|---|---|
-r |
--role |
server | Role: client or server |
-c |
--client-addr |
"" | Client IP address (auto-detected if empty) |
-s |
--server-addr |
"" | Server IP address (auto-detected for server role if empty) |
-t |
--tos |
64 | IP TOS/DSCP value |
-n |
--count |
0 | Max packets to send (0 = unlimited) |
-d |
--duration |
0 | Max send duration (0 = unlimited) |
--client-ports |
"43500,43599" | Client port range [min,max] | |
--server-ports |
"43500,43509" | Server port range [min,max] | |
--rate |
5000 | Packets per span | |
--msglen |
1024 | Message payload size (excluding 32-byte header) | |
--delay |
3s | Delay before processing stats (waiting for in-flight packets) | |
--verbose |
false | Print per-port loss details on packet loss (both client and server) |
# Server side — auto-detect, no need to specify -c
# Server auto-registers unknown clients on first packet
./bitflip
# Client side
sudo ./bitflip -r client -s 10.0.0.2
# Client with custom rate and duration
sudo ./bitflip --role client --server-addr 10.0.0.2 --rate 10000 --duration 60s
# Client with verbose loss port details
sudo ./bitflip -r client -s 10.0.0.2 --verbose
# Server with verbose loss port details (per-five-tuple loss)
./bitflip -s 10.0.0.1 --verbose
The client sends packets padded with 4 salt patterns, selected by seq % 4:
| Index | Pattern | Description |
|---|---|---|
| 0 | 0xFF |
All-ones byte |
| 1 | 0x00 |
All-zeros byte |
| 2 | 0x5A |
Fixed pattern 01011010 |
| 3 | Complementary alternating | 0xAAAA / 0x5555 alternating 16-bit words |
The server uses the same 4 salt patterns to validate packets, ensuring accurate identification of which bytes have been flipped.
+----------+----------+-----------+---------------+------------------+------------------+----------+
| Magic(8) | Seq(8) | Ts(8) | LastSent(4) | LastSrcPort(2) | LastDstPort(2) | Salt(N) |
+----------+----------+-----------+---------------+------------------+------------------+----------+
Through this compact protocol design, the server can reconstruct every port pair from the previous span using (LastSrcPort, LastDstPort, LastSent) and the deterministic GetNextPorts algorithm — enabling server-side unidirectional loss detection with per-five-tuple granularity, without the server needing to track client-side send state.
IPv6 variant of bitflip. Usage is identical to bitflip, with IPv6 addresses:
# Server side
./bitflip6
# Client side
sudo ./bitflip6 -r client -s fd00::2
A multi-target ICMP Echo ping tool for batch network quality inspection. Supports CIDR range expansion, DNS hostname resolution, hardware timestamping (Linux), high-rate probing, and packet corruption detection. mping6 is the IPv6 variant.
Key features:
- CIDR expansion: Pass a network prefix (e.g. 10.0.1.0/24) and mping automatically expands to all host addresses. IPv6 supports /112–/128 prefixes with a --max-targets safety cap.
- DNS resolution: Pass hostnames and mping resolves them automatically (A records for mping, AAAA for mping6).
- Hardware timestamps: Enabled by default on Linux via SO_TIMESTAMPING for nanosecond latency accuracy. Falls back to software timestamps on macOS.
- Rate control: Built-in token bucket rate limiter for precise per-target pps control.
- Multi-target: Comma-separated IPs, CIDR ranges, and DNS hostnames can be mixed freely.
- Packet corruption detection: Detects bit-flip errors in ICMP reply payloads by embedding known salt patterns in each probe packet.
Build:
make compile
Run:
# Single target (default 100 pps)
sudo ./mping -T 10.0.0.2
# Multiple targets
sudo ./mping -T 10.0.0.2,10.0.0.3,10.0.0.4
# CIDR range — probe entire /24
sudo ./mping -T 10.0.1.0/24
# DNS hostname
sudo ./mping -T www.example.com
# High rate for 30 seconds
sudo ./mping -T 10.0.0.2 -r 1000 -d 30s
# IPv6
sudo ./mping6 -T fd00::2
| Short | Long | Default | Description |
|---|---|---|---|
-T |
--targets |
— | Target IPv4 addresses/CIDR/hostnames, comma-separated (required) |
-l |
--local-addr |
auto | Local IP address |
-I |
--interface |
auto | Outgoing interface name |
-z |
--tos |
0 | IP TOS/DSCP value |
--ttl |
64 | IP TTL | |
-c |
--count |
0 | Max packets per target (0 = unlimited) |
-d |
--duration |
0 | Max send duration (0 = unlimited) |
--delay |
3s | Delay before processing stats | |
-t |
--timeout |
1s | Socket read timeout |
-r |
--rate |
100 | Packets per second per target |
-s |
--size |
64 | ICMP payload size in bytes (min: 8) |
--verbose |
false | Print per-reply ICMP details | |
--hwts |
true | Enable hardware timestamping | |
--max-targets |
65536 | Max targets after CIDR/DNS expansion | |
-V |
--version |
false | Print version and exit |
mping6 has the same flags with IPv6 equivalents (e.g. --tc instead of --tos, --hlim instead of --ttl).
See mping usage guide for more details.
A configuration-driven continuous network quality monitoring tool for long-term deployment. Unlike bitflip's command-line flag approach, baize uses a JSON config file and supports running both Client and Server in a single process.
Key features: - Config-driven: All parameters managed via JSON config file, easy for automated deployment. - Single-process dual-role: Run Client and Server together in one process. - Log rotation: Built-in daily log rotation with automatic cleanup of expired files and symlink to the latest log. - pprof integration: Built-in Go pprof HTTP server for runtime profiling. - Graceful shutdown: Listens for SIGINT/SIGTERM and gracefully shuts down all goroutines.
The internal version of baize used in Baidu's physical network also supports periodically pulling configuration from a database and pushing data to Kafka for aggregation. The open-source version is simplified to use config files only and output to logs by default, but provides interfaces for custom implementations.
Build:
go build -o baize ./cmd/baize/
Create a config file (e.g., baize.json):
{
"pprof_addr": ":6060",
"log_dir": "/var/log/baize",
"log_max_age_days": 7,
"client": {
"client_addr": "10.0.0.1",
"server_addrs": "10.0.0.2",
"rate_in_span": 5000,
"span": "1s",
"delay": "3s",
"msg_len": 1024,
"tos": 64
},
"server": {
"server_addr": "10.0.0.2",
"client_addrs": "10.0.0.1",
"rate_in_span": 5000,
"span": "1s",
"delay": "3s",
"msg_len": 1024,
"tos": 64
}
}
Run:
# Use default config file (baize.json)
sudo ./baize
# Specify config file path
sudo ./baize -c /etc/baize/baize.json
Top-level fields:
| Field | Type | Default | Description |
|---|---|---|---|
pprof_addr |
string | "" | pprof HTTP listen address (e.g. :6060), empty to disable |
log_dir |
string | "" | Log file directory, empty to output to stderr |
log_max_age_days |
int | 7 | Log retention days (≤0 defaults to 7) |
client |
object | null | Client config, null to skip |
server |
object | null | Server config, null to skip |
Client/Server fields:
| Field | Type | Default | Description |
|---|---|---|---|
client_addr / server_addr |
string | "" | Local IP address |
server_addrs / client_addrs |
string | "" | Remote IP address(es), comma-separated |
tos |
int | 0 | IP TOS/DSCP value |
client_port_range |
string | "" | Client port range min,max |
server_port_range |
string | "" | Server port range min,max |
rate_in_span |
int64 | 0 | Packets per span |
span |
string | "0s" | Stats time window (Go duration) |
delay |
string | "0s" | Stats processing delay |
msg_len |
int | 0 | Message payload size (excluding 32-byte header) |
count |
int | 0 | Max packets to send, client only (0 = unlimited) |
send_duration |
string | "0s" | Max send duration, client only (0 = unlimited) |
verbose |
bool | false | Print per-port loss details |
See baize usage guide for more details.
A GPU NIC interconnect probing tool for AI training clusters. Probes RoCEv2/UDP
$ claude mcp add nettools \
-- python -m otcore.mcp_server <graph>