VXLAN (Virtual Extensible LAN) header encoding and decoding (RFC 7348).

VXLAN encapsulates an Ethernet frame inside a UDP datagram (destination port VXLAN_PORT by convention) behind an 8-byte header:

 0      7 8     15 16    23 24    31
+--------+--------+--------+--------+
|  Flags |           Reserved1      |
+--------+--------+--------+--------+
|   VNI (24 bits)          |Reserv2 |
+--------+--------+--------+--------+
|                                    |
|         Inner Ethernet Frame      |
|              (variable)           |
+------------------------------------+

The header is two 32-bit words:

  • Word 1: an 8-bit flags field followed by a 24-bit reserved1 field. VXLAN_FLAG_VALID_VNI (0x08) is the only flag bit RFC 7348 defines — the "I" (VNI valid) flag, which MUST be set on every VXLAN packet. The other 7 bits of flags and all of reserved1 are reserved and MUST be transmitted as zero, ignored on receipt.
  • Word 2: a 24-bit vni (VXLAN Network Identifier) field followed by an 8-bit reserved2 field, also reserved and MUST be zero.

Following the header is the encapsulated inner Ethernet frame, consuming the rest of the buffer.

Scope for v0.0.1 is deliberately shallow: this coder covers the 8-byte header only. innerFrame is surfaced as a raw byte slice — pair it with @binstruct/ethernet to parse it further. Nothing is validated on decode (a stray flag bit or non-zero reserved field decodes verbatim rather than throwing), and nothing beyond the header — no VTEP discovery, no multicast/BGP EVPN control plane — is in scope.

Examples

Round-trip a VXLAN header wrapping a tiny inner frame

import { assertEquals } from "@std/assert";
import { vxlanHeader, VXLAN_FLAG_VALID_VNI } from "@binstruct/vxlan";

const coder = vxlanHeader();
const innerFrame = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
const packet = {
  flagsReserved1: { flags: VXLAN_FLAG_VALID_VNI, reserved1: 0 },
  vniReserved2: { vni: 42, reserved2: 0 },
  innerFrame,
};

const buffer = new Uint8Array(64);
const written = coder.encode(packet, buffer);
const [decoded, read] = coder.decode(buffer.subarray(0, written));

assertEquals(written, read);
assertEquals(decoded.flagsReserved1.flags, VXLAN_FLAG_VALID_VNI);
assertEquals(decoded.vniReserved2.vni, 42);
assertEquals(decoded.innerFrame, innerFrame);