Skip to main content

PingClient

PingClient is the client-side endpoint of Ping wire v2. It carries a complete inner IPv4 packet in a real ICMP Echo Request, and consumes correlated Echo Replies as wire acknowledgements. Reply generation is optional and disabled by default. It is a pure packet tunnel with no connection line state.

After decoding an Echo Request, inner packets are forwarded downstream on the arrival worker. Correlation, replay checks and any generated Echo Reply also stay on that worker; the shared tracker does not require transport-flow affinity. Inner fragments are forwarded immediately with their bytes and boundaries intact, without waiting for the leading fragment. A later stateful consumer establishes its own flow ownership. Unrelated or unmatched ICMP retains its packet bytes.

Use the paired edges in this order:

TunDevice -> PingClient -> RawSocket
RawSocket -> PingServer -> TunDevice

Two Independent Echo Sessions​

Ping v2 never puts new application data into an Echo Reply.

client data: PingClient -- Echo Request(data) --> PingServer
PingClient <-- optional Echo Reply(same bytes) -- PingServer

server data: PingClient <-- Echo Request(data) -- PingServer
PingClient -- optional Echo Reply(same bytes) --> PingServer

The peer delivers the received request's inner IPv4 packet once. With send-replies: true, it first sends an exact type-0 Echo Reply. False or omission skips reply allocation, copying, and transmission. The endpoints choose this setting independently; request tracking and replay suppression remain active, and incoming correlated replies are consumed regardless of the local setting. Data delivery does not wait for a reply.

PingClient callbackBehavior
upstream plain packetBuild a type-8 Echo Request; forward upstream.
downstream peer requestIf send-replies is true, build/send a type-0 reply upstream; strip and forward the original request downstream once.
downstream matching replyConsume as acknowledgement.

Settings​

{
"name": "ping-client",
"type": "PingClient",
"settings": {
"local-ipv4": "198.51.100.10",
"peer-ipv4": "203.0.113.20",
"send-replies": false,
"identifier": "random",
"sequence-start": 1,
"ttl": 64,
"tos": 0
},
"next": "raw-out"
}
SettingRequiredDefaultDescription
local-ipv4yes—Local source of requests/replies.
peer-ipv4yes—Request destination and expected source of peer carrier traffic.
send-repliesnofalseBoolean. Send exact Echo Replies for received peer requests when true; false or omission skips reply generation.
identifierno"random"Stable local request-session ID. Integer 0..65535 is a deterministic override; random defaults are nonzero.
sequence-startno1First local request sequence, 0..65535; wrap is valid.
ttlno64Locally generated packet TTL. Integer 0..255.
tosno0Local request TOS. Integer 0..255; generated replies copy the peer request TOS.

Client and server identifiers are intentionally independent. A reply mirrors the request's identifier and sequence rather than the responder configuration.

Wire and Safety Rules​

The wire format is exactly:

20-byte IPv4 header -> 8-byte ICMP Echo header -> complete inner IPv4 packet
  • Local requests: type 8, code 0, configured source/destination/TOS/TTL, DF set, IPv4 ID 0, local identifier, and ascending sequence.
  • Generated replies, when send-replies is true: type 0, code 0, reversed addresses, copied request identifier/sequence/payload length/payload bytes, copied request TOS, local TTL, and cleared fragmentation bits.
  • Reply IPv4 IDs come from a securely seeded tuple-scoped Linux-like approximation. This is not host-global Linux kernel state.

Input must be an exact IPv4 packet no larger than 1472 bytes. Valid inner IPv4 fragments are supported; outer carrier fragmentation, invalid checksums, malformed lengths, IPv6/non-IPv4 input, and oversized packets are dropped. Structurally valid traffic unrelated to the configured carrier tuple passes through unchanged in the same direction.

One synchronized node-wide tracker has a 1024-entry outstanding ring and a 1024-entry replay ring. Device worker affinity is not correlation identity: a reply or duplicate request can arrive on another packet-line WID and still match. Duplicate peer requests deliver their inner data once and get another reply only when send-replies is true. The 28-byte carrier overhead gives a 1500-byte maximum packet; Ping does not fragment, perform PMTU discovery, or adjust MSS.

Packet rejection diagnostics use the network logger at ERROR level and identify the specific validation, checksum, size, headroom, or tracking failure. Each drop message includes the packet length, maximum inner/carrier lengths, wrapper overhead, and available/required left headroom, all in bytes. The five-second log gate is shared by all failure reasons, directions, and workers of each node, so it does not emit one message per rejected packet.

Breaking Migration From v1​

Only the settings above are accepted. strategy, all wrap-*/warp-* modes, source, dest, protocol-swap settings, check-identifier, ipv4-id-start, xor-byte, roundup-size, and roundup are removed and produce a migration error.

Replace source/dest with local-ipv4/peer-ipv4; reverse them on the server. Upgrade both peers together: v2 is not compatible with the removed wire formats.

Correct Echo semantics reduce protocol fingerprints but do not make arbitrary, high-rate tunnel traffic indistinguishable from interactive ping traffic.

Node Metadata​

Source-backed metadata:

PropertyValue
version2
node flagskNodeFlagNone
can_have_prevtrue
can_have_nexttrue
layer_groupkNodeLayer3
layer_group_prev_nodekNodeLayer3
layer_group_next_nodekNodeLayer3
required_padding_left28 bytes
line statenone