Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}\build
run: PKG_CONFIG_PATH=${{github.workspace}}\local\lib\pkgconfig cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./cmake/conan_provider.cmake
run: PKG_CONFIG_PATH=${{github.workspace}}\local\lib\pkgconfig cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./cmake/conan_provider.cmake -DCONAN_INSTALL_BUILD_CONFIGURATIONS=$BUILD_TYPE

- name: Get VERSION
shell: pwsh
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ jobs:
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}\build
run: PKG_CONFIG_PATH=${{github.workspace}}\local\lib\pkgconfig cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./cmake/conan_provider.cmake
run: PKG_CONFIG_PATH=${{github.workspace}}\local\lib\pkgconfig cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./cmake/conan_provider.cmake -DCONAN_INSTALL_BUILD_CONFIGURATIONS=$BUILD_TYPE

- name: Get VERSION
shell: pwsh
Expand Down
11 changes: 5 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,11 @@ enable_testing()

message(STATUS "Building pktvisor version ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}${VISOR_PRERELEASE}")

# opentelemetry-cpp 1.26.0 generates proto headers with dllexport_decl=OPENTELEMETRY_PROTO_API; the Conan recipe doesn't propagate the macro. On Windows the proto package is a DLL (consumers must import); elsewhere it expands to nothing.
if(WIN32)
add_compile_definitions("OPENTELEMETRY_PROTO_API=__declspec(dllimport)")
else()
add_compile_definitions(OPENTELEMETRY_PROTO_API=)
endif()
# opentelemetry-cpp generates its proto headers with dllexport_decl=OPENTELEMETRY_PROTO_API and the
# Conan recipe does not propagate the macro to consumers. The recipe builds opentelemetry_proto as a
# static library on every platform (the shared option is removed on Windows), so the macro must
# expand to nothing; declaring dllimport against a static .lib leaves every proto symbol unresolved.
add_compile_definitions(OPENTELEMETRY_PROTO_API=)

add_subdirectory(3rd)
add_subdirectory(libs)
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ or
-H HOSTSPEC Specify subnets (comma separated) to consider HOST, in CIDR form. In live capture this
/may/ be detected automatically from capture device but /must/ be specified for pcaps.
Example: "10.0.1.0/24,10.0.2.1/32,2001:db8::/64"
Specifying this for live capture will append to any automatic detection.
For live capture, specifying this defines the host set explicitly and
disables automatic detection from the capture device; list every address
family (IPv4 and IPv6) you need.

```

Expand Down Expand Up @@ -396,7 +398,9 @@ docker run --rm netboxlabs/pktvisor pktvisor-reader --help
--geo-asn FILE GeoLite2 ASN database to use for IP to ASN mapping (if enabled)
-H HOSTSPEC Specify subnets (comma separated) to consider HOST, in CIDR form. In live capture this /may/ be detected automatically
from capture device but /must/ be specified for pcaps. Example: "10.0.1.0/24,10.0.2.1/32,2001:db8::/64"
Specifying this for live capture will append to any automatic detection.
For live capture, specifying this defines the host set explicitly and
disables automatic detection from the capture device; list every address
family (IPv4 and IPv6) you need.

```

