Skip to main content

VLAN Demux Deep Dive

Technical deep dive into the VLAN demultiplexer daemon.

Overview

abng-demux is a high-performance packet capture and VLAN interface creation daemon that dynamically creates QinQ VLAN sub-interfaces on-demand when subscriber packets arrive.

Packet Capture

AF_PACKET Socket

abng-demux uses AF_PACKET socket for raw packet capture:

socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

Advantages:

  • No IP address required on interface
  • Captures all frames at link layer
  • Supports BPF filtering at kernel level

BPF Filter

Kernel-level BPF (Berkeley Packet Filter) reduces CPU overhead by filtering at the socket level:

(ether[12:2] == 0x8100 or ether[12:2] == 0x88A8) and
(
(ether[16:2] == 0x8863) or
(udp and udp[6:2] == 67)
)

Filters for:

  • VLAN-tagged frames (802.1Q or 802.1ad)
  • PPPoE Discovery (ethertype 0x8863)
  • DHCP Discover (UDP port 67)

PACKET_AUXDATA

Kernel software VLAN acceleration strips outer VLAN tag into metadata. abng-demux enables PACKET_AUXDATA and uses recvmsg() to recover the stripped tag:

setsockopt(sock, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val))

When tp_vlan_tci is set in control message, the stripped tag is reinserted into the frame.

VLAN Parsing

Ethernet Header

Destination MAC (6 bytes)
Source MAC (6 bytes)
EtherType (2 bytes)

VLAN Tag

TPID (2 bytes): 0x8100 (802.1Q) or 0x88A8 (802.1ad)
TCI (2 bytes):
├─ Priority (3 bits)
├─ DEI (1 bit)
└─ VID (12 bits)

Multi-Level VLAN Nesting

abng-demux supports arbitrary VLAN nesting depth:

Frame: Ethernet → VLAN1 → VLAN2 → VLAN3 → Payload

Parsing algorithm:

  1. Start at offset 12 (after src/dst MAC)
  2. Read EtherType
  3. If VLAN (0x8100 or 0x88A8):
    • Extract VID
    • Move to next layer (offset += 4)
    • Repeat
  4. Stop when non-VLAN EtherType found

Interface Creation

Naming Convention

{trunk_interface}.{outer_vlan}.{stag}.{ctag}

Example:

eth1.111.500.100  (trunk=eth1, outer=111, stag=500, ctag=100)

Creation Process

  1. Check Existence — Verify interface doesn't already exist
  2. Create VLAN Interface — Use netlink to create VLAN interface
  3. Set Protocol — Set S-Tag protocol (802.1ad or 802.1q)
  4. Bring Up — Set interface to UP state
  5. Notify abngd — Send interface_created event via IPC

Uses rtnetlink crate to:

  • Create VLAN interfaces
  • Set interface state
  • Query interface properties

Safety Features

Rate Limiting

Maximum creation_rate_limit interfaces created per second (default 100).

Implemented via token bucket algorithm:

  • Tokens replenished at rate_limit per second
  • Each interface creation costs 1 token
  • If no tokens available, creation deferred

Packet Validation

Requires require_packets matching packets within require_window seconds before creating interface.

Prevents spurious interface creation from single corrupt frames.

Hard Limits

Maximum max_interfaces dynamic VLAN interfaces (default 50000).

Prevents resource exhaustion from unlimited interface creation.

Idle Cleanup

Background task runs every 60 seconds:

  1. Check each dynamic interface for active sessions
  2. Check traffic counters via ethtool
  3. If no sessions and no traffic for idle_timeout seconds:
    • Remove interface
    • Notify abngd

Performance Considerations

Packet Processing

  • BPF filter at kernel level reduces CPU overhead
  • PACKET_AUXDATA for VLAN tag recovery
  • Minimal copying of packet data

Interface Management

  • HashMap for O(1) interface lookup
  • Batch netlink operations where possible
  • Lazy interface creation (on-demand)

Memory Usage

  • One interface per subscriber (typical)
  • ~1KB per interface for kernel state
  • 50,000 interfaces ≈ 50MB memory

Troubleshooting

No VLAN Interfaces Created

Check 1: Demux Enabled

show configuration | match demux

Check 2: Trunk Interface Up

ip link show eth1

Check 3: Matching Packets

tcpdump -i eth1 -e 'ether[12:2] == 0x8100'

Check 4: Demux Logs

journalctl -u abng-demux -f

VLAN Interfaces Not Cleaned Up

Check 1: Idle Timeout

show configuration | match idle_timeout

Check 2: Active Sessions

show subscribers

Check 3: Interface Traffic

ethtool -S eth1.111.500.100

Too Many VLAN Interfaces

Check 1: Max Interfaces Limit

show configuration | match max_interfaces

Check 2: Stale Sessions

show subscribers

Next Steps