public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH installer v4 21/30] auto: pass through management network vlan options to low-level installer
Date: Mon,  2 Nov 2026 13:45:27 +0100	[thread overview]
Message-ID: <20261102124539.1008075-22-c.heiss@proxmox.com> (raw)
In-Reply-To: <20261102124539.1008075-1-c.heiss@proxmox.com>

Fixes #2164 [0].

The auto-installer gains a new section under [network] in its answer
file for setting up a VLAN on the management interface during the
installation:

  [network.vlan]
  vid = 5

Where `vid` is the desired VLAN ID.

This then just passes through the given VLAN options in the answer file
to the low-level installation configuration, verifying them beforehand
and printing a status message if the management interface will be put on
a VLAN.

[0] https://bugzilla.proxmox.com/show_bug.cgi?id=2164

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Changes v3 -> v4:
  * skip serializing disabled vlan options to low-level config

Changes v2 -> v3:
  * new patch

 proxmox-auto-installer/src/utils.rs           | 14 ++++++++
 proxmox-auto-installer/tests/parse-answer.rs  |  3 ++
 .../parse_answer/network_bond_and_vlan.json   | 29 ++++++++++++++++
 .../parse_answer/network_bond_and_vlan.toml   | 23 +++++++++++++
 .../resources/parse_answer/network_vlan.json  | 23 +++++++++++++
 .../resources/parse_answer/network_vlan.toml  | 17 ++++++++++
 .../network_vlan_invalid_vid.json             |  3 ++
 .../network_vlan_invalid_vid.toml             | 17 ++++++++++
 proxmox-installer-common/src/options.rs       | 33 +++++++++++++------
 proxmox-installer-common/src/setup.rs         | 30 +++++++++++++++--
 10 files changed, 180 insertions(+), 12 deletions(-)
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.json
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.toml
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/network_vlan.json
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/network_vlan.toml
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.json
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.toml

diff --git a/proxmox-auto-installer/src/utils.rs b/proxmox-auto-installer/src/utils.rs
index b9b3a8d..46598f9 100644
--- a/proxmox-auto-installer/src/utils.rs
+++ b/proxmox-auto-installer/src/utils.rs
@@ -48,6 +48,7 @@ fn get_network_settings(
                 None,
                 pinning_opts.as_ref(),
                 answer.network.bond(),
+                answer.network.vlan(),
             );
             opts.fqdn = name.to_owned();
             opts
@@ -77,6 +78,7 @@ fn get_network_settings(
                 domain.as_deref(),
                 pinning_opts.as_ref(),
                 answer.network.bond(),
+                answer.network.vlan(),
             )
         }
     };
@@ -124,6 +126,10 @@ fn get_network_settings(
         opts.verify()?;
     }
 
+    if let Some(opts) = &network_options.vlan_opts {
+        info!("Management interface reachable on VLAN {}", opts.vid);
+    }
+
     info!("Network interface used is '{}'", &network_options.ifname);
     Ok(network_options)
 }
@@ -555,6 +561,10 @@ pub fn verify_network_settings(
         opts.verify()?;
     }
 
+    if let Some(opts) = network.vlan() {
+        opts.verify()?;
+    }
+
     Ok(())
 }
 
@@ -625,6 +635,10 @@ pub fn parse_answer(
                 })
             })
             .unwrap_or_else(|| Ok(InstallNetworkBondOptions::default()))?,
+        mngmt_vlan: network_settings
+            .vlan_opts
+            .map(|opts| opts.into())
+            .unwrap_or_default(),
         network_interface_pin_map: network_settings
             .pinning_opts
             .map(|o| o.mapping)
