VLAN - 802.1Q/802.1ad VLAN Tag Types

pcapkit.protocols.link.vlan.protocol contains VLAN only, an abstract base class holding the tag layout shared by every VLAN tag [*]. The concrete tags live in packages of their own:

EtherType

Class

0x8100 (customer tag, 802.1Q)

C_Tag

0x88A8 (service tag, 802.1ad)

S_Tag

The tag structure, keyed as for a customer tag (a service tag’s keys start s_tag), is:

Octets

Bits

Name

Description

0

0

c_tag.tci

Tag Control Information

0

0

c_tag.tci.pcp

Priority Code Point

0

3

c_tag.tci.dei

Drop Eligible Indicator

0

4

c_tag.tci.vid

VLAN Identifier

2

16

c_tag.type

Protocol (Internet Layer)

The two tags differ only in the tag protocol identifier (TPID) that selects them, which is not part of either tag but the EtherType field of whatever encapsulates it. Both read the same four octets with the parsing and construction code this base holds.

They are distinct classes, not one class bound at two EtherTypes, because 802.1ad stacks them: in a Q-in-Q frame the service tag’s next EtherType, 0x8100, selects a customer tag:

ethernet.type                = 0x88A8
ethernet.s_tag.tci.vid       = 100     <- service tag,  802.1ad
ethernet.s_tag.type          = 0x8100
ethernet.s_tag.c_tag.tci.vid = 200     <- customer tag, 802.1Q
ethernet.s_tag.c_tag.type    = 0x0800

info_name – s_tag against c_tag – keeps the two apart in the parsed Info; one class would nest a c_tag inside a c_tag, leaving nothing to say which was the service tag.

Each tag has a package of its own because a package holds one protocol class, named after it, with only the framework bases in pcapkit.protocols.protocol exempt (#2529). This base is abstract, nothing dispatches to it, and it declares no __index__(), so its __index__ raises.

class pcapkit.protocols.link.vlan.protocol.VLAN(file=None, length=None, **kwargs)[source]

Bases: Link[VLAN, VLAN]

Abstract base class for 802.1Q/802.1ad VLAN tag types.

The class implements the whole of the tag – both parsing and construction – since the customer and service tags are byte-for-byte identical. What it deliberately leaves to its subclasses is only how the tag names itself: name, alias and info_name.

It is abstract for the same reason IP is: name is declared abstract by ProtocolBase and is not defined here, so the class cannot be instantiated. Bind C_Tag or S_Tag, never this class.

Changed in version 1.5.0: Became an abstract base. The 802.1Q customer tag it implemented, with its name, alias and info_name, moved to C_Tag.

Changed in version 1.6.0: pcp and type of make() each take a member or an int code, resolved with the enumeration’s get, and so does the pcp of its tci; a name, a bool, or a code the field cannot carry raises ProtocolError, rather than resolving against an enumeration inferred from the caller’s frame or writing a different value (#2594).

Removed in version 1.6.0: The pcp_default, pcp_namespace, pcp_reversed, type_default, type_namespace and type_reversed arguments of make(); resolve a name with resolve_index() first (#2594).

property length: Literal[4]

Header length of current protocol.

property protocol: EtherType

Name of next layer protocol.

classmethod id()[source]

Index ID of the protocol.

Return type:

tuple[Literal['VLAN'], Literal['C_Tag'], Literal['S_Tag']]

Returns:

Index ID of the protocol – the family name, then every tag in it, as L2TP.id does for its own family. Note that unlike L2TP’s versions, the two tags are distinct protocols rather than flavours of one, so each is its own canonical name; they carry VLAN only as a secondary alias.

read(length=None, **kwargs)[source]

Read 802.1Q/802.1ad VLAN tag type.

Structure of 802.1Q/802.1ad VLAN tag type [IEEE 802.1Q]:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              TCI              |                               |
|-------------------------------|                               |
|  P  |D|                       |             Type              |
|  C  |E|          VID          |                               |
|  P  |I|                       |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Parameters:
  • length (int | None) – Length of packet data.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

VLAN

Returns:

Parsed packet data.

make(tci=None, pcp=PriorityLevel.BE, dei=False, vid=0, type=EtherType.Internet_Protocol_version_4, payload=b'', **kwargs)[source]

Make (construct) packet data.

Parameters:
  • tci (TCI | TCIType | None) – TCI field; its pcp, dei and vid take the place of the arguments of those names when given.

  • pcp (PriorityLevel | int) – Priority Code Point (PCP) field.

  • dei (bool) – Drop Eligible Indicator (DEI) field.

  • vid (int) – VLAN Identifier (VID) field.

  • type (EtherType | int) – EtherType field.

  • payload (bytes | ProtocolBase | Schema) – Payload field.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

VLAN

Returns:

Constructed packet data.

Raises:

ProtocolError – If pcp, the pcp of tci, or type is a name, a bool, or a member or code its field cannot carry.

classmethod __index__()[source]

Numeral registry index of the protocol.

Raises:

UnsupportedCall – This protocol has no registry entry.

Return type:

NoReturn

classmethod _make_data(data)[source]

Create key-value pairs from data for protocol construction.

Parameters:

data (VLAN) – protocol data

Return type:

dict[str, Any]

Returns:

Key-value pairs for protocol construction.

Header Schemas

Removed in version 1.6.0: pcapkit.protocols.schema.link.vlan, with no alias: the module moved here (#2534).

Both tags share these, since their layouts are identical.

class pcapkit.protocols.link.vlan.schema.VLAN(tci=NO_VALUE, type=NO_VALUE, payload=NO_VALUE, *, __packet__=None, **kwargs)[source]

Bases: Schema

Header schema for an 802.1Q/802.1ad VLAN tag.

tci: TCIType = <BitField tci>

Tag control information.

type: EtherType = <EnumField type>

EtherType.

payload: bytes = <PayloadField payload>

Payload.

class pcapkit.protocols.link.vlan.schema.TCI(pcp=NO_VALUE, dei=NO_VALUE, vid=NO_VALUE, *, __packet__=None, **kwargs)[source]

Bases: Schema

Header schema for 802.1Q/802.1ad VLAN tag control information.

pcp: PriorityLevel = <EnumField pcp>

Priority code point.

dei: int = <UInt8Field dei>

Drop eligible indicator.

vid: int = <UInt16Field vid>

VLAN identifier.

Type Stubs

class pcapkit.protocols.link.vlan.schema.TCIType[source]

Bases: TypedDict

Type of 802.1Q/802.1ad VLAN tag control information.

pcp: int

Priority code point.

dei: int

Drop eligible indicator.

vid: int

VLAN identifier.

Data Models

Removed in version 1.6.0: pcapkit.protocols.data.link.vlan, with no alias: the module moved here (#2534).

class pcapkit.protocols.link.vlan.data.VLAN(tci, type)[source]

Bases: Protocol

Data model for an 802.1Q/802.1ad VLAN tag.

tci: TCI

Tag control information.

type: EtherType

Protocol (Internet Layer).

class pcapkit.protocols.link.vlan.data.TCI(pcp, dei, vid)[source]

Bases: Data

Data model for tag control information.

pcp: PriorityLevel

Priority code point.

dei: bool

Drop eligible indicator.

vid: int

VLAN identifier.

Footnotes