BFD (Bidirectional Forwarding Detection) control packet encoding and decoding — mandatory section only (RFC 5880 section 4.1).
A BFD control packet opens with a fixed 24-byte mandatory section. RFC 5880
also defines an optional authentication section that follows it when the
authenticationPresent flag is set, but this coder does not model it — see
"Scope" below.
0 7 8 15 16 23 24 31 +--------+--------+--------+--------+ |Ver/Diag| Flags | DetMult| Length | +--------+--------+--------+--------+ | | | My Discriminator | +--------+--------+--------+--------+ | | | Your Discriminator | +--------+--------+--------+--------+ | | | Desired Min TX Interval | +--------+--------+--------+--------+ | | | Required Min RX Interval | +--------+--------+--------+--------+ | | | Required Min Echo RX Interval | +-----------------------------------+
The first byte packs a 3-bit version and 5-bit diagnostic code; the
second byte packs the 2-bit session state and five single-bit flags
(poll, final, controlPlaneIndependent, authenticationPresent,
demand, multipoint — six flags plus 2-bit state is 8 bits). Both bytes
are exposed as nested objects via bitStruct, keeping the on-wire layout
faithful while preserving named-field access.
Scope (v0.0.1)
This package covers only the 24-byte mandatory section:
- No authentication section — when
flags.authenticationPresentis set, the caller is responsible for the bytes that follow the mandatory section; this coder neither reads nor writes them. - No checksum, no compression, no crypto — BFD control packets carry none of these, so there is nothing to add.
- Interval fields (
desiredMinTxInterval,requiredMinRxInterval,requiredMinEchoRxInterval) are surfaced as raw microsecond counts, not refined intoTemporal/Durationvalues — that conversion is left to the caller.
Round-trip a BFD Up control packet
Round-trip a BFD Up control packet
import { assertEquals } from "@std/assert"; import { bfdControlPacket, BFD_CONTROL_SIZE, BFD_STATE } from "@binstruct/bfd"; const coder = bfdControlPacket(); const packet = { versionDiagnostic: { version: 1, diagnostic: 0 }, flags: { state: BFD_STATE.UP, poll: 0, final: 0, controlPlaneIndependent: 0, authenticationPresent: 0, demand: 0, multipoint: 0, }, detectMultiplier: 3, length: BFD_CONTROL_SIZE, myDiscriminator: 0x11111111, yourDiscriminator: 0x22222222, desiredMinTxInterval: 1_000_000, requiredMinRxInterval: 1_000_000, requiredMinEchoRxInterval: 0, }; const buffer = new Uint8Array(BFD_CONTROL_SIZE); const written = coder.encode(packet, buffer); const [decoded, read] = coder.decode(buffer); assertEquals(written, BFD_CONTROL_SIZE); assertEquals(read, BFD_CONTROL_SIZE); assertEquals(decoded.flags.state, BFD_STATE.UP); assertEquals(decoded.myDiscriminator, 0x11111111);