diff --git a/proxmox-auto-installer/tests/parse-answer.rs b/proxmox-auto-installer/tests/parse-answer.rs
index 0320bba..4776c4d 100644
--- a/proxmox-auto-installer/tests/parse-answer.rs
+++ b/proxmox-auto-installer/tests/parse-answer.rs
@@ -128,8 +128,10 @@ mod tests {
             hashed_root_password,
             minimal,
             network_bond,
+            network_bond_and_vlan,
             network_interface_pinning,
             network_interface_pinning_mixed_case_mac_addresses,
+            network_vlan,
             nic_matching,
             no_network,
             specific_nic,
@@ -156,6 +158,7 @@ mod tests {
             network_bond_primary_not_member,
             network_bond_single_interface,
             network_interface_pinning_overlong_interface_name,
+            network_vlan_invalid_vid,
             no_fqdn_from_dhcp,
             no_root_password_set,
             short_password,
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.json b/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.json
new file mode 100644
index 0000000..7a27868
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.json
@@ -0,0 +1,29 @@
+{
+  "autoreboot": 1,
+  "cidr": "192.168.1.114/24",
+  "country": "at",
+  "dns": "192.168.1.254",
+  "domain": "testinstall",
+  "filesys": "ext4",
+  "gateway": "192.168.1.1",
+  "hdsize": 223.57088470458984,
+  "existing_storage_auto_rename": 1,
+  "hostname": "pveauto",
+  "keymap": "de",
+  "mailto": "mail@no.invalid",
+  "mngmt_nic": "bond0",
+  "mngmt_bond": {
+      "members": ["B4:2E:99:AC:AD:B4", "B4:2E:99:AC:AD:B5"],
+      "mode": "active-backup",
+      "hash-policy": "layer3+4",
+      "primary-interface": "B4:2E:99:AC:AD:B5"
+  },
+  "mngmt_vlan": {
+    "enabled": true,
+    "vid": 5
+  },
+  "root_password": { "plain": "12345678" },
+  "target_hd": "/dev/sda",
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.toml b/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.toml
new file mode 100644
index 0000000..1352391
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/network_bond_and_vlan.toml
@@ -0,0 +1,23 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn = "pveauto.testinstall"
+mailto = "mail@no.invalid"
+timezone = "Europe/Vienna"
+root-password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[network.bond]
+members-list = ["b4:2e:99:ac:ad:b4", "b4:2e:99:ac:ad:b5"]
+mode = "active-backup"
+hash-policy = "layer3+4"
+primary-interface = "b4:2e:99:ac:ad:b5"
+
+[network.vlan]
+vid = 5
+
+[disk-setup]
+filesystem = "ext4"
+disk-list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.json b/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.json
new file mode 100644
index 0000000..2761922
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.json
@@ -0,0 +1,23 @@
+{
+  "autoreboot": 1,
+  "cidr": "192.168.1.114/24",
+  "country": "at",
+  "dns": "192.168.1.254",
+  "domain": "testinstall",
+  "filesys": "ext4",
+  "gateway": "192.168.1.1",
+  "hdsize": 223.57088470458984,
+  "existing_storage_auto_rename": 1,
+  "hostname": "pveauto",
+  "keymap": "de",
+  "mailto": "mail@no.invalid",
+  "mngmt_nic": "eno1",
+  "mngmt_vlan": {
+    "enabled": true,
+    "vid": 5
+  },
+  "root_password": { "plain": "12345678" },
+  "target_hd": "/dev/sda",
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.toml b/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.toml
new file mode 100644
index 0000000..c977711
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/network_vlan.toml
@@ -0,0 +1,17 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn = "pveauto.testinstall"
+mailto = "mail@no.invalid"
+timezone = "Europe/Vienna"
+root-password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[network.vlan]
+vid = 5
+
+[disk-setup]
+filesystem = "ext4"
+disk-list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.json
new file mode 100644
index 0000000..61ce63c
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.json
@@ -0,0 +1,3 @@
+{
+  "error": "VLAN id must be between 2 and 4094 inclusive, got 5000"
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.toml b/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.toml
new file mode 100644
index 0000000..c0e51c2
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/network_vlan_invalid_vid.toml
@@ -0,0 +1,17 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn = "pveauto.testinstall"
+mailto = "mail@no.invalid"
+timezone = "Europe/Vienna"
+root-password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[network.vlan]
+vid = 5000
+
+[disk-setup]
+filesystem = "ext4"
+disk-list = ["sda"]
diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs
index 1add63b..e32b77d 100644
--- a/proxmox-installer-common/src/options.rs
+++ b/proxmox-installer-common/src/options.rs
@@ -16,7 +16,8 @@ use proxmox_installer_types::{
     EMAIL_DEFAULT_PLACEHOLDER,
     answer::{
         BtrfsCompressOption, BtrfsRaidLevel, FilesystemType, NetworkBondOptions,
-        NetworkInterfacePinningOptionsAnswer, ZfsChecksumOption, ZfsCompressOption, ZfsRaidLevel,
+        NetworkInterfacePinningOptionsAnswer, NetworkVlanOptions, ZfsChecksumOption,
+        ZfsCompressOption, ZfsRaidLevel,
     },
 };
 use proxmox_network_types::{MacAddress, fqdn::Fqdn, ip_address::Cidr};
@@ -396,6 +397,7 @@ pub struct NetworkOptions {
     pub dns_server: IpAddr,
     pub pinning_opts: Option<NetworkInterfacePinningOptions>,
     pub bond_opts: Option<NetworkBondOptions>,
+    pub vlan_opts: Option<NetworkVlanOptions>,
 }
 
 impl NetworkOptions {
@@ -407,6 +409,7 @@ impl NetworkOptions {
         default_domain: Option<&str>,
         pinning_opts: Option<&NetworkInterfacePinningOptions>,
         bond_opts: Option<&NetworkBondOptions>,
+        vlan_opts: Option<&NetworkVlanOptions>,
     ) -> Self {
         // Sets up sensible defaults as much as possible, such that even in the
         // worse case nothing breaks down *completely*.
@@ -420,6 +423,7 @@ impl NetworkOptions {
             dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
             pinning_opts: pinning_opts.cloned(),
             bond_opts: bond_opts.cloned(),
+            vlan_opts: vlan_opts.cloned(),
         };
 
         let iface = if let Some(gw) = &network.routes.gateway4
@@ -639,7 +643,7 @@ mod tests {
         let (setup, mut info) = mock_setup_network();
 
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.bar.com").unwrap(),
@@ -648,12 +652,13 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
 
         info.hostname = None;
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("pve.bar.com").unwrap(),
@@ -662,12 +667,13 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
 
         info.dns.domain = None;
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("pve.example.invalid").unwrap(),
@@ -676,12 +682,13 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
 
         info.hostname = Some("foo".to_owned());
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.example.invalid").unwrap(),
@@ -690,6 +697,7 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
     }
@@ -737,7 +745,7 @@ mod tests {
         let (setup, info) = mock_setup_network_v6_only();
 
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.bar.com").unwrap(),
@@ -746,6 +754,7 @@ mod tests {
                 dns_server: IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x53)),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
     }
@@ -755,7 +764,7 @@ mod tests {
         let (setup, mut info) = mock_setup_network();
 
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.bar.com").unwrap(),
@@ -764,12 +773,13 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
 
         info.dns.domain = None;
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, Some("custom.local"), None, None),
+            NetworkOptions::defaults_from(&setup, &info, Some("custom.local"), None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.custom.local").unwrap(),
@@ -778,12 +788,13 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
 
         info.dns.domain = Some("some.domain.local".to_owned());
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, Some("custom.local"), None, None),
+            NetworkOptions::defaults_from(&setup, &info, Some("custom.local"), None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("foo.custom.local").unwrap(),
@@ -792,6 +803,7 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
     }
@@ -828,7 +840,7 @@ mod tests {
         let setup = SetupInfo::mocked();
 
         pretty_assertions::assert_eq!(
-            NetworkOptions::defaults_from(&setup, &info, None, None, None),
+            NetworkOptions::defaults_from(&setup, &info, None, None, None, None),
             NetworkOptions {
                 ifname: "eth0".to_owned(),
                 fqdn: Fqdn::from("pve.example.invalid").unwrap(),
@@ -837,6 +849,7 @@ mod tests {
                 dns_server: Ipv4Addr::new(192, 168, 100, 1).into(),
                 pinning_opts: None,
                 bond_opts: None,
+                vlan_opts: None,
             }
         );
     }
diff --git a/proxmox-installer-common/src/setup.rs b/proxmox-installer-common/src/setup.rs
index 31a1195..e5dfef4 100644
--- a/proxmox-installer-common/src/setup.rs
+++ b/proxmox-installer-common/src/setup.rs
@@ -17,8 +17,8 @@ use crate::options::{
 use proxmox_installer_types::{
     BootType, IsoInfo, ProductConfig,
     answer::{
-        BtrfsCompressOption, FilesystemType, ZfsChecksumOption,
-        ZfsCompressOption,
+        BtrfsCompressOption, FilesystemType, NetworkVlanOptions,
+        ZfsChecksumOption, ZfsCompressOption,
     },
 };
 use proxmox_network_api::{BondXmitHashPolicy, LinuxBondMode};
@@ -526,6 +526,30 @@ impl InstallNetworkBondOptions {
     }
 }
 
+#[derive(Clone, Default, Debug, Deserialize, Serialize, PartialEq)]
+/// Low-level installer options for setting up a VLAN configuration on the management interface.
+pub struct InstallNetworkVlanOptions {
+    /// Whether to enable VLAN tagging on the management interface
+    enabled: bool,
+    /// VLAN tag to configure.
+    pub vid: u16,
+}
+
+impl From<NetworkVlanOptions> for InstallNetworkVlanOptions {
+    fn from(opts: NetworkVlanOptions) -> Self {
+        Self {
+            enabled: true,
+            vid: opts.vid,
+        }
+    }
+}
+
+impl InstallNetworkVlanOptions {
+    fn is_disabled(&self) -> bool {
+        !self.enabled
+    }
+}
+
 /// See Proxmox::Install::Config
 #[derive(Debug, Deserialize, Serialize)]
 pub struct InstallConfig {
@@ -570,6 +594,8 @@ pub struct InstallConfig {
     pub mngmt_nic: String,
     #[serde(skip_serializing_if = "InstallNetworkBondOptions::is_disabled")]
     pub mngmt_bond: InstallNetworkBondOptions,
+    #[serde(skip_serializing_if = "InstallNetworkVlanOptions::is_disabled")]
+    pub mngmt_vlan: InstallNetworkVlanOptions,
 
     // Maps MAC addresses -> custom name. If set, enables pinning for all
     // interfaces present.
-- 
2.55.0





  parent reply	other threads:[~2026-11-02 12:49 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 12:45 [PATCH installer/proxmox v4 00/30] fix #2164: add bond setup across all installers Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 01/30] installer-types: clippy: use .is_multiple_of() instead of manual modulo Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 02/30] installer-types: use `MacAddress` type where applicable Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 03/30] installer-types: derive Display for RebootMode and FilterMatch Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 04/30] installer-types: answer: add options for configuring management bond Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 05/30] installer-types: answer: add options for configuring management vlan Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 06/30] installer-types: bump fetch schema for bond and VLAN answer options Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 07/30] installer-types: bump version to 0.3.0-1 Christoph Heiss
2026-11-02 12:45 ` [PATCH proxmox v4 08/30] network-api: derive Display and FromStr for network bond types Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 09/30] install: run make tidy Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 10/30] tree-wide: use `MacAddress` type instead of string for MAC addresses Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 11/30] install: factor out ifupdown2 config generation into own subroutine Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 12/30] install: do not rely on interface name map to be fully populated Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 13/30] install: config: add option for setting up bond on management interface Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 14/30] install: config: add option for setting up vlan " Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 15/30] install: network: set up management bond if requested Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 16/30] install: network: set up vlan on management interface " Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 17/30] gui: network: factor out name pinning into advanced options dialog Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 18/30] gui: network: add bond setup options to " Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 19/30] gui: network: add vlan setup options to advanced network dialog Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 20/30] auto: pass through management network bond options to low-level installer Christoph Heiss
2026-11-02 12:45 ` Christoph Heiss [this message]
2026-11-02 12:45 ` [PATCH installer v4 22/30] tui: drop long obsolete comment about logo formatting Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 23/30] tui: views: add widget for displaying a group of checkboxes Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 24/30] tui: network: factor out name pinning into advanced options dialog Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 25/30] tui: network: add bond setup options to advanced network dialog Christoph Heiss
2026-11-02 14:55   ` Lukas Sichert
2026-11-02 12:45 ` [PATCH installer v4 26/30] tui: network: add vlan " Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 27/30] gui: network: split advanced options dialog into tabs Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 28/30] tui: " Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 29/30] gui: network: list bond member candidates sharing a MAC address once Christoph Heiss
2026-11-02 12:45 ` [PATCH installer v4 30/30] tui: " Christoph Heiss

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=20261102124539.1008075-22-c.heiss@proxmox.com \
    --to=c.heiss@proxmox.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