From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id B7EFF1FF137 for ; Tue, 03 Feb 2026 17:04:00 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 18945256FF; Tue, 3 Feb 2026 17:03:34 +0100 (CET) From: Gabriel Goller To: pve-devel@lists.proxmox.com Subject: [PATCH docs/manager/network/proxmox{-ve-rs,-perl-rs} 00/23] Generate frr config using jinja templates and rust types Date: Tue, 3 Feb 2026 17:01:07 +0100 Message-ID: <20260203160246.353351-1-g.goller@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1770134496189 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.003 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: F3RIPGK62T3HBZR327XW2HLC4WRYGMGK X-Message-ID-Hash: F3RIPGK62T3HBZR327XW2HLC4WRYGMGK X-MailFrom: g.goller@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Previously we generated the frr config using one big perl hash, where every controller-plugin and zone-plugin would push their stuff. This is not pretty and also tricky to unite with our new rust-based fabrics. Furthermore the only way to edit or override the frr config is currently the frr.conf.local file, which is merged with the perl-hash in a very janky manner, which has sprouted numerous forum threads. The main problem with the frr.conf.local is the limited control which the user has as to where the override or additional config gets placed. There are also a few config overrides or additions to frr.conf.local that are currently impossible or generate invalid frr config. To improve this we now ship templates, which we use to generate the frr config. This is the way it is done in e.g. sonic and vyos. These jinja2 templates are then populated using rust-structs. We changed the perl code to generate bgp/evpn and isis config that can be deserialized by the rust types and then rendered into a frr configuration using the templates. # Versioning The templates are in the proxmox-frr-templates debian package which, when installed, copies the template into `/usr/share/proxmox-frr/templates`, where they are read from using `include_str!`. This means the proxmox-frr-templates package is only used for development and to version the templates. The user only gets them in the binary of proxmox-frr (which, by extension, is in the perl-rs shared library). # User Override In order to extract these templates from the binary we introduce a new cli tool: pvesdn. Using pvesdn the user can show the currently packaged template file, automatically create an override file `/etc/proxmox-frr/templates/`, show the difference between the override file and the packaged file and reset the override files. libpve-network (pve-network) also has an additional debian/postinst script, which registers the override files with `ucf` and makes a three-way-merge with the override-file, the old packaged file and the updated packaged file. This way, when the templates are updated the user can choose "edit", "maintainer's version" or "my version". # frr.conf.local The frr.conf.local merging code has been adjusted so that the frr.conf.local still works as before. Also thanks to Stefan Hanreich as always :) proxmox-ve-rs: Gabriel Goller (9): ve-config: firewall: cargo fmt frr: add proxmox-frr-templates package that contains templates ve-config: remove FrrConfigBuilder struct sdn-types: support variable-length NET identifier frr: add template serializer and serialize fabrics using templates frr: add isis configuration and templates frr: support custom frr configuration lines frr: add bgp support with templates and serialization frr: store frr template content as a const map Makefile | 8 + proxmox-frr-templates/.gitignore | 1 + proxmox-frr-templates/Makefile | 50 +++ proxmox-frr-templates/debian/changelog | 5 + proxmox-frr-templates/debian/control | 17 + proxmox-frr-templates/debian/copyright | 18 ++ .../debian/proxmox-frr-templates.install | 1 + proxmox-frr-templates/debian/rules | 5 + .../templates/access_list.jinja | 6 + .../templates/access_lists.jinja | 6 + .../templates/bgp_router.jinja | 118 +++++++ proxmox-frr-templates/templates/bgpd.jinja | 35 ++ proxmox-frr-templates/templates/fabricd.jinja | 29 ++ .../templates/frr.conf.jinja | 12 + .../templates/interface.jinja | 9 + .../templates/ip_routes.jinja | 8 + proxmox-frr-templates/templates/isisd.jinja | 32 ++ proxmox-frr-templates/templates/ospfd.jinja | 18 ++ .../templates/prefix_lists.jinja | 6 + .../templates/protocol_routemaps.jinja | 10 + .../templates/route_maps.jinja | 20 ++ proxmox-frr/Cargo.toml | 4 + proxmox-frr/debian/control | 14 + proxmox-frr/src/ser/bgp.rs | 184 +++++++++++ proxmox-frr/src/ser/isis.rs | 49 +++ proxmox-frr/src/ser/mod.rs | 294 ++++++++--------- proxmox-frr/src/ser/openfabric.rs | 26 +- proxmox-frr/src/ser/ospf.rs | 56 +--- proxmox-frr/src/ser/route_map.rs | 175 ++++------ proxmox-frr/src/ser/serializer.rs | 242 +++----------- proxmox-sdn-types/src/net.rs | 140 +++++++- proxmox-ve-config/src/common/valid.rs | 4 +- proxmox-ve-config/src/firewall/cluster.rs | 3 +- proxmox-ve-config/src/firewall/types/ipset.rs | 2 +- proxmox-ve-config/src/sdn/fabric/frr.rs | 302 ++++++++++-------- proxmox-ve-config/src/sdn/frr.rs | 42 --- proxmox-ve-config/src/sdn/mod.rs | 2 - proxmox-ve-config/tests/fabric/main.rs | 101 +++--- .../fabric__openfabric_default_pve.snap | 2 +- .../fabric__openfabric_default_pve1.snap | 2 +- .../fabric__openfabric_dualstack_pve.snap | 13 +- .../fabric__openfabric_ipv6_only_pve.snap | 4 +- .../fabric__openfabric_multi_fabric_pve1.snap | 2 +- .../snapshots/fabric__ospf_default_pve.snap | 2 +- .../snapshots/fabric__ospf_default_pve1.snap | 2 +- .../fabric__ospf_multi_fabric_pve1.snap | 2 +- 46 files changed, 1339 insertions(+), 744 deletions(-) create mode 100644 proxmox-frr-templates/.gitignore create mode 100644 proxmox-frr-templates/Makefile create mode 100644 proxmox-frr-templates/debian/changelog create mode 100644 proxmox-frr-templates/debian/control create mode 100644 proxmox-frr-templates/debian/copyright create mode 100644 proxmox-frr-templates/debian/proxmox-frr-templates.install create mode 100755 proxmox-frr-templates/debian/rules create mode 100644 proxmox-frr-templates/templates/access_list.jinja create mode 100644 proxmox-frr-templates/templates/access_lists.jinja create mode 100644 proxmox-frr-templates/templates/bgp_router.jinja create mode 100644 proxmox-frr-templates/templates/bgpd.jinja create mode 100644 proxmox-frr-templates/templates/fabricd.jinja create mode 100644 proxmox-frr-templates/templates/frr.conf.jinja create mode 100644 proxmox-frr-templates/templates/interface.jinja create mode 100644 proxmox-frr-templates/templates/ip_routes.jinja create mode 100644 proxmox-frr-templates/templates/isisd.jinja create mode 100644 proxmox-frr-templates/templates/ospfd.jinja create mode 100644 proxmox-frr-templates/templates/prefix_lists.jinja create mode 100644 proxmox-frr-templates/templates/protocol_routemaps.jinja create mode 100644 proxmox-frr-templates/templates/route_maps.jinja create mode 100644 proxmox-frr/src/ser/bgp.rs create mode 100644 proxmox-frr/src/ser/isis.rs delete mode 100644 proxmox-ve-config/src/sdn/frr.rs proxmox-perl-rs: Gabriel Goller (2): sdn: add function to generate the frr config for all daemons sdn: add method to get a frr template pve-rs/Makefile | 1 + pve-rs/src/bindings/sdn/fabrics.rs | 25 +++------------------ pve-rs/src/bindings/sdn/mod.rs | 35 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 22 deletions(-) pve-network: Gabriel Goller (10): sdn: remove duplicate comment line '!' in frr config sdn: tests: add missing comment '!' in frr config tests: use Test::Differences to make test assertions sdn: write structured frr config that can be rendered using templates tests: rearrange some statements in the frr config sdn: adjust frr.conf.local merging to rust template types cli: add pvesdn cli tool for managing frr template overrides debian: handle user modifications to FRR templates via ucf api: add dry-run endpoint for sdn apply to preview changes test: add test for frr.conf.local merging debian/control | 2 + debian/libpve-network-api-perl.install | 1 + debian/libpve-network-perl.install | 4 + debian/libpve-network-perl.postinst | 34 +- debian/libpve-network-perl.postrm | 33 ++ src/Makefile | 2 +- src/PVE/API2/Network/SDN.pm | 67 ++++ src/PVE/CLI/Makefile | 7 + src/PVE/CLI/pvesdn.pm | 252 ++++++++++++ src/PVE/Makefile | 1 + src/PVE/Network/SDN.pm | 20 +- src/PVE/Network/SDN/Controllers/BgpPlugin.pm | 104 ++--- src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 372 +++++++++--------- src/PVE/Network/SDN/Controllers/IsisPlugin.pm | 28 +- src/PVE/Network/SDN/Fabrics.pm | 14 +- src/PVE/Network/SDN/Frr.pm | 366 +++++++++-------- src/bin/Makefile | 69 ++++ src/bin/pvesdn | 8 + src/test/run_test_dns.pl | 15 +- src/test/run_test_ipams.pl | 13 +- src/test/run_test_subnets.pl | 31 +- src/test/run_test_vnets_blackbox.pl | 23 +- src/test/run_test_zones.pl | 21 +- .../expected_controller_config | 1 - .../expected_controller_config | 1 - .../evpn/ebgp/expected_controller_config | 1 - .../ebgp_loopback/expected_controller_config | 3 +- .../evpn/exitnode/expected_controller_config | 1 - .../expected_controller_config | 1 - .../expected_controller_config | 1 - .../exitnode_snat/expected_controller_config | 1 - .../expected_controller_config | 1 - .../expected_controller_config | 61 +++ .../frr_local_merge/expected_sdn_interfaces | 42 ++ .../zones/evpn/frr_local_merge/frr.conf.local | 30 ++ .../zones/evpn/frr_local_merge/interfaces | 7 + .../zones/evpn/frr_local_merge/sdn_config | 24 ++ .../evpn/ipv4/expected_controller_config | 1 - .../evpn/ipv4ipv6/expected_controller_config | 1 - .../expected_controller_config | 1 - .../evpn/ipv6/expected_controller_config | 1 - .../ipv6underlay/expected_controller_config | 1 - .../evpn/isis/expected_controller_config | 15 +- .../isis_loopback/expected_controller_config | 15 +- .../expected_controller_config | 13 +- .../expected_controller_config | 3 +- .../multiplezones/expected_controller_config | 1 - .../expected_controller_config | 13 +- .../ospf_fabric/expected_controller_config | 13 +- .../evpn/rt_import/expected_controller_config | 1 - .../evpn/vxlanport/expected_controller_config | 1 - 51 files changed, 1192 insertions(+), 550 deletions(-) create mode 100644 debian/libpve-network-perl.postrm create mode 100644 src/PVE/CLI/Makefile create mode 100644 src/PVE/CLI/pvesdn.pm create mode 100644 src/bin/Makefile create mode 100755 src/bin/pvesdn create mode 100644 src/test/zones/evpn/frr_local_merge/expected_controller_config create mode 100644 src/test/zones/evpn/frr_local_merge/expected_sdn_interfaces create mode 100644 src/test/zones/evpn/frr_local_merge/frr.conf.local create mode 100644 src/test/zones/evpn/frr_local_merge/interfaces create mode 100644 src/test/zones/evpn/frr_local_merge/sdn_config pve-manager: Gabriel Goller (1): sdn: add dry-run view for sdn apply www/manager6/Makefile | 1 + www/manager6/sdn/SdnDiffView.js | 123 ++++++++++++++++++++++++++++++++ www/manager6/sdn/StatusView.js | 8 +++ 3 files changed, 132 insertions(+) create mode 100644 www/manager6/sdn/SdnDiffView.js pve-docs: Gabriel Goller (1): docs: add man page for the `pvesdn` cli pvesdn.1-synopsis.adoc | 39 +++++++++++++++++++++++++++++++++++++++ pvesdn.adoc | 24 +++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 pvesdn.1-synopsis.adoc Summary over all repositories: 105 files changed, 2764 insertions(+), 1317 deletions(-) -- Generated by git-murpp 0.8.0