Repository navigation
fix(inputs/netprobe): connect TCP probes to IPv6 targets and account for every attempt - #807
Conversation
…for every attempt uvw's connect(ip, port) builds the address with a helper that returns a 16-byte sockaddr, so an IPv6 target lost the end of its address and the connect went to whatever followed on the stack. The probe now builds a sockaddr_storage and calls connect(const sockaddr &). The same function had three more problems: - connect()'s returned error was ignored, so a connect that failed inside connect() itself was reported neither way. It is now a connect failure. - A failed attempt never closed its handle, leaking it and its socket on every interval. It is now closed. - An attempt still connecting when the next interval started was never closed: stop() closed only the newest, and the loop stayed busy until the kernel gave up. The next interval now closes it, before any DNS lookup, and reports it as a timeout, because the stream handler counts a timeout only when a result arrives late. A tick can come before the attempt has run timeout_msec, when the attempt started late behind a loop blocked by another target's DNS lookup, or by the loop clock's rounding to milliseconds when timeout_msec equals interval_msec. That tick is put off until the attempt has run its timeout. An attempt closed by stop() or by the next interval is not reported as a connect failure, and neither is an error from the shutdown that follows a successful connect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
/ai-review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
AI Code Review — risk tier: Advisory only. A human owns the merge decision. Summary — Net-positive fix: the new attempt-tracking state machine correctly connects TCP probes to IPv6 targets and accounts for every connection attempt, with tests covering the refused/immediate-failure/still-connecting/late-tick cases. No correctness or security issues found. 🤖 AI Code Review · run · prompts: |
|
AI Code Review — risk tier: Advisory only. A human owns the merge decision. Summary — Net positive change. The TcpProbe attempt-lifecycle rework (IPv6 sockaddr fix, connect()-error handling, timeout deferral, cancel-vs-failure disambiguation) and the 🤖 AI Code Review · run · prompts: Previous review · 2026-10-29 · c7c2905AI Code Review — risk tier: Advisory only. A human owns the merge decision. Summary — Net-positive fix: corrects IPv6 🤖 AI Code Review · run · prompts: |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
LCOV of commit
|
…s transaction TTL create_event_proxy passed the stream's _timeout_msec to the handler as xact_ttl_ms, but only start() sets that member, and a policy load creates the proxy before it starts the input. So the handler of a policy that created its netprobe input always timed ping replies and TCP connections against the 2000 ms default, whatever timeout_msec said. The proxy now reads timeout_msec from the input's config, which is merged in before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
/ai-review |
|
🔁 AI Code Review updated for |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Follow-up to #805: problems in netprobe's TCP probe, all in
TcpProbe::_perform_tcp_process()and its interval timer.IPv6 targets connected to a corrupted address. uvw's
connect(ip, port)builds the address with a helper that returns a 16-bytesockaddr. That cuts a 28-bytesockaddr_in6short, so libuv read the end of the address and the scope id from whatever followed on the stack. This is the same truncation #805 fixed for flow binds. The probe now builds asockaddr_storagewithuv_ip4_addr/uv_ip6_addrand callsconnect(const sockaddr &).Every attempt now gets exactly one result. Before:
connect()'s returned error was ignored, so a connect that failed insideconnect()itself, such as a TCP connect to a multicast address, reported neither success nor failure._client,stop()closed only the newest, and the loop stayed busy until the kernel gave up on the SYNs: 75 s here, 127 s on Linux. When it gave up, the attempt counted as a connect failure, although by then it had long passedtimeout_msec.Now:
stop()or by the next interval (UV_ECANCELED) is not a connect failure, and neither is an error from the shutdown that follows a successful connect.A tick that comes before the attempt has run
timeout_msecis put off. An attempt can start late behind a loop blocked by another target's synchronous DNS lookup. Also, libuv's loop clock rounds to milliseconds, so whentimeout_msecequalsinterval_mseca tick can come a millisecond early. Dropping the attempt then would count a timeout too early, and skipping the tick would lose 10-30% of attempts in that configuration. So the tick is put off until the attempt has run its timeout, by a steady clock. A deferral shifts that probe's later ticks by the same amount. No attempt is lost, and with the defaults (5000/2000) it takes a block of more than 3 s.The handler timed results against 2000 ms, whatever
timeout_msecsaid.create_event_proxypassed the stream's_timeout_msecto the handler asxact_ttl_ms. Onlystart()sets that member, and a policy load creates the proxy before it starts the input (Policies.cpp). So withtimeout_msec: 500a 1.5 s ping reply counted as a success, and withtimeout_msec: 5000a 3 s TCP handshake counted as a timeout. The proxy now readstimeout_msecfrom the input's config, which is merged in before the proxy is created. This was found while documenting the timeout behaviour, and predates this PR.Tests
All 25 ctest targets pass on macOS, Release and
-O0. The new TCP probe tests drive aTcpProbedirectly on its own loop:[::1], with every attempt succeeding.224.0.0.1that fails insideconnect()is reported.timeout_msec. This failed on develop with 2000.Every probe test also checks that no handle is left open and that the loop closes. All of them failed on develop. The IPv6 one fails only unoptimized: at
-O2the truncated address happens to survive on the stack. The Debug code-coverage job runs it unoptimized. The late-start test checks ordering against a timer that ticks with the probe, not wall-clock gaps, so CPU load doesn't affect it. The probe stops 25 ms after its sixth attempt, so the counts are exact.Not changed here
docs/backends/pktvisor/inputs/netprobe.mdsays the TCP probe does not enforcetimeout_msec. After this change it does, at the next tick. The docs are updated in a separate orb-agent PR, to merge after this one._is_ipv4stays unused, as on develop.toString()orinet_ntop.🤖 Generated with Claude Code