Implement the MH FMIPv6 fast-handover messages and options - #383
Merged
Merged
Conversation
First tranche of the MH work the Help Wanted page asks for, taking message
dispatch from 8/24 to 14/24 and options from 17/71 to 20/71.
Messages, per RFC 5568 unless noted: 8 Fast Binding Update, 9 Fast Binding
Acknowledgment, 10 Fast Neighbor Advertisement (RFC 4068, deprecated by 5568),
11 Experimental (RFC 5096), 14 Handover Initiate and 15 Handover Acknowledge.
Options: 18 Experimental, 21 Binding Authorization Data for FMIPv6, 34 Mobility
Header IPv6 Address/Prefix. Each has a read handler, a make counterpart, a
schema, a data model, dispatch registration and docs, and each is covered by a
byte-level RFC conformance case and a byte-identical round trip.
Four handover_* and handoff_* const enums that were generated but never
imported are now consumed.
Two value sets get enums local to this module rather than const plus a vendor
crawler, because RFC 5568 defines them inline and IANA registers neither:
FastBindingAcknowledgmentStatus (6.2.3) and IPv6AddressPrefixCode (6.4.2). The
first cannot reuse pcapkit.const.mh.status_code.StatusCode - 1 and 131 mean
different things in the two lists, so that would mislabel real packets. Both
carry the const modules' _missing_ handling so an unassigned value parses
instead of raising. Placement follows pcapkit/protocols/misc/pcapng.py, which
already defines two enums locally.
The schema fields stay UInt8Field: EnumField needs its namespace at class-body
time and the schema module cannot import the protocol module, which imports it,
so the enum is applied when the data model is built, as pcapng does.
Not implemented, deliberately: the three remaining CGA extensions are RFC 4581
experimental code points with no defined layout, so the existing opaque handler
is already the faithful reading. BADF's length field follows RFC 5568's literal
wording, which excludes the SPI and contradicts RFC 6275's generic rule.
Also fixes two typos in the class docstring ("og", "resgitered").
There was a problem hiding this comment.
🟢 Approval recommended
The implementation is consistent with existing MH patterns and is backed by detailed RFC-based and round-trip tests, with only minor documentation wording to consider.
Pull request overview
This PR extends PyPCAPKit’s Mobility Header (MH) support by implementing additional FMIPv6 (and related experimental) MH message types and mobility options, including full read/make symmetry plus documentation and unit tests.
Changes:
- Added MH dispatch + schema + data-model + constructor support for FMIPv6 messages (FBU/FBack/FNA/HI/HAck) and Experimental Mobility Header (EMH).
- Added MH mobility option support for Experimental Mobility Option, BADF, and Mobility Header IPv6 Address/Prefix.
- Added comprehensive unit tests (wire-format conformance + round-trip byte identity + local-enum coverage) and updated Sphinx docs to include the new APIs.
File summaries
| File | Description |
|---|---|
| tests/protocols/internet/test_mh_unit.py | Adds FMIPv6/EMH message+option unit tests, including RFC wire-format and round-trip coverage. |
| pcapkit/protocols/schema/internet/mh.py | Introduces new MH message/option schemas and related flag TypedDicts. |
| pcapkit/protocols/internet/mh.py | Implements new MH message/option readers & makers, registers dispatch, and adds two module-local enums. |
| pcapkit/protocols/data/internet/mh.py | Adds corresponding data models and type annotations for the new messages/options. |
| docs/source/pcapkit/protocols/internet/mh.rst | Documents the new message/option handlers, schemas, data models, and local enums. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This was referenced Sep 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First tranche of the MH work the Help Wanted page asks for. Takes message dispatch from 8/24 to 14/24 and mobility options from 17/71 to 20/71.
What is implemented
Messages, per :rfc:
5568unless noted:Options: 18 Experimental (RFC 5096 §4), 21 Binding Authorization Data for FMIPv6 (§6.4.5), 34 Mobility Header IPv6 Address/Prefix (§6.4.2 + erratum 1816).
Types 14 and 15 were added beyond the obvious 8–11 because they are the other half of RFC 5568's message set, and they are what the four already-generated
handover_*/handoff_typeconst enums exist for — those were imported but never consumed until now.Each type gets a read handler and a make counterpart, a schema, a data model, dispatch registration and docs, keeping the codebase's read/make invariant intact (verified programmatically: zero orphans on either side).
The two local enums, and why they are local
The project's rule is that registry-derived enums live in
pcapkit/const/<proto>/with apcapkit/vendor/crawler, and value sets with no registry stay in the protocol module.pcapkit/const/mh/already holds 43 crawler-generated enums, so this tranche adds none there. But two value sets RFC 5568 defines inline have no IANA registry, and "no registry" means keep the enum in the module, not use a bare int:FastBindingAcknowledgmentStatus(§6.2.3). It deliberately does not reusepcapkit.const.mh.status_code.StatusCode: value1means "NCoA invalid" here but "prefix discovery necessary" there, and131means "incorrect interface identifier length" here but "home registration not supported" there. Typing the field asStatusCodewould mislabel real packets.IPv6AddressPrefixCode(§6.4.2), codes 1–4.Both carry the const modules'
_missing_handling, so an unassigned value in a wild capture parses toUnassigned_Ninstead of raising. Placement followspcapkit/protocols/misc/pcapng.py, which already definesPacketDirection/PacketReceptionlocally — though that precedent uses bareenum.IntEnumwith no unassigned handling, so this combines pcapng's placement with the const modules' robustness.One deviation worth a reviewer's eye: the schema fields stay
UInt8Fieldrather thanEnumField.EnumFieldneeds its namespace class at class-body time, and the schema module cannot import the protocol module — the protocol module imports the schema module, so it is a hard cycle. The enum is applied when the data model is built, which is exactly the split pcapng uses, and both class docstrings record why.Deliberately not implemented
Exp_FFFD/FFFE/FFFF, RFC 4581 experimental code points with no defined layout. The existing opaque handler already is the faithful reading; implementing them would mean inventing a wire format.OptionFieldadvances by bytes actually consumed; the total is reported aslength + 6.statusand the option-34codeare typed as the new local enums rather than shared registries, per above.Tests
5 tests / 21 subtests added, in three layers:
1105 08 00 1234 | 1234 d000 000a | 0310 <addr> | 150c deadbeef→seq=0x1234, ack/home/key_mngt set, lla_compat clear, lifetime 40 s, BADF spi0xdeadbeef). Each asserted 8-octet aligned.make, parsed withread, rebuilt from the parsed data model and asserted byte-identical to the original.makeaccepts member / bare int / member-name.Plus a regression test for bit-independent flag packing.
Full suite: 508 passed, 4 skipped, 315 subtests passed — exactly
mainplus this tranche, nothing else moved.Remaining MH gap, for whoever takes the next tranche
10 message types (12 Home Agent Switch, 13 Heartbeat, 16 Binding Revocation, 17/18 Localized Routing, 19/20 Update Notification, 21 Flow Binding, 22/23 Subscription) and 51 options (17, 19, 20, 22–33, 35–70). The PMIPv6 cluster (RFC 5213, options 22–27) is the natural next one — self-contained, and
handoff_type/access_typeare already generated for it.Two MH defects found while working here are filed separately and not fixed in this PR: #354 (
_make_opt_padgrows aPadNby two octets per round trip) and #355 (aPad1option crashes parsing withstruct.error). The round-trip tests here are padding-free by construction because of them, noted in a comment.