Skip to content

Commit 2f2594c

Browse files
committed
New post, Inside Infix. A brief architectural overview
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
1 parent aa85453 commit 2f2594c

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

_posts/2026-03-11-inside-infix.md

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
title: "Inside Infix"
3+
description: "Built on YANG, Built to Last"
4+
author: troglobit
5+
date: 2026-03-11 12:25:00 +0100
6+
categories: [architecture]
7+
tags: [design, architecture, yang, netconf, buildroot, sysrepo]
8+
image:
9+
path: /assets/img/architecture-overview.svg
10+
alt: Infix architecture overview showing the management stack
11+
show_in_post: false
12+
---
13+
14+
How does Infix work, what is it based on, and what is YANG? These are a
15+
few of the questions we get from time to time, and this time we will
16+
attempt to answer them. Let's dive in!
17+
18+
> If your questions are not answered here, please feel free to engage
19+
> with us in our [Discussion Forum][1] or join us on [Discord][2]!
20+
{: .prompt-info }
21+
22+
### Overview
23+
24+
Let's start by zooming out and identify the major components:
25+
26+
- *sysrepo:* the engine which all other major components connect to,
27+
funnels all actions to callbacks in *confd*
28+
- *netopeer2:* provides the NETCONF interface (XML over SSH) for
29+
external management
30+
- *rousette:* provides the RESTCONF interface (JSON over HTTPS) for
31+
external management, this is also where the upcoming WebUI will
32+
connect to, meaning the same WebUI can be used to manage all Infix
33+
devices on the LAN
34+
- *klish:* provides the built-in Command Line Interface (CLI)
35+
- *confd:* gets callbacks for all changes from *sysrepo* which is
36+
translated into C-library API calls, configuration file changes in
37+
`/etc`, and network interface setup calls to `iproute2`
38+
39+
![](/assets/img/architecture-overview.svg)
40+
_**Figure 1:** Infix Architecture Overview_
41+
42+
Infix runs on a [broad range of hardware][3] — from Raspberry Pi home lab
43+
boards and compact dual-port routers like the NanoPi R2S, through
44+
general-purpose ARM and RISC-V end devices such as the NXP i.MX8MP EVK
45+
and StarFive VisionFive2, all the way up to enterprise switch platforms
46+
like the Microchip SparX-5i. It also runs on x86_64, making it easy to
47+
spin up instances in Qemu or GNS3 for development and testing without
48+
any dedicated hardware. The same OS, the same tooling, the same
49+
management interfaces throughout.
50+
51+
From a bottom-up perspective, one of the critical design choices for
52+
switch platforms is to rely on Linux *switchdev* for switch silicon
53+
abstraction. It is what makes it possible to configure actual hardware
54+
switch cores using the common Linux bridge. Underneath switchdev sits
55+
DSA (Distributed Switch Architecture), a kernel sub-layer that models
56+
the individual ports and internal links of a switch chip and translates
57+
bridge operations into hardware-specific commands. All operations on the
58+
bridge are thus "offloaded" to the DSA driver, e.g., adding an interface
59+
to a bridge enables hardware switching on that port, and adding a VLAN
60+
enables VLAN filtering in the switch silicon. On platforms without a
61+
switch core, the same bridge model applies in software — the management
62+
interface is identical regardless of whether forwarding happens in
63+
silicon or in the kernel.
64+
65+
Unlike many other Linux-based network operating systems, Infix is not a
66+
flavor of OpenWRT. Instead it is built on top of the developer-friendly
67+
[Buildroot][0], tracking its long-term support (LTS) releases.
68+
Buildroot's LTS cadence is one release every two years (in February),
69+
each supported for three years, with quarterly stable releases in
70+
between. This provides a solid base and forms the majority of all Open
71+
Source packages. A few of those are locally upgraded by the Infix team,
72+
e.g., sysrepo and netopeer2, and another few are tailor made for Infix,
73+
e.g., `confd`.
74+
75+
### YANG
76+
77+
The real hero, however, is YANG.
78+
79+
YANG (RFC 6020/7950) is a data modeling language designed specifically
80+
for network devices. At its core, YANG lets you formally describe what
81+
configuration and state a device has — what knobs exist, what values
82+
they accept, how they relate to each other — in a machine-readable way.
83+
Think of it as a schema, but one that carries enough semantic weight for
84+
tools to do genuinely useful things with it automatically.
85+
86+
In Infix, the entire system is modeled in YANG. This has one profound
87+
consequence: every management interface — the CLI, NETCONF, RESTCONF,
88+
and the upcoming WebUI — is ultimately backed by the same models. There
89+
is no separate CLI grammar to maintain, no divergence between what the
90+
web interface can do and what NETCONF can do. When a new feature is
91+
added to YANG, it appears everywhere at once.
92+
93+
Infix follows industry-standard IETF models wherever they exist. So
94+
`ietf-interfaces`, `ietf-routing`, `ietf-ip`, and friends describe
95+
interfaces, routes, and addresses — the same models you would find on
96+
any standards-compliant device. Where no standard model exists, Infix
97+
defines its own, prefixed with `infix-`.
98+
99+
Here is a small, simplified excerpt to give a flavour of what a YANG
100+
module looks like. Real modules are larger, but the structure is
101+
always the same:
102+
103+
```yang
104+
container interface {
105+
leaf name {
106+
type string {
107+
length "1..15";
108+
pattern '[a-zA-Z][a-zA-Z0-9_-]*';
109+
}
110+
description
111+
"Interface name, e.g. eth0 or br0. Linux limits
112+
interface names to 15 characters.";
113+
}
114+
115+
leaf description {
116+
type string {
117+
length "0..64";
118+
}
119+
description "Human-readable interface label.";
120+
}
121+
122+
leaf enabled {
123+
type boolean;
124+
default true;
125+
description
126+
"Administrative state. Set to false to bring the
127+
interface down without removing its configuration.";
128+
}
129+
130+
leaf mtu {
131+
type uint16 {
132+
range "68..9000";
133+
}
134+
units "bytes";
135+
default 1500;
136+
description
137+
"Maximum transmission unit. Standard Ethernet is 1500
138+
bytes; jumbo frames typically go up to 9000.";
139+
}
140+
}
141+
```
142+
143+
The `pattern` on `name` is a regular expression — only valid Linux
144+
interface names are accepted. The `range` on `mtu` means a value of
145+
`42` is rejected before it ever reaches the device; the model itself
146+
is the contract. This is what makes *offline validation* possible: a
147+
configuration file can be checked against the loaded YANG modules at
148+
any point — on a developer's laptop, in CI, or in a management system
149+
— and any constraint violation is caught immediately, before anything
150+
is sent over the wire.
151+
152+
#### The CLI is generated from YANG
153+
154+
One of the most visible benefits is the CLI. *klish* generates the
155+
entire command hierarchy directly from the loaded YANG modules. This
156+
means `?` and `TAB` completion always reflect the actual model —
157+
if a node is in YANG, it is in the CLI; if it is not, it is not. There
158+
is no hand-written command parser to drift out of sync.
159+
160+
#### Datastores
161+
162+
*sysrepo* organises configuration into a set of datastores:
163+
164+
- `factory-config` — generated at first boot, holds per-device defaults
165+
such as a unique hostname and the correct number of ports; can be
166+
customised per product by OEMs
167+
- `failure-config` — also generated at boot; used when the system
168+
enters *Fail Secure Mode* to ensure the device remains accessible
169+
even if `startup-config` is broken
170+
- `startup-config` — created from `factory-config` if it does not yet
171+
exist; loaded as the active configuration on every boot
172+
- `running-config` — what is actually running right now; identical to
173+
`startup-config` at boot unless changes have been made since
174+
- `candidate-config` — a scratch space created from `running-config`
175+
when entering the configure context; changes here can be freely
176+
discarded with `abort` or committed with `leave`
177+
178+
The separation between `candidate` and `running` means you can stage a
179+
set of changes, inspect the diff, and apply them atomically — or throw
180+
them away without touching the live system.
181+
182+
### Immutable by Design
183+
184+
Infix runs from a read-only *SquashFS* root filesystem. There is
185+
nothing to corrupt, no package manager to leave the system in a
186+
half-upgraded state, and no way for a bad configuration to break the OS
187+
itself. Configuration lives separately in a writable partition, and the
188+
YANG datastore sits on top of that.
189+
190+
Software upgrades use an A/B partition scheme. A new image is written
191+
to the inactive slot while the system keeps running, and the bootloader
192+
is only pointed at the new slot once the write completes successfully.
193+
If the new image fails to boot, the system automatically falls back to
194+
the previous slot. Upgrades are therefore atomic: you either end up on
195+
the new version or the old one — never in between.
196+
197+
### Built for Continuous Testing
198+
199+
The same design choices that make Infix robust in production also make
200+
it straightforward to test thoroughly. Because *sysrepo* is the
201+
authoritative source of truth and configuration is fully decoupled from
202+
the OS, the Infix regression suite can push NETCONF configuration to a
203+
device under test (DUT), verify the resulting operational state via
204+
RESTCONF, and reset it to a known-good baseline — all without touching
205+
the filesystem directly and without any CLI scraping.
206+
207+
The test suite, *Infamy*, runs against both virtual topologies in Qemu
208+
and real physical hardware using identical test cases. Virtual
209+
topologies make it cheap to catch regressions early in development;
210+
physical runs ensure that hardware-specific paths — DSA offloads, WiFi,
211+
switch silicon — are exercised regularly.
212+
213+
This level of automation means Infix is not constrained to a fixed
214+
monthly release cadence. When a fix or feature is ready and passes the
215+
full suite, a release can go out the same day. The result is a project
216+
that moves quickly without sacrificing stability.
217+
218+
219+
### Wrapping Up
220+
221+
Three ideas run through everything described here. YANG gives the
222+
system a single source of truth that every interface — CLI, NETCONF,
223+
RESTCONF, WebUI — derives from automatically, and whose constraints
224+
catch mistakes before they reach a device. Buildroot gives it a
225+
stable, well-understood foundation that is easy to audit and extend.
226+
And the immutable, A/B filesystem means that neither a bad upgrade nor
227+
a broken configuration can leave a device in an unrecoverable state.
228+
229+
Together they add up to a system that is easier to manage at scale, easier
230+
to automate, and easier to trust in production — whether you are running
231+
it on a $35 Raspberry Pi or a data-centre switch.
232+
233+
If you want to go deeper, the [full documentation][4] covers every
234+
feature in detail. Questions and feedback are always welcome in the
235+
[Discussion Forum][1] and on [Discord][2]!
236+
237+
[0]: https://buildroot.org/lts.html
238+
[1]: https://github.com/orgs/kernelkit/discussions
239+
[2]: https://discord.gg/6bHJWQNVxN
240+
[3]: /posts/router-boards/
241+
[4]: https://www.kernelkit.org/infix/

assets/img/architecture-overview.svg

Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)