Parent: #3404
Depends on: #3406
Add ICMP ping capability to the geoprobe-agent so it can measure RTT to OutboundIcmp targets.
Context
The geoprobe-agent runs on geoprobe servers (Ubuntu bare metal or VPS), not DZDs. Today it measures latency to Outbound targets using TWAMP (via the Pinger component, which creates twamplight.Sender instances). OutboundIcmp targets need a different measurement path — ICMP echo request/reply — since the target host won't be running a TWAMP reflector.
DZDs are uninvolved here — they always use TWAMP to measure geoprobes. This change only affects the geoprobe→target measurement leg.
Changes
Target Discovery (controlplane/telemetry/internal/geoprobe/target_discovery.go)
- Add a third update channel (or extend
TargetUpdate) for OutboundIcmp targets.
- In the discovery switch, route
GeoLocationTargetTypeOutboundIcmp targets to the new channel. Extract IP address the same way as Outbound, but use a simpler address type (no TWAMP port needed).
- Validate scope (public unicast) the same as
Outbound.
ICMP Pinger (controlplane/telemetry/internal/geoprobe/icmp_pinger.go — new file)
- Implement an ICMP pinger that sends echo requests and measures RTT.
- Match the
Pinger interface pattern: AddProbe, RemoveProbe, ProbeAll returning RTT per target.
- Use the same probe interval and stagger delay as the TWAMP pinger.
- Handle ICMP-specific concerns: sequence numbers, identifier fields, timeout for unreachable hosts.
Agent main.go (controlplane/telemetry/cmd/geoprobe-agent/main.go)
- Instantiate the ICMP pinger alongside the existing TWAMP pinger.
- Wire target discovery updates to the ICMP pinger.
- Feed ICMP RTT results into the measurement cycle.
- Add a
--additional-icmp-targets flag (or extend --additional-targets with a type prefix) for CLI-specified ICMP targets.
Deployment
The geoprobe-agent currently requires no special privileges (all UDP, unprivileged ports). ICMP changes this:
- Raw ICMP sockets (
ip4:icmp) require CAP_NET_RAW.
- Unprivileged ICMP (
udp4 DGRAM sockets via icmp.ListenPacket("udp4", ...)) avoids CAP_NET_RAW but requires the net.ipv4.ping_group_range sysctl to include the agent's GID.
Pick one approach and document the deployment requirement:
- If raw sockets: add
AmbientCapabilities=CAP_NET_RAW to the systemd unit and update Ansible.
- If unprivileged ICMP: add the sysctl configuration to Ansible.
Tests
- Unit tests for ICMP pinger (mock ICMP socket or use loopback).
- Unit tests for target discovery routing of
OutboundIcmp targets.
- Integration test if feasible (ICMP to localhost).
Design Considerations
- No offset delivery:
OutboundIcmp targets don't have a location_offset_port and don't run any DoubleZero software, so the publisher cannot send composite offsets to them. The RTT measurement is still valuable for geolocation triangulation. Clarify how ICMP RTT data is consumed — does it get submitted onchain, reported via metrics only, or fed into a different pipeline than the TWAMP composite offset flow?
- Measurement quality: ICMP RTT may differ from TWAMP RTT due to kernel vs. userspace timestamping. Document any expected delta.
Acceptance
- Geoprobe-agent discovers
OutboundIcmp targets from onchain data and pings them via ICMP.
- RTT measurements appear in logs/metrics.
- Targets that are unreachable are handled gracefully (logged, not fatal).
- Existing
Outbound (TWAMP) and Inbound flows are unaffected.
- Deployment requirements (capability or sysctl) are documented and added to Ansible/systemd config.
Parent: #3404
Depends on: #3406
Add ICMP ping capability to the geoprobe-agent so it can measure RTT to
OutboundIcmptargets.Context
The geoprobe-agent runs on geoprobe servers (Ubuntu bare metal or VPS), not DZDs. Today it measures latency to
Outboundtargets using TWAMP (via thePingercomponent, which createstwamplight.Senderinstances).OutboundIcmptargets need a different measurement path — ICMP echo request/reply — since the target host won't be running a TWAMP reflector.DZDs are uninvolved here — they always use TWAMP to measure geoprobes. This change only affects the geoprobe→target measurement leg.
Changes
Target Discovery (
controlplane/telemetry/internal/geoprobe/target_discovery.go)TargetUpdate) forOutboundIcmptargets.GeoLocationTargetTypeOutboundIcmptargets to the new channel. Extract IP address the same way asOutbound, but use a simpler address type (no TWAMP port needed).Outbound.ICMP Pinger (
controlplane/telemetry/internal/geoprobe/icmp_pinger.go— new file)Pingerinterface pattern:AddProbe,RemoveProbe,ProbeAllreturning RTT per target.Agent main.go (
controlplane/telemetry/cmd/geoprobe-agent/main.go)--additional-icmp-targetsflag (or extend--additional-targetswith a type prefix) for CLI-specified ICMP targets.Deployment
The geoprobe-agent currently requires no special privileges (all UDP, unprivileged ports). ICMP changes this:
ip4:icmp) requireCAP_NET_RAW.udp4DGRAM sockets viaicmp.ListenPacket("udp4", ...)) avoidsCAP_NET_RAWbut requires thenet.ipv4.ping_group_rangesysctl to include the agent's GID.Pick one approach and document the deployment requirement:
AmbientCapabilities=CAP_NET_RAWto the systemd unit and update Ansible.Tests
OutboundIcmptargets.Design Considerations
OutboundIcmptargets don't have alocation_offset_portand don't run any DoubleZero software, so the publisher cannot send composite offsets to them. The RTT measurement is still valuable for geolocation triangulation. Clarify how ICMP RTT data is consumed — does it get submitted onchain, reported via metrics only, or fed into a different pipeline than the TWAMP composite offset flow?Acceptance
OutboundIcmptargets from onchain data and pings them via ICMP.Outbound(TWAMP) andInboundflows are unaffected.