Skip to content

feat(link): add GRE dissector for IPGRE/IP6GRE on LINUX_SLL/SLL2 - #2508

Merged
JarryShaw merged 3 commits into
mainfrom
feat/2501-gre-dissector
Nov 1, 2026
Merged

JarryShaw merged 3 commits into
mainfrom
feat/2501-gre-dissector

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

Part of #2460.

What

LinuxSLL/LinuxSLL1/LinuxSLL2 fell back to Raw for the IPGRE (778)
and IP6GRE (823) arphrd_type values. This adds
pcapkit.protocols.link.gre.GRE, dissecting the Generic Routing
Encapsulation base header (RFC 2784) plus the optional Key and Sequence
Number extensions (RFC 2890), and wires LinuxSLL's shared
_import_next_layer to dispatch both ARPHRD_IPGRE and ARPHRD_IP6GRE
to this one class.

Why one class, two bindings

IPGRE and IP6GRE both land on the same GRE header — the "IP" vs "IP6" in
the arphrd_type name is about which IP version the Linux kernel's GRE
tunnel interface carries on its outer layer (i.e. which arphrd_type
fired), not a different GRE header shape. The GRE framing itself is
identical either way, so this is one dissector bound at two arphrd_type
values, exactly as #2460 scoped it.

What the dissector covers

The base header (RFC 2784 §2.1): a C/Reserved0/Ver flags-and-version
word, then a 16-bit Protocol Type (an EtherType). When C is set, a
Checksum/Reserved1 pair follows (§2.5-2.6). RFC 2890 §2 carves K (Key
Present) and S (Sequence Number Present) out of Reserved0, each gating
its own 4-octet field — so the header is 4, 8, 12 or 16 octets depending on
which of C/K/S are set.

The Protocol Type field dispatches onward as an EtherType through
Link.__proto__, the same family registry Ethernet, VLAN and LinuxSLL
already share — exactly as VLAN resolves its own type field. Unlike
FRAD (keyed by NLPID, not an EtherType), GRE therefore keeps no registry
of its own.

A nonzero Version Number (RFC 2637's "Enhanced GRE"/PPTP, version 1, a
different and incompatible header layout) is refused rather than misread.

Not implemented: per-family interpretation of the Key/Sequence Number
values — recorded but not interpreted further, since their meaning is a
matter for the tunnel endpoints, not something a passive dissector can
resolve from the header alone.

Registration

Registered in all 8 places: pcapkit/__init__.py, pcapkit/all.py,
pcapkit/protocols/__init__.py, pcapkit/protocols/data/__init__.py,
pcapkit/protocols/data/link/__init__.py, pcapkit/protocols/link/__init__.py,
pcapkit/protocols/schema/__init__.py, pcapkit/protocols/schema/link/__init__.py.

Tests

  • tests/protocols/link/test_gre_unit.py (new): 17 tests / 42 subtests —
    base header dispatch (IPv4/IPv6), each optional field individually and
    together (longest 16-octet form), reserved-bit round trips, the nonzero-
    version refusal, make()/read() round trips, and make() validation.
  • test_linux_sll1_unit.py/test_linux_sll2_unit.py: moved IPGRE/IP6GRE
    out of the "kept raw" sweep, added an explicit GRE-dispatch test to each.
  • test_short_read_roundtrip_unit.py: a GRE case (longest form, all three
    optional fields) added to the cut-at-every-offset sweep.
  • tests/project/test_rfc_constants_one_home_1739_unit.py: four entries
    added for literals that collide with homed constants by value but mean
    something unrelated (GRE's own header-length/field-width/bit-span
    literals), following the FRAD/Netlink precedent.

Counts: new test file 17 passed / 42 subtests; tests/protocols/link/
170 passed / 922 subtests; tests/protocols/test_short_read_roundtrip_unit.py
9 passed / 1390 subtests; tests/project/ full run 2132 passed, 80 skipped,
10619 subtests, 0 failed. pylint 10.00/10 and mypy clean on every
touched/new pcapkit/ file (verified: 110 pre-existing pcapkit/vendor/
mypy errors are identical on bare main, unrelated to this change).

Changelog & docs

Entry in docs/source/changelog/1.6.0.rst, CHANGELOG.md regenerated
(util/changelog_md.py --check clean), new docs page
docs/source/pcapkit/protocols/link/gre.rst indexed in the link-layer
toctree.

Scope