Expand Down Expand Up @@ -527,6 +531,9 @@ using [remote write](https://prometheus.io/docs/operating/integrations/#remote-e
cloud providers, there is a [docker image available](https://hub.docker.com/r/netboxlabs/pktvisor-prom-write) to make this
easy. See [centralized_collection/prometheus](centralized_collection/prometheus) for more.

To run pktvisor as a sidecar in Kubernetes and scrape it with Prometheus, see
[centralized_collection/k8s](centralized_collection/k8s).

Also see [getorb.io](https://getorb.io) for information on connecting pktvisor agents to the Orb observability platform.

### REST API
Expand Down
1 change: 1 addition & 0 deletions centralized_collection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ See the individual READMEs for more information:

* [Prometheus](prometheus/README.md)
* [Elasticsearch](elastic/README.md)
* [Kubernetes sidecar (scraped by Prometheus)](k8s/README.md)
6 changes: 3 additions & 3 deletions k8s/README.md → centralized_collection/k8s/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ the same `eth0` as your application container.
## Deploy

```shell
# from the repo root (or use the bare filename from inside k8s/)
kubectl apply -f k8s/pktvisor-sidecar.yaml
# from the repo root (or use the bare filename from inside centralized_collection/k8s/)
kubectl apply -f centralized_collection/k8s/pktvisor-sidecar.yaml
```

Creates a `pktvisor-demo` Deployment with three containers: your app (`nginx`
Expand Down Expand Up @@ -140,7 +140,7 @@ explicit selection, do it inside a pktvisor-only scrape job.
## Grafana dashboard

Import the community dashboard **ID 14221**, or the JSON at
`../centralized_collection/prometheus/grafana-dashboard-prometheus.json`.
`../prometheus/grafana-dashboard-prometheus.json`.

## Use with your own workload

Expand Down
File renamed without changes.
9 changes: 5 additions & 4 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class Pktvisor(ConanFile):
generators = "CMakeToolchain", "CMakeDeps"

def requirements(self):
self.requires("catch2/3.15.1")
self.requires("cpp-httplib/0.27.0")
self.requires("catch2/3.16.0")
self.requires("cpp-httplib/0.47.0")
self.requires("docopt.cpp/0.6.3")
self.requires("fast-cpp-csv-parser/cci.20240102")
self.requires("json-schema-validator/2.4.0")
self.requires("libmaxminddb/1.12.2")
self.requires("nlohmann_json/3.12.0", force=True)
self.requires("openssl/3.6.3")
self.requires("openssl/3.6.4")
if self.settings.os != "Windows":
self.requires("libpcap/1.10.6", force=True)
else:
Expand All @@ -27,7 +27,7 @@ def requirements(self):
self.requires("uvw/3.4.0")
self.requires("yaml-cpp/0.9.0")
self.requires("robin-hood-hashing/3.11.5")
self.requires("libcurl/8.21.0")
self.requires("libcurl/8.22.0")
self.requires("libnghttp2/1.68.1")
if (
"libc" not in self.settings.compiler.fields
Expand All @@ -37,6 +37,7 @@ def requirements(self):

def configure(self):
self.options["libcurl"].with_nghttp2 = True
self.options["cpp-httplib"].use_non_blocking_getaddrinfo = False

def build_requirements(self):
self.tool_requires("protobuf/6.33.5")
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/netprobe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ All metrics are per-target (keyed by the name given in the `targets` config map)
| `dns_lookup_failures` | DNS resolution failures |
| `packets_timeout` | Probes that timed out |
| `http_status_failures` | HTTP/DoH responses whose HTTP status failed the configured status checks (default: any status outside 2xx/3xx). See [Success semantics](#success-semantics) above for the full `failure_status`/`expected_status` precedence — this counter fires whenever that evaluation lands on "fail," whether by the default 2xx/3xx rule, an `expected_status` miss, or a `failure_status` hit. |
| `content_failures` | HTTP responses whose status passed the status check but the configured `expected_body`/`expected_body_regex` check(s) did not match. Never incremented together with `successes` or `http_status_failures` for the same response — HTTP-only (not applicable to `doh`, which has no body-check config). |
| `content_failures` | HTTP responses whose status passed the status check but at least one configured response assertion failed — body (`expected_body`, `expected_body_regex`, `not_contains`, `body_not_matches_regex`), JSON (`json_path`/`json_equals`), size (`min_response_size_bytes`/`max_response_size_bytes`), header (`fail_if_header_matches`/`fail_if_header_not_matches`, `max_last_modified_diff_secs`) or protocol version (`valid_http_versions`). Never incremented together with `successes` or `http_status_failures` for the same response — HTTP-only (not applicable to `doh`, which has no response-assertion config). |
| `top_status_codes` | Top HTTP status codes observed (e.g. `"200"`, `"404"`, `"503"`) |
| `dns_response_failures` | DoH responses with HTTP 2xx/3xx but a non-NOERROR or unparseable DNS rcode |
| `top_rcodes` | Top DNS response codes observed in DoH probes (e.g. `"NOERROR"`, `"NXDOMAIN"`, `"SRVFAIL"`, `"PARSE_ERROR"`) |
Expand Down
50 changes: 50 additions & 0 deletions src/inputs/netprobe/test_netprobe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,56 @@ TEST_CASE("NetProbe ip_version config", "[netprobe][config][ipv6]")
}
}

TEST_CASE("NetProbe ip_version config: literal IPv6 target is auto-detected and routed to a probe", "[netprobe][config][ipv6]")
{
// Design-spec test #3. A ping stream cannot start unprivileged (the shared receiver opens raw
// sockets), so exercise the literal-target parse/route path — shared by ping and tcp — through
// the tcp test type: "::1" must be accepted as an IPv6 literal without any ip_version hint,
// survive start(), and be counted as one target.
NetProbeInputStream stream{"net-probe-test-v6-literal"};
stream.config_set("test_type", "tcp");
stream.config_set<uint64_t>("interval_msec", 60000);
stream.config_set<uint64_t>("timeout_msec", 100);
auto targets = std::make_shared<visor::Configurable>();
auto target = std::make_shared<visor::Configurable>();
target->config_set("target", "::1");
target->config_set<uint64_t>("port", 9);
targets->config_set<std::shared_ptr<visor::Configurable>>("v6_literal", target);
stream.config_set<std::shared_ptr<visor::Configurable>>("targets", targets);

CHECK_NOTHROW(stream.start());
nlohmann::json j;
stream.info_json(j);
CHECK(j[stream.schema_key()]["current_targets_total"] == 1);
CHECK(j["module"]["config"]["targets"]["v6_literal"]["target"] == "::1");
CHECK_NOTHROW(stream.stop());
}

TEST_CASE("NetProbe ip_version config: DNS target with ip_version 6 round-trips through start and info_json", "[netprobe][config][ipv6]")
{
// Design-spec test #4: a DNS (non-literal) target may carry ip_version: 6. It must parse,
// reach start() as a DNS-entry probe, and echo the per-target ip_version back via info_json.
// Same tcp-instead-of-ping justification as the literal-IPv6 case above.
NetProbeInputStream stream{"net-probe-test-v6-dns"};
stream.config_set("test_type", "tcp");
stream.config_set<uint64_t>("interval_msec", 60000);
stream.config_set<uint64_t>("timeout_msec", 100);
auto targets = std::make_shared<visor::Configurable>();
auto target = std::make_shared<visor::Configurable>();
target->config_set("target", "localhost");
target->config_set<uint64_t>("port", 9);
target->config_set<uint64_t>("ip_version", 6);
targets->config_set<std::shared_ptr<visor::Configurable>>("v6_dns", target);
stream.config_set<std::shared_ptr<visor::Configurable>>("targets", targets);

CHECK_NOTHROW(stream.start());
nlohmann::json j;
stream.info_json(j);
CHECK(j[stream.schema_key()]["current_targets_total"] == 1);
CHECK(j["module"]["config"]["targets"]["v6_dns"]["ip_version"] == 6);
CHECK_NOTHROW(stream.stop());
}

TEST_CASE("NetProbe http_method config validates", "[netprobe][config][http]")
{
// Validates that the http_method key is accepted by validate_configs (no throw before
Expand Down
Loading