Files
nginx-ipng-stats-plugin/tests/01-module/lab/server/nginx.conf
Pim van Pelt badb684431 Allow plain and device-tagged listens to share a sockaddr (v0.7.1)
The previous wrapper skipped nginx's duplicate-listen check only
for listens that carried device=, so a `listen 80;` next to a
`listen 80 device=eth0 ...;` in the same server block was
rejected at config time. Under SO_BINDTODEVICE that restriction
tracked a real kernel constraint (device-tagged listens created
separate sockets, a bare listen alongside them was genuinely
ambiguous). Under the IP_PKTINFO model introduced in 450391a
the constraint no longer exists — all same-sockaddr listens
collapse to one wildcard kernel socket and attribution is a
per-connection cmsg readback — but the wrapper kept enforcing
the old rule by accident.

Extend the (cscf, sockaddr) dedup in the listen wrapper to
cover plain listens too: the first occurrence at a given
(server, sockaddr) pair calls nginx's handler and registers the
kernel socket, and every subsequent sibling — plain or
device-tagged — is accepted without tripping nginx's
duplicate-listen check. Device-tagged siblings additionally
push a binding into the attribution table as before; plain
siblings contribute only the seen-list entry. No code path
exercised by the existing 22 e2e tests changes behavior.

Update FR-1.5, the user-guide "shared port" section, the
module's top-of-function comments, and the test nginx.conf
comment to describe the relaxed rule. Bump VERSION and add a
debian/changelog entry for 0.7.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 09:17:44 +02:00

105 lines
3.5 KiB
Nginx Configuration File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPDX-License-Identifier: Apache-2.0
# Test nginx configuration for the ipng_stats module.
#
# Data plane (port 8080) uses four wildcard listens — two address
# families × two devices — to exercise per-(device, family)
# attribution. eth1 uses the same tag (`tag1`) for IPv4 and IPv6,
# while eth2 splits them (`tag2-v4` / `tag2-v6`) so the e2e suite
# can verify that the module can either combine or distinguish
# families per device.
#
# Mgmt/direct traffic hits a separate server block on port 9180 —
# a clean port split rather than a technical requirement; plain and
# device-tagged listens may share a port under the IP_PKTINFO model
# (see docs/user-guide.md).
load_module /usr/lib/nginx/modules/ngx_http_ipng_stats_module.so;
error_log stderr notice;
events {
worker_connections 128;
}
http {
ipng_stats_zone ipng:1m;
ipng_stats_flush_interval 500ms;
ipng_stats_default_source direct;
log_format tagged '$remote_addr src=$ipng_source_tag vip=$server_addr '
'"$request" $status $body_bytes_sent';
access_log /var/log/nginx/access.log tagged;
# Global logtail — fires for ALL requests regardless of server block.
# The if= condition suppresses /notfound from the logtail stream.
map $request_uri $logtail_enabled {
~^/notfound 0;
default 1;
}
log_format ipng_stats_logtail '$host\t$remote_addr\t$request_method\t$request_uri\t'
'$status\t$body_bytes_sent\t'
'$ipng_source_tag\t$server_addr\t$scheme';
ipng_stats_logtail ipng_stats_logtail udp://127.0.0.1:9514 buffer=4k flush=500ms if=$logtail_enabled;
# Three server blocks that all pull in the same listen include —
# mirrors the real-world pattern where every site-*.conf has the
# same `include listens.conf;`. The wrapper must:
# * invoke nginx's listen handler exactly once per (server, addr)
# pair, so each server block gets its own cscf attached but no
# server block triggers nginx's "duplicate listen options"
# check;
# * dedup bindings globally on (sockaddr, device), so init_module
# creates exactly four sockets here (two families × two
# devices) rather than 3 × 4 = 12.
# The default server owns the locations used by the traffic tests;
# the two extras exist only to exercise the shared-include pattern.
server {
include /opt/config/ipng-listens.inc;
server_name _;
location / {
return 200 "ok $server_addr\n";
}
location /notfound {
return 404 "nope\n";
}
location /slow {
proxy_pass http://127.0.0.1:29080/;
}
}
server {
include /opt/config/ipng-listens.inc;
server_name extra-a.test;
location / { return 200 "a\n"; }
}
server {
include /opt/config/ipng-listens.inc;
server_name extra-b.test;
location / { return 200 "b\n"; }
}
server {
# Direct (mgmt) traffic: no device binding on the listen,
# `ipng_stats_default_source direct;` therefore tags it "direct".
# Separate port so it doesn't collide with the device-tagged
# wildcards above.
listen 172.20.40.2:9180;
server_name _;
location / {
return 200 "ok direct\n";
}
}
server {
listen 172.20.40.2:9113;
location = /.well-known/ipng/statsz {
ipng_stats;
allow all;
}
}
}