Skip to content

Operations

Service control

The RPM ships a systemd unit named pdns-pf-ipmapper.service, running as the pdns-ipmapper user. Everyday commands:

# Status and recent logs
systemctl status pdns-pf-ipmapper

# Follow the log stream
journalctl -u pdns-pf-ipmapper -f

# Restart after a config change
systemctl reload-or-restart pdns-pf-ipmapper

The service does not watch its config file for changes; restart it after editing ipmapper.yaml.

On startup the service loads all sessions from Redis before accepting connections. During this load the ipmapper_ready_status metric reads 0; it flips to 1 once the load finishes. The duration is reported in ipmapper_redis_load_duration_seconds.

Config location

The default config path is /etc/pdns-pf/ipmapper.yaml. A commented template with every option is shipped alongside it as /etc/pdns-pf/ipmapper.example.yaml. See Configuration for the full reference.

Command-line flags

Flag Default Purpose
-c, --config /etc/pdns-pf/ipmapper.yaml Path to the YAML config file.
--debug false Enable debug logging.
--no-redis false Disable Redis persistence entirely (state is lost on restart).
--no-redisload false Skip loading state from Redis on startup; the service starts with an empty session table.
--force-gc-interval 0 (disabled) Force a full Go GC at this interval. Do not set below a few seconds — a forced GC sweep at high session counts causes visible CPU spikes.

Observability

All live-inspection surfaces are served by the HTTP server bound to http.address (see Configuration → http).

  • Status page. HTML summary at / showing active sessions, memory usage, Redis connection pool stats, and the readiness indicator.
  • Readiness probe. /healthz returns HTTP 200 once the instance is active and has loaded its state, and HTTP 503 while it is starting, waiting for the HA lock, or loading from Redis. The response body is a JSON go-healthz status payload. On 503 responses, readiness messages appear under failures["ipmapper-ready"]; for example, passive instances report waiting for redis lock. Use it as the backend health check for a load balancer or cluster controller (e.g. an HA proxy between the RADIUS Listener and the IP Mapper) so traffic only reaches the active instance. If the load balancer validates the response body, check a JSON field such as ok: true or status: "OK" instead of a bare OK body. See Architecture → Monitoring availability with /healthz.
  • Prometheus metrics. Scraped at /metrics. See Metrics for the full reference.
  • pprof. Go net/http/pprof handlers under /debug/pprof/ for CPU, heap, goroutine, and block profiles.

The journal also receives a stats line every 30 seconds when Redis sync is enabled, including session count, Redis send/receive throughput, and heap size.

When the session API is enabled it is served from this same listener under /api/v1/sessions. Protect that listener with TLS — and ideally an auth_token or mTLS — before exposing the port beyond a trusted network. Watch ipmapper_http_calls_unauthorized_total for rejected requests and ipmapper_http_duration_seconds for latency (see Metrics → Is the HTTP API healthy?).

Performance characteristics

Memory

The main cost is the in-memory session table. Set options.initial_allocation to your expected peak session count to avoid runtime map growth.

Preliminary sizing results for 10 million sessions under a single load with no fragmentation:

Mode Redis RAM usage IP Mapper RAM usage Session updates per second
Redis Script 18 GB n/a 20 k
IP Mapper with OpaqueID maps 7 GB ~10 GB 150 k
IP Mapper direct user mappings 5 GB ~10 GB 180 k

Treat these as lower-bound lab results. For production sizing, assume roughly double the RAM to account for fragmentation and operational headroom.

These figures exclude filter settings and device mappings. The IP Mapper internal state map accounts for about 2 GB of the Redis usage above and could be moved to a separate Redis instance.

The service sets Go's GOGC to 50 by default. This keeps peak heap allocation at roughly 1.5× the live set rather than the Go default of 2×, at the cost of more frequent GC sweeps. Override by setting GOGC in the service environment file before starting the unit.

Redis sync pipeline

The internal pipeline is sized by the performance knobs in the redis section. The defaults sustain several hundred thousand session updates per second. Watch ipmapper_nats_duration_seconds and ipmapper_resp_duration_seconds for signs that the pipeline is backing up.

Companion tool: pdns-pf-ipmapper-fill

The RPM ships pdns-pf-ipmapper-fill, a load-generation tool for benchmarking or pre-seeding sessions via the RESP interface using the legacy Lua script protocol.

pdns-pf-ipmapper-fill [flags]
Flag Default Purpose
-r 127.0.0.1:6379 RESP listener address.
-n 1000 Number of sessions to create.
-s ../../redis-scripts/pdns-pf-redis-script.lua Path to the redis script used to format session updates.
-L 0 (unlimited) Rate limit in sessions per second.

The tool generates synthetic IPv6 sessions using incrementing addresses in the 2001:db8:beef::/48 range and sends them using the setSession legacy Lua script interface.