public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: "Rémi PAETA" <remi.paeta@comaite.com>
To: pve-devel@lists.proxmox.com
Subject: SPAM: [RFC PATCH network 02/16] sdn: controllers: add ovn plugin
Date: Tue, 13 Oct 2026 14:14:18 +0200	[thread overview]
Message-ID: <20261013121432.2642979-3-remi.paeta@comaite.com> (raw)
In-Reply-To: <20261013121432.2642979-1-remi.paeta@comaite.com>

An OVN controller describes an existing OVN deployment: the connection
strings of its northbound and southbound databases and the tunnel
encapsulation used between the chassis. The OVN central components are
deployed and operated by the administrator, PVE only connects to them,
similar to how the external IPAM plugins use an existing service.

Only plain TCP connections are supported for now.

OVN does not use FRR, so OVN controllers are not taken into account
when deciding whether an FRR configuration needs to be generated.

Signed-off-by: Rémi PAETA <remi.paeta@comaite.com>
---
 src/PVE/Network/SDN.pm                       |  4 +-
 src/PVE/Network/SDN/Controllers.pm           |  2 +
 src/PVE/Network/SDN/Controllers/Makefile     |  2 +-
 src/PVE/Network/SDN/Controllers/OvnPlugin.pm | 86 ++++++++++++++++++++
 src/test/Makefile                            |  5 +-
 src/test/run_test_ovn.pl                     | 28 +++++++
 6 files changed, 124 insertions(+), 3 deletions(-)
 create mode 100644 src/PVE/Network/SDN/Controllers/OvnPlugin.pm
 create mode 100755 src/test/run_test_ovn.pl

diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm
index 33a3cf3..aeb9b4c 100644
--- a/src/PVE/Network/SDN.pm
+++ b/src/PVE/Network/SDN.pm
@@ -126,13 +126,15 @@ sub running_config_has_frr {
 
     # all can be empty if the SDN configuration was never applied
     my $controllers = $running_config->{controllers}->{ids} // {};
+    # OVN controllers do not generate any FRR configuration
+    my @frr_controllers = grep { $controllers->{$_}->{type} ne 'ovn' } keys %$controllers;
     my $fabrics = $running_config->{fabrics}->{ids} // {};
     my $route_maps = $running_config->{'route-maps'}->{ids} // {};
     my $prefix_lists = $running_config->{'prefix-lists'}->{ids} // {};
 
     my $local_frr_config = PVE::Network::SDN::Frr::local_frr_config_exists();
 
-    return %$controllers || %$fabrics || %$route_maps || %$prefix_lists || $local_frr_config;
+    return @frr_controllers || %$fabrics || %$route_maps || %$prefix_lists || $local_frr_config;
 }
 
 sub pending_config {
diff --git a/src/PVE/Network/SDN/Controllers.pm b/src/PVE/Network/SDN/Controllers.pm
index b2c2f9d..ac0d70a 100644
--- a/src/PVE/Network/SDN/Controllers.pm
+++ b/src/PVE/Network/SDN/Controllers.pm
@@ -15,11 +15,13 @@ use PVE::Network::SDN::Controllers::EvpnPlugin;
 use PVE::Network::SDN::Controllers::BgpPlugin;
 use PVE::Network::SDN::Controllers::IsisPlugin;
 use PVE::Network::SDN::Controllers::FaucetPlugin;
+use PVE::Network::SDN::Controllers::OvnPlugin;
 use PVE::Network::SDN::Controllers::Plugin;
 PVE::Network::SDN::Controllers::EvpnPlugin->register();
 PVE::Network::SDN::Controllers::BgpPlugin->register();
 PVE::Network::SDN::Controllers::IsisPlugin->register();
 PVE::Network::SDN::Controllers::FaucetPlugin->register();
+PVE::Network::SDN::Controllers::OvnPlugin->register();
 PVE::Network::SDN::Controllers::Plugin->init();
 
 sub sdn_controllers_config {
diff --git a/src/PVE/Network/SDN/Controllers/Makefile b/src/PVE/Network/SDN/Controllers/Makefile
index fd9f881..a1cd14e 100644
--- a/src/PVE/Network/SDN/Controllers/Makefile
+++ b/src/PVE/Network/SDN/Controllers/Makefile
@@ -1,4 +1,4 @@
-SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm IsisPlugin.pm
+SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm IsisPlugin.pm OvnPlugin.pm
 
 
 PERL5DIR=${DESTDIR}/usr/share/perl5
diff --git a/src/PVE/Network/SDN/Controllers/OvnPlugin.pm b/src/PVE/Network/SDN/Controllers/OvnPlugin.pm
new file mode 100644
index 0000000..f7a9b96
--- /dev/null
+++ b/src/PVE/Network/SDN/Controllers/OvnPlugin.pm
@@ -0,0 +1,86 @@
+package PVE::Network::SDN::Controllers::OvnPlugin;
+
+use v5.36;
+
+use PVE::JSONSchema;
+use PVE::Tools;
+
+use PVE::Network::SDN::Controllers::Plugin;
+
+use base('PVE::Network::SDN::Controllers::Plugin');
+
+PVE::JSONSchema::register_format('pve-sdn-ovn-remotes', \&pve_verify_sdn_ovn_remotes);
+
+sub pve_verify_sdn_ovn_remotes {
+    my ($remotes, $noerr) = @_;
+
+    for my $remote (split(/,/, $remotes)) {
+        next if $remote =~ m/^tcp:$PVE::Tools::IPV4RE:\d+$/;
+        next if $remote =~ m/^tcp:\[$PVE::Tools::IPV6RE\]:\d+$/;
+
+        return undef if $noerr;
+        die "invalid OVN database connection '$remote', expected tcp:<ip>:<port>\n";
+    }
+
+    return $remotes;
+}
+
+sub type {
+    return 'ovn';
+}
+
+sub properties {
+    return {
+        'nb-connection' => {
+            description => "Comma separated list of the OVN northbound database servers,"
+                . " for example tcp:10.0.0.1:6641,tcp:10.0.0.2:6641.",
+            type => 'string',
+            format => 'pve-sdn-ovn-remotes',
+        },
+        'sb-connection' => {
+            description => "Comma separated list of the OVN southbound database servers,"
+                . " for example tcp:10.0.0.1:6642,tcp:10.0.0.2:6642.",
+            type => 'string',
+            format => 'pve-sdn-ovn-remotes',
+        },
+        'encap-type' => {
+            description => "Tunnel encapsulation used between the chassis.",
+            type => 'string',
+            enum => ['geneve', 'vxlan'],
+            default => 'geneve',
+        },
+    };
+}
+
+sub options {
+    return {
+        'nb-connection' => { optional => 0 },
+        'sb-connection' => { optional => 0 },
+        'encap-type' => { optional => 1 },
+    };
+}
+
+# OVN does not use FRR
+sub generate_frr_config {
+    my ($class, $plugin_config, $controller_cfg, $id, $uplinks, $config) = @_;
+
+    return;
+}
+
+sub generate_zone_frr_config {
+    my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
+
+    return;
+}
+
+sub on_delete_hook {
+    my ($class, $controllerid, $zone_cfg) = @_;
+
+    for my $id (sort keys %{ $zone_cfg->{ids} }) {
+        my $zone = $zone_cfg->{ids}->{$id};
+        die "controller $controllerid is used by $id\n"
+            if defined($zone->{controller}) && $zone->{controller} eq $controllerid;
+    }
+}
+
+1;
diff --git a/src/test/Makefile b/src/test/Makefile
index 5a937a4..b3c5d69 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -1,6 +1,6 @@
 all: test
 
-test: test_zones test_ipams test_dns test_subnets test_vnets_blackbox
+test: test_zones test_ipams test_dns test_subnets test_vnets_blackbox test_ovn
 
 test_zones: run_test_zones.pl
 	./run_test_zones.pl
@@ -17,4 +17,7 @@ test_subnets: run_test_subnets.pl
 test_vnets_blackbox: run_test_vnets_blackbox.pl
 	./run_test_vnets_blackbox.pl
 
+test_ovn: run_test_ovn.pl
+	./run_test_ovn.pl
+
 clean:
diff --git a/src/test/run_test_ovn.pl b/src/test/run_test_ovn.pl
new file mode 100755
index 0000000..60e752b
--- /dev/null
+++ b/src/test/run_test_ovn.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib qw(..);
+
+use Test::More;
+
+use PVE::Network::SDN;
+use PVE::Network::SDN::Controllers::OvnPlugin;
+
+# controller schema
+
+ok(
+    PVE::Network::SDN::Controllers::OvnPlugin::pve_verify_sdn_ovn_remotes(
+        'tcp:10.0.0.1:6641,tcp:[fd00::1]:6641', 1,
+    ),
+    'remotes format: valid',
+);
+for my $invalid ('ssl:10.0.0.1:6641', 'tcp:10.0.0.1', 'tcp:ovn.example.com:6641') {
+    ok(
+        !PVE::Network::SDN::Controllers::OvnPlugin::pve_verify_sdn_ovn_remotes($invalid, 1),
+        "remotes format: invalid '$invalid'",
+    );
+}
+
+done_testing();
-- 
2.47.3




  parent reply	other threads:[~2026-10-13 12:32 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09  9:22 [RFC] sdn: OVN zone and controller plugins Rémi PAETA
2026-10-13 12:14 ` [RFC PATCH ve-rs/network/manager/docs 00/16] sdn: add " Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH ve-rs 01/16] ve-config: sdn: add ovn zone type Rémi PAETA
2026-10-13 12:14   ` Rémi PAETA [this message]
2026-10-13 12:14   ` [RFC PATCH network 03/16] sdn: zones: add ovn plugin Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 04/16] sdn: ovn: sync the northbound database on reload Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 05/16] sdn: ovn: configure the chassis on boot and on network reload Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 06/16] sdn: ovn: add port security Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 07/16] sdn: ovn: allow overriding the port security per vnet Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 08/16] sdn: subnets: refuse gateway, snat and dhcp on ovn zones Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 09/16] sdn: ovn: support ssl connections to the databases Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH network 10/16] sdn: ovn: bind guest ports to the chassis of their node Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH manager 11/16] ui: sdn: controller selector: allow filtering by controller type Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH manager 12/16] ui: sdn: add ovn controller Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH manager 13/16] ui: sdn: add ovn zone Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH manager 14/16] ui: sdn: vnet: add port security for ovn zones Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH manager 15/16] ui: sdn: vnet: disable isolate ports " Rémi PAETA
2026-10-13 12:14   ` [RFC PATCH docs 16/16] sdn: document ovn zones and controllers Rémi PAETA

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261013121432.2642979-3-remi.paeta@comaite.com \
    --to=remi.paeta@comaite.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal