[pve-devel] [RFC network/ve-rs 0/8] Template-based FRR config generation

Thomas Lamprecht thomas at lamprecht.org
Sat Oct 4 13:58:15 CEST 2025


Am 19.09.25 um 11:41 schrieb Gabriel Goller:
> Currently we generate the frr config by having a few rust-structs that look
> very similar to the literal frr config -- these structs then implement a custom
> trait similar to Display, which serializes the config into a String. This is
> not optimal due to multiple reasons, the main one being it's quite verbose and
> and the fact that we often mixed Display and FrrDump implementations. This
> means that sometimes structs are serialized using Display and sometimes using
> FrrDump. There is also the question of granularity, so does a single line
> correspond to a single FrrDump implementation? Or does every frr word
> correspond to an FrrDump implementation and a random one just adds a '
> '?
> 
> In order to clean this up a bit, there was an attempt at writing a full-fledged
> serde serializer, which takes structs and converts them into blocks and using
> nested enums as the options on every line. This turned out to be quite
> difficult and involved a lot of magic when creating the config in rust.
> Especially the ending statements (e.g. 'exit-address-family' when exiting an
> address-family block, but 'exit' when exiting a router block) turned out to be
> quite tricky.
> 
> The third and probably most popular way (Vyos and Sonic both use jinja
> templates as well) to generate frr config is to use templates. So you basically
> have rust-structs that look similar to the frr config and implement derive or
> implemennt serialize. Then we can use template files, which contain the whole
> configuration with every option wrapped in a `if` block and lists/blocks
> wrapped in `for` loops. Finally, we can use the rust structs to insert them into
> the templates and get the full frr config. The major downside of this approach
> is that the frr template files get quite complicated and can be a major source
> of config generation errors. A positive thing though, is that we don't need to
> model the whole frr config with every option and every property, we can easily
> wrap a few options into a single (e.g.) bool, and then maybe split it out later
> when we add a ui option for each property.

I mean, that should be possible in any representation, just needs separation of
types for the API and types to generate the (dumped) FRR config from.
One drawback is. that you loose type checks with templates, but that can be
made up by a regression test system (which is a necessity either way), so your
approach can be OK to me in general, but this needs to be Ack'ed also by Stefan.

> Here I made the decision to split every protocol into its own template file.
> These template files then import some common structs, such as the interfaces and
> route-maps, which are used in every protocol. To accommodate for this, I also had
> to change the structure of the FrrConfig:
> So we no longer have:
> 
> config/
> ├─ interfaces/
> │  ├─ openfabric
> │  ├─ ospf
> ├─ routers/
> │  ├─ openfabric
> │  ├─ ospf
> 
> but:
> 
> config/
> ├─ openfabric/
> │  ├─ interfaces
> │  ├─ routers
> ├─ ospf/
> │  ├─ interfaces
> │  ├─ routers
> 
> Which plays much nicer with the templates, and IMO still makes sense logically.

Sounds OK.

> I used minijinja for this series, as that seems to be the most used template
> engine in the rust ecosystem, even though we mostly seem to use handlebars. I
> discussed this we Lukas and Thomas, and we'll decide in the next few weeks if
> this is fine, or it's better if we use the same templating engine
> everywhere.

I took a (not so deep) look, and saw already that minijinja had two major
releases during the last two years, while that's the same amount as handlebars,
it's also a big turn-off there. Using one templating project where some
maintainers live out their refactoring hobby is already pain enough for us,
using two of them is IMO a no-go, at least for mid/long term. So if we really
want to choose minijinja here, I'd need an actionable plan–at least a draft–for
switching everything to it; which naturally makes me question why we shouldn't
go the route that do not need us to do some migrations for all notification
templates we now got in multiple projects. Is there a strong technical reason,
to favor minijinja that really is worth the cost of us migrating all handlebar
templates over? As from a quick look at the dependency tree the "mini" in the
name seems rather relative, or at least it's not orders of magnitude leaner
compared to handlebars-rust; and given that it also had as many major breaking
releases since 2023 it's not signalling a much stronger stability to me either,
which is naturally hard to predict for the future though.
Because just migrating due to you not checking upfront for the templating
engines in use in our projects, and some subjective "minijinja might be better"
opinion is IMO not enough; if there's a broader front and some technical arguments
that make it quite likely that the cost of the switch will be compensated due
to lower maintenance or whatever, I can be fine with going for this; but otherwise
I'd at least like you to investigate if this would be really that much worse/harder
with handlebars.

The third option of using two template engines is naturally also one, but actively
and knowingly planing a schism is not something I'd promote much either tbh.



More information about the pve-devel mailing list