External sources Linx draws on — kernel documentation, prior-art libraries in C and other languages, and the Elixir conventions that shaped the API. Anything cited in a moduledoc or referenced in a design discussion should appear here.

A living doc — add to it when new sources inform a decision.

The wire format Linx speaks and the message families it knows come from the kernel:

UAPI headers (the authoritative wire definitions; cited inline wherever a struct appears):

The kernel ships machine-readable descriptions of netlink protocols. The target of the future YAML-driven codegen path for genl families.

Prior-art C libraries

Studied for the layering Linx adopts (Socket → Message → Attr → Request → Codec → per-family resources):

  • libmnl — minimalistic netlink helpers; the model for Linx's pure-codec layer.
  • libnl — the larger object/cache library; the model for the high-level resource pattern. libnl-route adds typed object support around the core.
  • iproute2's libnetlink.crtnl_talk, rtnl_dump_filter. The reference C client.

Prior-art bindings in other languages

Cross-checked Linx's API shape against these:

  • vishvananda/netlink (Go) — top-level LinkAdd / AddrAdd / RouteAdd verbs plus an nl/ low-level split.
  • pyroute2 (Python) (docs) — the low-level IPRoute and high-level NDB. The schema-driven message classes (fields + nla_map) were the most interesting comparison point.
  • rust-netlink — the deliberate crate split (netlink-sys / netlink-packet-core / netlink-packet-route / netlink-proto / rtnetlink). The clearest layering reference; Linx's module groups mirror it.
  • Feuerlabs/netlink (Erlang) — the cautionary example: gen_server-IS-the-socket, twin hand-written codecs, dated C port driver. Its multicast-diff idea (subscribe to link / addr / route events) is genuinely useful and is the seed of the planned Linx.Netlink.Monitor — rebuilt as a clean layer on top of Connection, not baked into the socket.

Elixir conventions and ecosystem

The API shape — {:ok, _} | {:error, %Struct{}}, the ~IP sigil, error structs as defexception — follows what's established in modern Elixir.

Libraries that use {:error, %Struct{}}:

  • Ecto.Repo.insert/2{:error, %Ecto.Changeset{}}, the dominant Elixir error-struct pattern.
  • Req{:error, exception} (%Req.TransportError{}, %Req.HTTPError{}).
  • Jason{:error, %Jason.DecodeError{}}.
  • Postgrex{:error, %Postgrex.Error{}}.
  • Finch{:error, %Finch.HTTPError{} | %Finch.TransportError{}}.

  • Mint.TransportErrordefexception carrying a structured :reason.

Background reading on error-handling conventions: