Skip to content

feat(internet): add IGMPv1/IGMPv2 as concrete classes over an abstract base - #2444

Merged
JarryShaw merged 5 commits into
mainfrom
feat-igmp-v1-v2-2439
Oct 31, 2026
Merged

JarryShaw merged 5 commits into
mainfrom
feat-igmp-v1-v2-2439

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

Test plan

  • tests/protocols/internet/test_igmp_unit.py, tests/protocols/test_dispatch_registry_unit.py: 40 passed, 169 subtests
  • IGMP modules: 100% line and branch coverage
  • examples/generators/make_samples.py runs clean
  • isort clean on changed files; internet.py fails isort on main as well
  • pylint on igmp.py: C0301, R0913/R0917 on make, W0622 on _classify's type
  • Full suite not run; CI pending

@github-actions github-actions Bot added this to the PyPCAPKit v1.5 milestone Oct 30, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 30, 2026
@JarryShaw JarryShaw added feat Pull requests that add a new capability (feat: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 30, 2026
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 94.47% (unit tier, Python 3.15, 9518f6957, 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 3070 24 1072 26 98.79%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 18424 195 4838 181 98.38%
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.

@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES (cross-review, different model from the author).

Required: (1) a plain # comment at igmp.py:131 uses the :issue: role instead of bare #2439, breaking tests/project/test_issue_refs_in_comments.py; (2) only types 0x11/0x12/0x16/0x17 are handled — a v3 Report, DVMRP or MRD message still decodes through the v1/v2 layout instead of falling back to Raw, giving a garbage group/max_resp_time; (3) versionadded:: 1.5.0 should read 1.6.0, and the PR has no 1.6.0 changelog bullet.

Should-fix: wrong :rfc:1112#section-4`` citation (the header is really Appendix I, not §4); checksum docstring wrongly says "8-octet message" for v2 (only v1 is 8 octets fixed); no IGMPv3 follow-up issue exists despite the PR describing one.

Type codes, field layout, checksum fixtures and protocol wiring for v1/v2 all independently confirmed correct. Relaying all three required fixes to the original agent.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 30, 2026
@JarryShaw
JarryShaw force-pushed the feat-igmp-v1-v2-2439 branch from 90169ae to 41b5735 Compare October 30, 2026 06:34
@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Oct 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

All required fixes applied and verified directly (new head 41b5735ef): plain #2439 instead of the :issue: role in a #-comment; a new _V1_V2_TYPES check raises ProtocolError for any non-v1/v2 type (IGMPv3 Report, DVMRP, etc.), falling back to Raw; versionadded corrected to 1.6.0 with a changelog bullet added. Should-fix items (RFC 1112 Appendix I citation, version-correct checksum wording) also applied. Spot-verified: 15 passed/12 subtests on the targeted regression tests. One item flagged back rather than fixed: the PR body claims an IGMPv3 follow-up issue exists when it doesn't — I'll address that directly rather than re-looping on it. Cross-review re-dispatched.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Auto-resolved conflict (standing rule): #2444 went CONFLICTING against origin/main because both this branch and main independently added docs/source/changelog/1.6.0.rst as new files — the branch's version replicated the header text by hand rather than inheriting it, so git saw an add/add conflict rather than a clean extension.

Old head 41b5735ef → new head d1e4b4e2f. Resolution: docs/source/changelog/1.6.0.rst took the branch's version (a strict superset — header text byte-identical to main's, plus the IGMP bullet); CHANGELOG.md was regenerated via util/changelog_md.py rather than hand-merged. Patch-id on every other file is unchanged (git patch-id --stable matches before/after). tests/project/test_changelog_md.py: 68 passed/45 subtests on the rebased tree.

Old head's CI was still early (only 2 check-runs posted, both non-failing) when this landed, so there's no completed-green state to bypass checks against — the rebase just needs its own CI run.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Round 2 verdict: substantively GOOD, one timing note.

The reviewer's one "blocker" (head not rebased onto main, CONFLICTING) was reviewed against head 41b5735ef — which I'd already superseded with a real rebase (to d1e4b4e2f, confirmed origin/main is now an ancestor) in a prior tick, before this review's results came back. Current head is already correctly rebased; that finding is moot.

All substantive checks passed: _V1_V2_TYPES matches RFC 1112 Appendix I/RFC 2236 §2.1 exactly; dispatch-to-Raw verified for 9 different non-v1/v2 message types including a v3 Report with real (non-zero) group records; checksum wording genuinely distinguishes v1 (8-octet) from v2 (whole payload); all 11 RFC citations now say Appendix I; tests/project/tests/const/tests/vendor: 2697 passed/36794 subtests, 0 new failures vs. main; no cross-PR registration collision.

Two should-fix items found: the RFC 1112 Appendix I citation has no working #appendix-I anchor on the rendered RFC (dead link); pep.rst wrongly says IGMP landed "ahead of wave 2" (it's part of wave 2) and cites the wrong issue for the v3 follow-up. Both relayed for a quick fix. Also: I've corrected #2448's body myself — the reviewer found my own issue text was wrong about v3 Queries (they share type 0x11 with v1/v2 and correctly decode with the extra octets as trailing Raw per RFC 2236 §2.5; the real v3 gap is the floating-point Max Resp Code encoding, now documented there instead).

Noted for later: all three sibling wave-2 PRs will conflict with this one on pep.rst/changelog text once any of them merges — whichever lands last needs a rebase with count-pins re-derived.

@JarryShaw
JarryShaw force-pushed the feat-igmp-v1-v2-2439 branch from d1e4b4e to ce2f5e6 Compare October 30, 2026 07:01
@JarryShaw

Copy link
Copy Markdown
Owner Author

Both should-fix items applied and verified directly (new head ce2f5e6df): all 11 RFC anchors now point at #page-11 (confirmed against the real datatracker page); pep.rst's "ahead of wave 2" corrected to "within wave 2" in both spots, and the follow-up issue cite corrected to #2448. With round 2's substantive findings already clean and the stale rebase concern resolved, this is GOOD TO GO at ce2f5e6df, pending CI.

@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 30, 2026
@JarryShaw
JarryShaw force-pushed the feat-igmp-v1-v2-2439 branch from ce2f5e6 to 63a93e7 Compare October 30, 2026 07:07
@JarryShaw

Copy link
Copy Markdown
Owner Author

Re-resolved the conflict (my own process gap this time, not the worker's): the previous fix-relay agent amended the branch inside the live worktree, which still held the pre-rebase history — my earlier out-of-band rebase (pushed from a separate scratch worktree) never got synced back into the live one, so that agent's force-push silently reverted it, and #2444 went CONFLICTING again.

Old head ce2f5e6df → new head 63a93e719, rebased directly in the live worktree this time so it stays in sync going forward. Resolution identical to before (git's rerere reused the recorded resolution): 1.6.0.rst takes the branch's superset version, CHANGELOG.md regenerated. tests/protocols/internet/test_igmp_unit.py + tests/project/test_changelog_md.py: 78 passed/57 subtests. origin/main confirmed an ancestor this time.

@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: good-to-go Cross-review at the current head says ready; CI state is separate review: running A cross-review is in flight against the current head - no verdict yet labels Oct 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Confirmed by direct diff: content at new head 63a93e719 is byte-identical to the already-approved ce2f5e6df outside the two conflict-resolution files, which carry the same resolution as before (verified by git rerere reusing the recorded pattern, plus a clean test run). Restoring GOOD TO GO without a fresh review round — nothing substantive changed.

@JarryShaw

Copy link
Copy Markdown
Owner Author

No, IGMP base class should never be instantiable.

@JarryShaw

Copy link
Copy Markdown
Owner Author

My reading of your 03:49Z comment: the IGMP base stays abstract and non-instantiable. The rework repoints the TransType.IGMP registry entry and the tests at the concrete IGMPv1/IGMPv2 classes, with version abstract on the base. Back to needs-changes; the fix round is dispatched.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Held: Actions queue at 50 (above the hold line). The rework dispatches when the queue drops below 40.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Member order is in scope for this rework. Group the class body as: properties, public methods (id, read, make, register_xxx), dunders (__index__, __length_hint__), then utilities (_read_xxx before its _make_xxx). Use the old protocols (IPv4, TCP, UDP, ARP) as the reference.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Rework pushed as 226a0685f: version is abstract on the base, IGMPv1 and IGMPv2 return 1 and 2, and the old _pinned/_version are gone.

Decision needed: TransType.IGMP now points at IGMPv2. That makes IGMPv1 messages on IP protocol 2 fall back to Raw. Which should the registry entry point at, and is the Raw fallback for IGMPv1 acceptable?

@JarryShaw

Copy link
Copy Markdown
Owner Author

hmm, in this case, sounds like we'd still need a dispatcher logic then.

@JarryShaw

Copy link
Copy Markdown
Owner Author

My reading of your 04:44Z comment: the IGMP registry entry needs dispatch logic to choose between IGMPv1 and IGMPv2, so the earlier no-dispatcher direction is reversed for this case. This is a rework: #2444 goes back to needs-changes, held until the Actions queue is below 40.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Held: Actions queue at 78 (well above the hold line). The dispatch rework dispatches when the queue drops below 40.

@JarryShaw

Copy link
Copy Markdown
Owner Author

My reading of your ruling: TransType does not distinguish IGMPv1, v2 and v3, so the IGMP base class carries the dispatcher that picks IGMPv1, IGMPv2 or IGMPv3 from the message. This is the design for this PR; the local rework follows it. Push held until the Actions queue is below 40.

@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO (Sonnet, da17ab0f2). IGMP() raises TypeError; v1 and v2 return 1 and 2; dispatch picks v1, v2 or Raw correctly end to end; 44 tests pass.

@JarryShaw

Copy link
Copy Markdown
Owner Author

id should be narrowed on v1//2 class but contains both on base class only

@JarryShaw

Copy link
Copy Markdown
Owner Author

My reading of your 05:51Z comment: id() narrows to its own name on IGMPv1 and IGMPv2, and the IGMP base alone keeps both. This is a rework, so #2444 goes back to needs-changes; the local fix is held until the Actions queue is below 40.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Local-only commit cd94291 forks from an older base and cannot fast-forward onto origin da17ab0; origin already carries the same IGMP changes. Blocker: the owner's dispatcher ruling. Not pushed.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Decision needed: IGMP dispatcher. Options: (a) the IGMP base carries the version dispatcher, as origin da17ab0 does now; (b) no dispatcher, use dynamic properties and log/error messages, per your 02:15Z comment. Recommendation: (a). TransType cannot tell IGMPv1, v2 and v3 apart, so the base has to dispatch. This also unblocks #2465 and #2448.

@JarryShaw

Copy link
Copy Markdown
Owner Author

take (a). IGMP is having a similar situation as HTTP, where we cannot tell the exact versions from the registered enum value, so a dispatch at the base class is required. but (b)'s work can be partly taken if applicable.

@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES (Sonnet, 43c8a7501). Reconciled against your 04:29Z ruling on member order: public methods include id, and the IGMP base has no id in its class body (pcapkit/protocols/internet/igmp.py, Methods at line 81 holds only read and make). Your 05:51Z ruling also says the base id must contain both versions, and v1/v2 narrow theirs. Required: add id to the base public methods, before read, returning both IGMPv1 and IGMPv2. The bool fix and dispatch are otherwise fine.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Hold, not pushed. The base id() fix is local commit 5d489369 on top of 43c8a7501. It is a fast-forward and will be pushed once the Actions queue drops below 20 (currently 23 queued). Sweep will push it then and re-review.

@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO (Sonnet, 5d489369). The commit only adds id to the IGMP base, before read, returning IGMP, IGMPv1 and IGMPv2. v1 and v2 still narrow theirs. Narrow tests on this head: 39 passed, 76 subtests. No const census or registry test calls id() on IGMP. The new base-id test was shown to fail on the previous head by the worker. Merge is yours.

…patch

- igmp.py: IGMP is abstract (version is an abstract property) and never
  instantiated. It holds the schema, data model, read and make; _classify
  places a message in a version (a Query is v1/v2 only at 8 octets). _dispatch
  picks IGMPv1 or IGMPv2 from the type and max response time, else Raw.
- internet.py: TransType.IGMP is registered against the IGMP base, and
  _next_layer_class dispatches it through IGMP._dispatch.
- igmpv1.py / igmpv2.py: concrete classes returning version 1 / 2; id() is the
  family and version, alias is dynamic from version.
- Schema, data model, IANA Type registry, docs, dispatch generator and tests
  added.
- igmp.py: make() checks type and max_resp_time in one loop and refuses
  bool for both, replacing the separate max_resp_time bool check.
- test_igmp_unit.py: make(type=True/False) raises ProtocolError.
- Add id() to the abstract IGMP base, in the Methods group before read(),
  returning ('IGMP', 'IGMPv1', 'IGMPv2'). The base previously inherited
  Protocol.id() and reported only ('IGMP',).
- IGMPv1 and IGMPv2 keep their narrowed ids.
- Test: the base id names both versions; each version narrows it.

Fails on 43c8a75 (base id), passes here. Narrow run:
pytest tests/protocols/internet -k igmp, 39 passed.
@JarryShaw

Copy link
Copy Markdown
Owner Author

Rebased onto main (487c91c67) after #2443/#2491 landed, new head e588dccac. Conflicts in pep.rst, pcapkit/all.py, and the dispatch-registry count test, all resolved by merging both sides. Patch-id of the IGMP implementation itself unchanged. Narrow tests: 39 passed, 76 subtests. Re-review needed.

An earlier rebase resolved pep.rst's conflicts by 'merging both sides'
and reintroduced stale text that main had already corrected, plus
left two broken cross-references:

- LINUX_SLL/LINUX_SLL2 were re-added to the Link Layer outstanding
  list even though main already removed them once #2438 landed, and
  a contradictory 'now implemented' clause was appended describing
  them as still outstanding one sentence earlier.
- IGMP stayed listed as outstanding on the Internet Layer and among
  the real-capture gaps, despite this PR implementing it.
- igmpv1.IGMPv1 and igmpv2.IGMPv2 don't exist; both modules export a
  class literally named IGMP. Fixed the cross-references to use
  explicit display text over the real igmpv1.IGMP/igmpv2.IGMP
  targets.

Verified: test_conventions_doc_claims.py passes clean (34 tests, 259
subtests); IGMP and dispatch-registry narrow tests unaffected (47
tests, 194 subtests).
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed 50ea421b2: fixed a botched pep.rst conflict resolution from the e588dccac rebase. 'Merging both sides' reintroduced stale text main had already corrected and left two broken cross-refs:

  • LINUX_SLL/LINUX_SLL2 re-added to the Link Layer outstanding list (main already dropped them once feat(link): implement LINUX_SLL and LINUX_SLL2 (the tcpdump -i any cooked-capture headers) #2438 landed), with a contradictory 'now implemented' clause appended right after.
  • IGMP still listed as outstanding (Internet Layer, and the real-capture-gaps sentence) despite this PR implementing it.
  • igmpv1.IGMPv1/igmpv2.IGMPv2 don't exist -- both modules export a class literally named IGMP. Fixed to explicit-display cross-refs over the real igmpv1.IGMP/igmpv2.IGMP targets.

Verified: test_conventions_doc_claims.py clean (34 tests, 259 subtests); IGMP and dispatch-registry narrow tests unaffected (47 tests, 194 subtests). Re-review owed on this head.

IGMP adds pcapkit/const/igmp/type.py, but the pin bumps across the 4
census test files were missing. Bumped: ints 117->118, enums
133->134, distinct modules 127->128 (test_const_enum_builtin_parity);
enums 123->124, covered 120->121 (test_const_enum_get); enums
117->118 (test_const_enum_lookup); all_files 127->128, generated
110->111 (test_const_registry_protocol).

Verified: tests/const/, tests/vendor/, test_igmp_unit.py,
test_dispatch_registry_unit.py and test_conventions_doc_claims.py all
pass clean (661 tests, 27092 subtests).
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review (Sonnet) at 50ea421b2: pep.rst fix and implementation both confirmed clean against RFC 1112/2236 -- only issue was census pins (igmp/type.py is a new const module, pins weren't bumped). Pushed 9518f6957: bumped all 7 affected assertions across the 4 census files (including generated, which the review's count missed). Verified: tests/const/, tests/vendor/, test_igmp_unit.py, test_dispatch_registry_unit.py, test_conventions_doc_claims.py all pass clean -- 661 tests, 27092 subtests. Re-review owed on this head.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review (Sonnet) at 9518f6957: GOOD TO GO. Diff since the last round touches only the 4 census test files, exactly +1 each (new igmp/type.py const module). Verified independently: real const-file count is 128 (main is 127), matching the pin; generated moves 1:1 with all_files since this PR doesn't touch the CONVERTED/EXCLUDED sets. Full suite clean -- 661 tests, 27092 subtests. Ready for merge -- your call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant