From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 313AE1FF0C0 for ; Wed, 21 Oct 2026 18:14:37 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 9A3BB2147A; Wed, 21 Oct 2026 18:14:34 +0200 (CEST) Message-ID: <125e7833-c8e6-4cfa-a0d7-7d8daec2836e@proxmox.com> Date: Wed, 21 Oct 2026 18:14:29 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird From: Stefan Hanreich Subject: Re: [PATCH proxmox-perl-rs 07/15] pve-rs: fabrics: make per-fabric status queries VRF-aware To: pve-devel@lists.proxmox.com References: <20260821140404.322081-1-g.goller@proxmox.com> <20260821140404.322081-8-g.goller@proxmox.com> Content-Language: en-US In-Reply-To: <20260821140404.322081-8-g.goller@proxmox.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.339 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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: BIOXM6RAOFXM7O6UG4YTBMBRHOSZUZAM X-Message-ID-Hash: BIOXM6RAOFXM7O6UG4YTBMBRHOSZUZAM X-MailFrom: s.hanreich@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: as already mentioned in the response to the cover letter, the VRF specific commands have a different format and fail to deserialize for OSPF neighbors and interfaces. On 8/21/26 4:04 PM, Gabriel Goller wrote: > Use the fabric VRF in FRR route, neighbor, and interface queries for > OSPF and BGP. > > Keep the existing commands for fabrics in the default routing table. > > Signed-off-by: Gabriel Goller > --- > pve-rs/src/bindings/sdn/fabrics.rs | 63 +++++++++++++++++++----------- > 1 file changed, 41 insertions(+), 22 deletions(-) > > diff --git a/pve-rs/src/bindings/sdn/fabrics.rs b/pve-rs/src/bindings/sdn/fabrics.rs > index 98470eeaa397..0fb1ccec9b7c 100644 > --- a/pve-rs/src/bindings/sdn/fabrics.rs > +++ b/pve-rs/src/bindings/sdn/fabrics.rs > @@ -848,6 +848,7 @@ pub mod pve_rs_sdn_fabrics { > }; > > let fabric = config.get_fabric(&fabric_id)?; > + let vrf = fabric_vrf_name(fabric); > match fabric { > FabricEntry::Openfabric(_) => { > let openfabric_ipv4_routes_string = String::from_utf8( > @@ -885,12 +886,12 @@ pub mod pve_rs_sdn_fabrics { > ) > } > FabricEntry::Ospf(_) => { > - let ospf_routes_string = String::from_utf8( > - Command::new("sh") > - .args(["-c", "vtysh -c 'show ip route ospf json'"]) > - .output()? > - .stdout, > - )?; > + let command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show ip route vrf {vrf} ospf json'"), > + None => "vtysh -c 'show ip route ospf json'".to_string(), > + }; > + let ospf_routes_string = > + String::from_utf8(Command::new("sh").args(["-c", &command]).output()?.stdout)?; > let ospf_routes: proxmox_frr::de::Routes = if ospf_routes_string.is_empty() { > proxmox_frr::de::Routes::default() > } else { > @@ -902,10 +903,18 @@ pub mod pve_rs_sdn_fabrics { > } > FabricEntry::WireGuard(_) => Ok(Vec::new()), > FabricEntry::Bgp(_) => { > + let ipv4_command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show ip route vrf {vrf} bgp json'"), > + None => "vtysh -c 'show ip route bgp json'".to_string(), > + }; > + let ipv6_command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show ipv6 route vrf {vrf} bgp json'"), > + None => "vtysh -c 'show ipv6 route bgp json'".to_string(), > + }; > let bgp_ipv4_routes_string = String::from_utf8( > Command::new("sh") > .env("VTYSH_HISTFILE", "/dev/null") > - .args(["-c", "vtysh -c 'show ip route bgp json'"]) > + .args(["-c", &ipv4_command]) > .output()? > .stdout, > )?; > @@ -913,7 +922,7 @@ pub mod pve_rs_sdn_fabrics { > let bgp_ipv6_routes_string = String::from_utf8( > Command::new("sh") > .env("VTYSH_HISTFILE", "/dev/null") > - .args(["-c", "vtysh -c 'show ipv6 route bgp json'"]) > + .args(["-c", &ipv6_command]) > .output()? > .stdout, > )?; > @@ -948,6 +957,7 @@ pub mod pve_rs_sdn_fabrics { > }; > > let fabric = config.get_fabric(&fabric_id)?; > + let vrf = fabric_vrf_name(fabric); > > match fabric { > FabricEntry::Openfabric(_) => { > @@ -968,12 +978,12 @@ pub mod pve_rs_sdn_fabrics { > status::get_neighbors_openfabric(fabric_id, openfabric_neighbors).map(|v| v.into()) > } > FabricEntry::Ospf(fabric) => { > - let ospf_neighbors_string = String::from_utf8( > - Command::new("sh") > - .args(["-c", "vtysh -c 'show ip ospf neighbor json'"]) > - .output()? > - .stdout, > - )?; > + let command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show ip ospf vrf {vrf} neighbor json'"), > + None => "vtysh -c 'show ip ospf neighbor json'".to_string(), > + }; > + let ospf_neighbors_string = > + String::from_utf8(Command::new("sh").args(["-c", &command]).output()?.stdout)?; > let ospf_neighbors: proxmox_frr::de::ospf::Neighbors = > if ospf_neighbors_string.is_empty() { > proxmox_frr::de::ospf::Neighbors::default() > @@ -992,10 +1002,14 @@ pub mod pve_rs_sdn_fabrics { > } > FabricEntry::WireGuard(_) => Ok(status::NeighborStatus::WireGuard(Vec::new())), > FabricEntry::Bgp(_) => { > + let command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show bgp vrf {vrf} neighbors json'"), > + None => "vtysh -c 'show bgp neighbors json'".to_string(), > + }; > let bgp_neighbors_string = String::from_utf8( > Command::new("sh") > .env("VTYSH_HISTFILE", "/dev/null") > - .args(["-c", "vtysh -c 'show bgp neighbors json'"]) > + .args(["-c", &command]) > .output()? > .stdout, > )?; > @@ -1025,6 +1039,7 @@ pub mod pve_rs_sdn_fabrics { > }; > > let fabric = config.get_fabric(&fabric_id)?; > + let vrf = fabric_vrf_name(fabric); > > match fabric { > FabricEntry::Openfabric(_) => { > @@ -1046,12 +1061,12 @@ pub mod pve_rs_sdn_fabrics { > .map(|v| v.into()) > } > FabricEntry::Ospf(fabric) => { > - let ospf_interfaces_string = String::from_utf8( > - Command::new("sh") > - .args(["-c", "vtysh -c 'show ip ospf interface json'"]) > - .output()? > - .stdout, > - )?; > + let command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show ip ospf vrf {vrf} interface json'"), > + None => "vtysh -c 'show ip ospf interface json'".to_string(), > + }; > + let ospf_interfaces_string = > + String::from_utf8(Command::new("sh").args(["-c", &command]).output()?.stdout)?; > let ospf_interfaces: proxmox_frr::de::ospf::Interfaces = > if ospf_interfaces_string.is_empty() { > proxmox_frr::de::ospf::Interfaces::default() > @@ -1070,10 +1085,14 @@ pub mod pve_rs_sdn_fabrics { > } > FabricEntry::WireGuard(_) => Ok(status::InterfaceStatus::WireGuard(Vec::new())), > FabricEntry::Bgp(_) => { > + let command = match &vrf { > + Some(vrf) => format!("vtysh -c 'show bgp vrf {vrf} neighbors json'"), > + None => "vtysh -c 'show bgp neighbors json'".to_string(), > + }; > let bgp_neighbors_string = String::from_utf8( > Command::new("sh") > .env("VTYSH_HISTFILE", "/dev/null") > - .args(["-c", "vtysh -c 'show bgp neighbors json'"]) > + .args(["-c", &command]) > .output()? > .stdout, > )?;