Two of #2460's five arphrd_type follow-ups remain: IEEE80211_RADIOTAP
(#2502) and FRAD (#2499, already its own PR). NETLINK has its own PR,
#2507. This PR does not close #2460.

Part of #2460.

- Add pcapkit.protocols.link.gre.GRE, dissecting the RFC 2784 base header
  (C/Reserved0/Ver/Protocol Type, plus optional Checksum/Reserved1) and the
  RFC 2890 Key/Sequence Number extensions, gated by the C/K/S flag bits.
- Wire LinuxSLL/LinuxSLL1/LinuxSLL2 to dispatch both ARPHRD_IPGRE and
  ARPHRD_IP6GRE to this one class -- same GRE framing either way, the
  "IP"/"IP6" distinction being only which outer IP version the tunnel
  carries.
- Protocol Type dispatches onward as an EtherType through the shared
  Link.__proto__ registry (as VLAN/Ethernet do), so GRE keeps no registry
  of its own, unlike FRAD's NLPID-keyed one.
- Register in all 8 places; add docs page and changelog entry.

Build and tests: pylint 10.00/10, mypy clean on touched files; new
tests/protocols/link/test_gre_unit.py (17 passed/42 subtests);
tests/protocols/link/ (170 passed/922 subtests); tests/project/ full run
(2132 passed, 80 skipped, 10619 subtests, 0 failed).
@JarryShaw JarryShaw added feat Pull requests that add a new capability (feat: subject prefix) review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Oct 31, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 31, 2026
@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Oct 31, 2026
@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 31, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review (Sonnet) at aac4e2714: GOOD TO GO. Header layout confirmed against RFC 2890 §2 directly, including the conditional Checksum/Key/Sequence Number gating -- a real C+K+S probe round-tripped correctly, and a bogus version-1 header (the PPTP variant with a different layout) is correctly refused. EtherType dispatch confirmed to mirror VLAN/Ethernet's existing pattern via the shared Link.__proto__, no new registry. Both ARPHRD_IPGRE and ARPHRD_IP6GRE confirmed dispatching to the same class. All 8 registrations present. Test counts reproduced exactly: 179/2312 subtests on the link suite, 2132/10619 on the full tests/project/ run, 0 failures. PR body correctly says 'Part of #2460', not 'Closes'. No conflict markers. Ready for merge -- your call.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage: 94.48% (unit tier, Python 3.15, aac4e2714, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 19738 133 2642 120 98.85%
pcapkit/corekit 2605 74 818 37 96.52%
pcapkit/dumpkit 281 3 100 3 98.43%
pcapkit/foundation 3183 27 1110 31 98.65%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 18574 199 4892 184 98.36%
pcapkit/toolkit 924 36 334 10 95.55%
pcapkit/utilities 502 7 144 5 98.14%
pcapkit/vendor 4510 1888 1034 169 54.89%

Per-file detail: the coverage-html artifact of this run.

Copilot AI and others added 2 commits November 1, 2026 05:30
# Conflicts:
#	CHANGELOG.md
#	docs/source/changelog/1.6.0.rst
#	docs/source/pcapkit/protocols/link/index.rst
#	pcapkit/__init__.py
#	pcapkit/all.py
#	pcapkit/protocols/__init__.py
#	pcapkit/protocols/data/__init__.py
#	pcapkit/protocols/data/link/__init__.py
#	pcapkit/protocols/link/__init__.py
#	pcapkit/protocols/link/linux_sll.py
#	pcapkit/protocols/schema/__init__.py
#	pcapkit/protocols/schema/link/__init__.py
#	tests/protocols/link/test_linux_sll1_unit.py
#	tests/protocols/link/test_linux_sll2_unit.py

Co-authored-by: JarryShaw <15666417+JarryShaw@users.noreply.github.com>
# Conflicts:
#	CHANGELOG.md
#	docs/source/changelog/1.6.0.rst
#	pcapkit/__init__.py
#	pcapkit/all.py
#	pcapkit/protocols/__init__.py
#	pcapkit/protocols/link/__init__.py
#	pcapkit/protocols/link/linux_sll.py
#	tests/protocols/link/test_linux_sll1_unit.py
#	tests/protocols/link/test_linux_sll2_unit.py

Co-authored-by: JarryShaw <15666417+JarryShaw@users.noreply.github.com>
@JarryShaw
JarryShaw merged commit 574186e into main Nov 1, 2026
1 check passed
@JarryShaw
JarryShaw deleted the feat/2501-gre-dissector branch November 1, 2026 05:43
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Nov 1, 2026
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Pull requests that add a new capability (feat: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Dissectors for non-ethertype ARPHRD types on LINUX_SLL/SLL2 (NETLINK/IPGRE/IP6GRE/802.11 radiotap/FRAD)

2 participants