Linx.Netlink.Codec (Linx v0.1.0)

Copy Markdown View Source

A small DSL for defining netlink message codecs.

Every netlink message body has the same shape — a fixed C-struct header followed by a stream of type-length-value attributes. A module that uses this one declares that shape in a codec block, and gets a struct plus an encode/1 and a decode/1 generated for it:

defmodule MyMessage do
  use Linx.Netlink.Codec

  codec do
    header do
      field :family, :u8
      pad 1
      field :index, :s32
    end

    attr 1, :name, :string
    attr 2, :mtu, :u32
  end

  # hand-written verbs may follow — the struct is already defined
end

encode/1 turns a %MyMessage{} into a message body; decode/1 turns a body back into a struct. Header fields default to 0; an attribute field is nil when absent, and a nil field is omitted on encode.

The whole definition is one codec block so the struct is defined right there, before any hand-written functions below it can refer to it.

This module is the reference codec backend: the generated encode/1 and decode/1 are thin wrappers over one shared engine driven by the declared schema. The schema is also exposed as data through the generated __codec__/0 — the seam a future kernel-YAML-driven front end would target.

Field and attribute types

Scalars :u8, :u16, :u32, :u64, :s8, :s16, :s32; :string (a NUL-terminated string); :binary (raw bytes).

The escape hatches

An attribute's type may also be:

  • a module that exports encode/1 and decode/1. Pointed at another Linx.Netlink.Codec module it covers a nested attribute set; pointed at a hand-written module it covers any value whose wire form a primitive cannot express.
  • a dispatch table: {:dispatch, :other_field, %{"k1" => Mod1, "k2" => Mod2, …}}. The sub-codec is chosen at encode and decode time from the current value of :other_field — a sibling attribute on the same struct. The dispatching field must be declared before the dispatched one, so its value is in hand by the time the latter is processed.

Both let the DSL handle the regular case and step aside, to module-level code, for the rest.

Summary

Functions

Declares a message codec: a header block of field/2 and pad/1 calls, and attr/3 declarations. Generates the struct, encode/1 and decode/1.

Functions

codec(list)

(macro)

Declares a message codec: a header block of field/2 and pad/1 calls, and attr/3 declarations. Generates the struct, encode/1 and decode/1.

A codec with no header block is a bare attribute set — the shape a nested attribute takes.