Pktvisor
The pktvisor backend embeds the pktvisord process inside Orb Agent to run deep packet analytics, active probes, and streaming aggregations directly at the edge. Pktvisor policies let you decide which network taps to activate, which analyzers to run, and how the resulting metrics are exported to your observability stack.
Reference
The two sections of a policy have a folder each.
| Page | Contents |
|---|---|
| Inputs | The data streams a policy can consume, and how a tap is declared. Covers pcap, flow and dnstap inline, with netprobe on its own page. |
| Handlers | The handler section, the available handler types and versions, metric groups, and the settings shared by every handler. One page per handler: DNS, Network, Flow, DHCP, BGP, Packet capture, Netprobe, Input resources. |
| Metrics | The metrics each handler produces. The input_resources metrics are on its own page. |
Configuration
Orb writes a temporary pktvisor configuration file each time it starts pktvisord, based on the orb.backends.pktvisor block; a pktvisor declared on demand that never starts writes none. Any key that is not handled explicitly is forwarded to visor.config in the generated file, so you can pass through native pktvisor options such as logging, crashpad, or custom data paths when needed.
Backend settings
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
host | string | no | localhost | Admin API host. Written to visor.config.host, which is the address the pktvisord the agent starts binds its admin API to, and the address the agent uses to reach it. Change it only to alter that bind address. |
port | string | no | free port | Admin API port, written to visor.config.port and passed to pktvisord with -p. Unset, a loopback host gets a port free at each start and any other host gets 10853; see Backend keys. |
taps | map | no | – | Declarative tap definitions copied into visor.taps. Each tap sets the data source (input_type, config, and optional tags). Not required: netprobe and flow policies can run on taps the agent manages. Tap names that start with fleet_ are refused here. |
| other keys | any | no | – | Added verbatim under visor.config (for example log_level, crashpad options, or storage paths). |
Pktvisor ships with the Orb agent container image. If you run Orb on a bare host, ensure the pktvisord binary is in $PATH or adjust your deployment accordingly.
Taps
A tap names a data source once, on the agent, so that policies can refer to it.
There are two kinds: local taps, which you declare on the agent, and taps the agent
manages for netprobe and flow policies.
Local taps
Each tap sets an input_type, its config, and optional tags that a policy can
select on. See Inputs for the configuration each input type accepts.
A tap has no filter key: filters belong to the policy's input, and a filter
written on a tap is ignored without an error. For packet capture a BPF expression
can also go in the tap's config, since pcap accepts bpf there.
orb:
backends:
pktvisor:
start_mode: on_demand # the image declares this backend on demand; see the README's Backends section
host: 0.0.0.0
port: "10853"
taps:
edge_dns:
input_type: pcap
config:
iface: eth0
bpf: "port 53"
sflow:
input_type: flow
config:
flow_type: sflow
port: 6343
bind: 192.168.1.1
tags:
virtual: false
vhost: 2
common:
otlp:
http: "http://otel-collector.monitoring.svc.cluster.local:4318"A pcap or dnstap policy always needs a local tap, since the interface or socket is a
property of the host. Names starting with fleet_ are reserved for the taps the agent
manages. A local tap with that prefix is refused when the agent configures the backend,
and the agent does not start.
Defining taps with environment variables
In a container, you can define local taps with ORB_BACKENDS__PKTVISOR__TAPS__<NAME>__...
variables instead of a config file. Names are lower-cased, so
ORB_BACKENDS__PKTVISOR__TAPS__EDGE_DNS__INPUT_TYPE defines the tap edge_dns, and a
policy must name it that way.
ORB_BACKENDS__PKTVISOR__START_MODE=on_demand
ORB_BACKENDS__PKTVISOR__TAPS__EDGE_DNS__INPUT_TYPE=pcap
ORB_BACKENDS__PKTVISOR__TAPS__EDGE_DNS__CONFIG__IFACE=eth0These variables replace the image's whole pktvisor entry, including its start_mode.
Set ORB_BACKENDS__PKTVISOR__START_MODE=on_demand as well, or pktvisord starts with
the agent instead of when the first pktvisor policy arrives. Values set this way are
strings. See Environment variable configuration
for how the overlay works.
Taps are the one backend setting an agent in Fleet mode accepts from its edge. The agent
reports them in agent_config from its first connect, and in the backend capabilities
from the next connect after pktvisord starts.
Taps the agent manages
A policy that names no tap, and has input_type netprobe or flow, runs on a tap the
agent manages. The tap is fleet_netprobe or fleet_flow. You do not declare it:
- When the agent applies the policy, it creates the tap through the
pktvisordtap API. The tap carries only theinput_type. Everything else stays in the policy'sinput.config. - The agent sends
pktvisorda copy of the policy withinput.tapset to the managed tap. Your policy body is not changed. - When no policy uses the tap any more, the agent deletes it.
- Managed taps are not part of the capabilities the agent sends to Fleet.
A policy names no tap when input.tap is absent, null or empty and input.tap_selector
is absent or null. Two related cases:
- A policy that names no tap with any other input type, such as
pcapordnstap, is refused:pktvisor policy with input_type "pcap" must name a tap in input.tap or input.tap_selector; the agent creates taps only for netprobe and flow. Forsflowthe message adds(for sFlow, use input_type flow). - A policy that sets
input.tapto a name starting withfleet_is refused. Leaveinput.tapout to use the managed tap.
Policies on the same tap with an identical input config share one input stream. For flow,
pktvisord refuses any other input whose bind and port overlap a listener that is already
running, including the same config on another tap. They overlap when the port is the same and
so is the address, or a wildcard covers the other's address; two different specific addresses
can share a port. See Choosing a port and flow type
for the details, including ::. The policy fails to apply, and its error ends with
unable to bind flow UDP server on <bind>:<port>: address already in use. So an edit that
changes the config or the tap of a flow policy that shares its listener with another policy,
and still overlaps that listener, fails the same way. The old version has already been removed
by then, so the policy runs nothing until the edit is fixed; see Edits.
pktvisord puts the tap name in its handler names, so moving a policy between a managed
tap and a local one starts new metric series.
Exporting pktvisor metrics
pktvisord can stream OpenTelemetry HTTP metrics directly to a collector. Configure the shared backends.common.otlp section, as in the example above, to point Orb Agent at your collector endpoint.
pktvisord summarizes each policy in one-minute windows and pushes each window once, within about 5 seconds of its closing. A policy's first metrics therefore arrive about a minute after it starts, and each later window a minute after the one before; a push carries only the policies with a newly closed window. With merge_like_handlers, a merged window is pushed once every handler in the policy has closed it. A policy whose window_config sets num_periods: 1 never closes a window while it runs, so it pushes its running totals once a minute instead.
When a pcap_file capture ends, its open window counts as closed and is pushed once. A capture shorter than a minute therefore still produces metrics, and one with num_periods: 1 stops pushing once a minute.
Policy structure
Define pktvisor policies under orb.policies.pktvisor. Each entry key becomes the policy name pushed to pktvisord, and the agent wraps the body you write in the envelope pktvisord expects, so the body is just the four sections below.
orb:
policies:
pktvisor:
my_policy:
input: ...
handlers: ...
config: ...
kind: collection| Section | Required | Description |
|---|---|---|
input | yes | The data stream to analyse: a tap name or tag selector, plus the input type and any filters. |
handlers | yes | The analyzer modules to run on that input, and their configuration, filters and metric groups. |
config | no | Policy level settings. Currently only merge_like_handlers. |
kind | yes | The only supported value is collection. |
A policy name must be unique within the backend. Policy, tap and handler module
names must match [a-zA-Z_][a-zA-Z0-9_-]*, so they start with a letter or
underscore and contain only letters, digits, _ or -.
Policies from Fleet
A policy from Fleet has the same body as an orb.policies.pktvisor.<name> entry: kind,
input, handlers and config. The agent wraps it in the envelope pktvisord expects.
The policy name must match [a-zA-Z_][a-zA-Z0-9_-]*. The agent refuses any other name
before it calls pktvisord.
This body probes two targets with the managed fleet_netprobe tap. It names no tap:
kind: collection
input:
input_type: netprobe
config:
test_type: ping
interval_msec: 5000
targets:
gateway:
target: 192.0.2.1
resolver:
target: 192.0.2.53
handlers:
modules:
probe_metrics:
type: netprobeFlow
The managed tap carries no config, so a flow body that does not set
pcap_file sets both port and bind in
input.config. pktvisord refuses a flow input without them.
kind: collection
input:
input_type: flow
config:
flow_type: sflow
port: 6343
bind: 0.0.0.0
handlers:
modules:
flow_metrics:
type: flowBehind a container, use bind: 0.0.0.0 and publish the UDP port. Use input_type: flow,
not the sflow alias, because the agent creates managed taps only for flow and
netprobe. A pcap_file is replayed while the policy is applied, so keep it well under
the 10 second apply timeout.
Edits
An edit is a remove followed by an apply. A flow listener closes briefly when the edited policy is the last one on its listener.
The agent checks the policy name and the tap before an edit removes the running policy. So when the agent refuses an edit:
- The old version keeps running, and the policy shows
failed_to_apply. - After a refused rename, the old version's series lose their policy attribution until the edit is fixed or the policy is removed.
- The next
pktvisordrestart drops the old version.
Two failures come after the old version is removed: the agent cannot create the tap, or
pktvisord refuses the new version. Then the old version is already gone, and the policy
runs nothing until the edit is fixed.
Policies that are refused
The agent refuses a policy with a bad name, or one that names no tap and has an input
type other than netprobe or flow. It still starts pktvisord on demand first, as it
already does for a name with a slash.
If pktvisord takes longer than the 10 second apply timeout to accept a policy on a
managed tap, the agent keeps that tap until it next starts pktvisord, even after the
last policy that used it is removed.
Example policy
The following policy inspects DNS traffic captured from the edge_dns tap and runs both DNS-specific and network-wide analytics. Use this pattern when you want to reuse a tap across multiple handlers.
orb:
policies:
pktvisor:
edge_dns_inspection:
input:
input_type: pcap
tap: edge_dns
config:
merge_like_handlers: true
handlers:
window_config:
num_periods: 5
deep_sample_rate: 100
modules:
dns_summary:
type: dns
require_version: "2.0"
metric_groups:
enable:
- counters
- quantiles
config:
public_suffix_list: true
topn_count: 25
net_overview:
type: net
kind: collectionNote the require_version: "2.0" on the DNS module. A module that omits require_version runs version 1.0 of that handler; see available handlers.
Additional resources
- Pktvisor project home - feature overview, module reference, and deployment notes.
Device Discovery - Supported Platforms
This page lists the vendors, operating systems, and NAPALM drivers supported by the device discovery backend - currently 48 drivers (7 standard + 41 custom) ...
Metrics
The metrics each handler produces, grouped by handler type. The inputresources handler is not listed here; its four metrics are on its own page. A handler em...