Appendix 6.A PNP ABI Reference
Every name, value, offset and size in this appendix is generated from
pkm/uapi/pkm/pnp.h by pkm/tools/gen-pnp-abi.py, with struct
layouts measured by compiling a probe against the real header.
Regenerate it whenever the ABI changes; do not edit it by hand. The
names here are the ones a program actually compiles
against.
What a compiler cannot measure -- the device's read and poll semantics, what each ioctl expects, the error vocabulary, and the bounds that are not in the header -- is in the notes appendix, §6.B, which this generator does not touch.
6.A.1 Ioctl requests #
Request numbers on /dev/peios-pnp, packed as <linux/ioctl.h>
packs them (direction, argument size, type 'N', number).
| Constant | Value | Definition |
|---|---|---|
PEIOS_PNP_IOC_STATUS | 0x81604E01 | _IOR(PEIOS_PNP_IOC_TYPE, PEIOS_PNP_IOC_STATUS_NR, struct peios_pnp_status) |
PEIOS_PNP_IOC_COUNTERS | 0xC0184E02 | _IOWR(PEIOS_PNP_IOC_TYPE, PEIOS_PNP_IOC_COUNTERS_NR, struct peios_pnp_counters_query) |
PEIOS_PNP_IOC_FLOWS | 0xC0184E03 | _IOWR(PEIOS_PNP_IOC_TYPE, PEIOS_PNP_IOC_FLOWS_NR, struct peios_pnp_flows_query) |
6.A.2 Structure layouts #
Offsets and sizes are measured, not declared.
6.A.2.1 struct peios_pnp_event #
Total size 176 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 8 | __u64 | seq |
| 8 | 8 | __u64 | t_ns |
| 16 | 1 | __u8 | seat |
| 17 | 1 | __u8 | layer |
| 18 | 1 | __u8 | verdict |
| 19 | 1 | __u8 | flags |
| 20 | 1 | __u8 | direction |
| 21 | 1 | __u8 | addr_family |
| 22 | 1 | __u8 | protocol |
| 23 | 1 | __u8 | flow_state |
| 24 | 4 | __u32 | ifindex |
| 28 | 2 | __u16 | src_port |
| 30 | 2 | __u16 | dst_port |
| 32 | 2 | __u16 | ether_type |
| 34 | 1 | __u8 | reject_kind |
| 35 | 1 | __u8 | _pad0 |
| 36 | 16 | __u8[16] | src_addr |
| 52 | 16 | __u8[16] | dst_addr |
| 68 | 4 | __u32 | length |
| 72 | 4 | __u32 | effects |
| 76 | 96 | __u8[PEIOS_PNP_EV_ATTR_LEN] | attributed |
| 172 | 4 | __u32 | _pad1 |
6.A.2.2 struct peios_pnp_status #
Total size 352 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 8 | __u64 | abi |
| 8 | 8 | __u64 | generation |
| 16 | 8 | __u64 | enforcing |
| 24 | 8 | __u64 | events_dropped |
| 32 | 8 | __u64 | seen_ingress |
| 40 | 8 | __u64 | seen_egress |
| 48 | 8 | __u64 | seen_local_in |
| 56 | 8 | __u64 | deferred |
| 64 | 8 | __u64 | fallback_judged |
| 72 | 8 | __u64 | parse_errors |
| 80 | 8 | __u64 | judged |
| 88 | 8 | __u64 | permissive |
| 96 | 8 | __u64 | fail_closed |
| 104 | 8 | __u64 | verdict_pass |
| 112 | 8 | __u64 | verdict_drop |
| 120 | 8 | __u64 | verdict_reject |
| 128 | 8 | __u64 | reject_degraded |
| 136 | 8 | __u64 | fx_tags |
| 144 | 8 | __u64 | fx_counts |
| 152 | 8 | __u64 | fx_reports |
| 160 | 8 | __u64 | fx_prompts |
| 168 | 8 | __u64 | last_ingest_error |
| 176 | 8 | __u64 | last_ingest_t_ns |
| 184 | 8 | __u64 | tag_writes |
| 192 | 8 | __u64 | tag_untracked |
| 200 | 8 | __u64 | tag_refused |
| 208 | 8 | __u64 | count_writes |
| 216 | 8 | __u64 | count_key_absent |
| 224 | 8 | __u64 | count_refused |
| 232 | 8 | __u64 | reports_emitted |
| 240 | 8 | __u64 | counter_cells |
| 248 | 8 | __u64 | reporting_level |
| 256 | 8 | __u64 | seen_local_out |
| 264 | 8 | __u64 | flow_judged |
| 272 | 8 | __u64 | flow_cached |
| 280 | 8 | __u64 | flow_rejudged |
| 288 | 8 | __u64 | flow_expired |
| 296 | 8 | __u64 | flow_uncached |
| 304 | 8 | __u64 | refusals_emitted |
| 312 | 8 | __u64 | refusals_bypassed |
| 320 | 8 | __u64 | teardowns_emitted |
| 328 | 24 | __u64[3] | _reserved |
6.A.2.3 struct peios_pnp_counter_rec #
Total size 232 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 64 | __u8[PEIOS_PNP_COUNTER_NAME_LEN] | name |
| 64 | 8 | __u64 | hash |
| 72 | 1 | __u8 | keyspec |
| 73 | 1 | __u8 | family |
| 74 | 2 | __u8[2] | _pad0 |
| 76 | 4 | __s32 | ifindex |
| 80 | 16 | __u8[16] | src_addr |
| 96 | 16 | __u8[16] | dst_addr |
| 112 | 8 | __u64 | total |
| 120 | 8 | __u64 | last_secs |
| 128 | 4 | __u32 | n_windows |
| 132 | 4 | __u32 | _pad1 |
| 136 | 32 | __u32[PEIOS_PNP_COUNTER_MAX_WINDOWS] | window_secs |
| 168 | 64 | __u64[PEIOS_PNP_COUNTER_MAX_WINDOWS] | window_value |
6.A.2.4 struct peios_pnp_counters_query #
Total size 24 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 8 | __u64 | buf |
| 8 | 4 | __u32 | buf_len |
| 12 | 4 | __u32 | count |
| 16 | 4 | __u32 | total |
| 20 | 4 | __u32 | _pad0 |
6.A.2.5 struct peios_pnp_flow_rec #
Total size 288 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 4 | __u32 | id |
| 4 | 1 | __u8 | family |
| 5 | 1 | __u8 | protocol |
| 6 | 1 | __u8 | direction |
| 7 | 1 | __u8 | loopback |
| 8 | 1 | __u8 | seen_reply |
| 9 | 1 | __u8 | assured |
| 10 | 1 | __u8 | related |
| 11 | 1 | __u8 | judged |
| 12 | 4 | __s32 | ifindex |
| 16 | 4 | __u32 | timeout_secs |
| 20 | 16 | __u8[16] | src_addr |
| 36 | 16 | __u8[16] | dst_addr |
| 52 | 2 | __u16 | src_port |
| 54 | 2 | __u16 | dst_port |
| 56 | 1 | __u8 | icmp_type |
| 57 | 1 | __u8 | icmp_code |
| 58 | 1 | __u8 | n_tags |
| 59 | 5 | __u8[5] | _pad0 |
| 64 | 8 | __u64 | start_secs |
| 72 | 16 | __u64[2] | packets |
| 88 | 16 | __u64[2] | bytes |
| 104 | 16 | __u64[PEIOS_PNP_FLOW_SENTENCES] | sentence_generation |
| 120 | 16 | __s64[PEIOS_PNP_FLOW_SENTENCES] | sentence_expires_at |
| 136 | 16 | __u64[PEIOS_PNP_FLOW_SENTENCES] | sentence_rule_hash |
| 152 | 2 | __u8[PEIOS_PNP_FLOW_SENTENCES] | sentence_verdict |
| 154 | 2 | __u8[PEIOS_PNP_FLOW_SENTENCES] | sentence_reject_kind |
| 156 | 4 | __u8[4] | _pad1 |
| 160 | 64 | __u64[PEIOS_PNP_FLOW_MAX_TAGS] | tag_hash |
| 224 | 64 | __u64[PEIOS_PNP_FLOW_MAX_TAGS] | tag_value |
6.A.2.6 struct peios_pnp_flows_query #
Total size 24 bytes.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 8 | __u64 | buf |
| 8 | 4 | __u32 | buf_len |
| 12 | 4 | __u32 | count |
| 16 | 4 | __u32 | total |
| 20 | 4 | __u32 | _pad0 |
6.A.3 Constants #
Grouped as the header groups them.
PNP — Peios Network Policy: the verdict event stream and engine status.
The engine (net/pnp) judges every traversal at its standing seats and appends one event per evaluation to a bounded ring. /dev/peios-pnp (mode 0600; one reader at a time) drains it: read() returns whole events only — never a partial record — and blocks when the ring is empty unless O_NONBLOCK; poll() raises POLLIN when events are waiting. A slow reader loses the OLDEST events, and the loss is confessed in peios_pnp_status.events_dropped (the honesty rule: drops are counted, never silent).
Events are emitted for real evaluations (a published forest judged the traversal) and for fail-closed drops; permissive traversals (a layer with no forest — all of them at generation 0) emit nothing, because there is no decision to attribute. Status tells that story instead: generation 0 means "not enforcing", loudly.
This ABI is EXPERIMENTAL while PNP grows: no stability promise until the
design ships (PEI-598). Check abi before trusting the rest.
| Constant | Value |
|---|---|
PEIOS_PNP_ABI_VERSION | 3 |
Which standing seat judged the traversal.
| Constant | Value |
|---|---|
PEIOS_PNP_EV_SEAT_INGRESS | 1 |
PEIOS_PNP_EV_SEAT_EGRESS | 2 |
PEIOS_PNP_EV_SEAT_LOCAL_IN | 3 |
PEIOS_PNP_EV_SEAT_LOCAL_OUT | 4 |
| Constant | Value |
|---|---|
PEIOS_PNP_EV_LAYER_PACKET | 0 |
PEIOS_PNP_EV_LAYER_RAWPACKET | 1 |
PEIOS_PNP_EV_LAYER_FLOW | 2 |
The verdict, in strictness order.
| Constant | Value |
|---|---|
PEIOS_PNP_EV_VERDICT_PASS | 0 |
PEIOS_PNP_EV_VERDICT_REJECT | 1 |
PEIOS_PNP_EV_VERDICT_DROP | 2 |
The story a REJECT told (meaningful iff verdict == REJECT).
| Constant | Value | Notes |
|---|---|---|
PEIOS_PNP_EV_REJECT_REFUSED | 0 | RST / port-unreachable |
PEIOS_PNP_EV_REJECT_PROHIBITED | 1 | admin-prohibited |
| Constant | Value |
|---|---|
PEIOS_PNP_EV_DIR_IN | 0 |
PEIOS_PNP_EV_DIR_OUT | 1 |
Flow state as the snapshot carried it (0 = the fact was absent).
| Constant | Value |
|---|---|
PEIOS_PNP_EV_FLOW_ABSENT | 0 |
PEIOS_PNP_EV_FLOW_NEW | 1 |
PEIOS_PNP_EV_FLOW_ESTABLISHED | 2 |
PEIOS_PNP_EV_FLOW_RELATED | 3 |
PEIOS_PNP_EV_FLOW_INVALID | 4 |
PEIOS_PNP_EV_FLOW_UNTRACKED | 5 |
| Constant | Value | Notes |
|---|---|---|
PEIOS_PNP_EV_F_BACKSTOP | 0x01 | nothing yielded; DROP |
PEIOS_PNP_EV_F_FAIL_CLOSED | 0x02 | evaluation failed; DROP |
PEIOS_PNP_EV_F_REJECT_DEGRADED | 0x04 | REJECT emitted as DROP |
PEIOS_PNP_EV_F_REJUDGED | 0x08 | Flow: a stale sentence re-judged |
PEIOS_PNP_EV_ATTR_LEN | 96 |
One counter cell, as the counters dump reports it: the stream and key- spec of its table, the key it holds (only the facts the key-spec names are meaningful; the rest are zero), the cumulative total, and the value of every window the table answers.
| Constant | Value |
|---|---|
PEIOS_PNP_COUNTER_NAME_LEN | 64 |
PEIOS_PNP_COUNTER_MAX_WINDOWS | 8 |
| Constant | Value |
|---|---|
PEIOS_PNP_KEY_SRC_ADDR | 0x01 |
PEIOS_PNP_KEY_DST_ADDR | 0x02 |
PEIOS_PNP_KEY_INTERFACE | 0x04 |
One live flow, as the flows dump reports it (ABI 3): conntrack's view of the flow (original-direction tuple, state, remaining lifetime, accounting), PNP's extension (start time, the interface and direction at first judgment, the sentences, the tags). Tags are reported by hash; the policy names them.
| Constant | Value |
|---|---|
PEIOS_PNP_FLOW_MAX_TAGS | 8 |
PEIOS_PNP_FLOW_SENTENCES | 2 |
The flows dump: fills buf with as many records as fit; count is how
many were written, total how many live flows the walk saw. A best-
effort snapshot of a table that changes under the walk.
| Constant | Value |
|---|---|
PEIOS_PNP_IOC_TYPE | 0x0000004E |
PEIOS_PNP_IOC_STATUS_NR | 0x00000001 |
PEIOS_PNP_IOC_COUNTERS_NR | 0x00000002 |
PEIOS_PNP_IOC_FLOWS_NR | 0x00000003 |