Skip to content

refactor(ipv6): rename IPv6_GenericExt to IPv6_Ext and make it the base for all 8 extension headers #917

Description

@JarryShaw

Follow-up to #904, on the owner's ruling. Verbatim:

My initial thought was to directly rename IPv6_GenericExt to IPv6_Ext, and use it as the base class and the unknown extension header's fallback parser.

and, approving the plan to do it here rather than inside #904:

Go

The change

Rename IPv6_GenericExt to IPv6_Ext (pcapkit/protocols/internet/ipv6_generic_ext.py → ipv6_ext.py), and make the one class serve both roles: the base every IPv6 extension header subclasses, and the concrete fallback parser for an RFC 6564-conforming header this library does not implement.

Re-parent all 8 members of the family, per the owner's earlier ruling on #891 that ESP joins because IANA marks it Y in the IPv6 Extension Header column:

IPv6_Route  IPv6_Frag  IPv6_Opts  HIP  MH        ->  subclass IPv6_Ext
AH                                                ->  AH(IPsec, IPv6_Ext)
ESP                                               ->  ESP(IPsec, IPv6_Ext)

Why one class is viable — measured, not assumed

The obvious objection is that IPv6_GenericExt.__index__ raises UnsupportedCall, because one instance stands in for many extension-header codes and a @classmethod has nowhere to put a per-instance value. That would be fatal for a base of six numbered headers — except every one of them defines __index__ on itself:

IPv6_Route  43    IPv6_Frag  44    IPv6_Opts  60
HIP        139    MH        135    AH         51        each `defined on` itself

So the raising member is shadowed everywhere and harms nothing. Same for name and alias, which each header declares as its own Literal. The class already carries the extension contract too: its payload and protochain return ... | NoReturn, the _extf guard shape AH has at ah.py:75,87,99.

What the merge costs, and the required mitigation

It removes a safety net for anything added later. A seventh extension header that forgets to override inherits concrete values and silently reports itself as "Generic IPv6 Extension Header" with alias IPv6-GenericExt, and __index__ raising instead of returning its number. Today's six are correct only because all six happen to shadow everything; nothing enforces it.

So this change must ship a test asserting that every IPv6_Ext subclass overrides name, alias and __index__, and that __index__ returns a real Enum_TransType rather than raising. That converts an invariant currently held by luck into one held by CI, and is the reason the merge is safe rather than merely tidy.

Blocked on #904

#904 adds the very file this renames, and holds esp.py and mh.py besides. Unblocks with:

gh pr view 904 -R JarryShaw/PyPCAPKit --json state -q .state   # MERGED

Landing this also unblocks #895, whose blocked label names the IPv6_Ext base as its blocker: ESP gains the extension-mode contract by construction once it subclasses the base, rather than by hand-writing the three _extf guards.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)refactorRestructuring for its own sake — neither a fix nor a new capability (refactor: prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions