all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces
@ 2026-09-25 12:34 Christoph Heiss
  2026-09-25 12:34 ` [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces Christoph Heiss
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Christoph Heiss @ 2026-09-25 12:34 UTC (permalink / raw)
  To: pbs-devel

Fixes #6121 [0], for both PBS and (through proxmox-network-api) PDM.

Adds a new 'bond-miimon' option to the network interface API for
specifying the link monitoring interval.

This is needed so that (at least) in active-backup mode, the bond
correctly switches over to the backup link if the active one goes down.

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

proxmox:

Christoph Heiss (2):
  fix #6121: network-api: api: add `bond-miimon` option for interfaces
  fix #6121: network-api: config: add support for `bond-miimon` option

 proxmox-network-api/src/api_impl.rs      |  9 +++
 proxmox-network-api/src/api_types.rs     | 18 ++++++
 proxmox-network-api/src/config/lexer.rs  |  3 +
 proxmox-network-api/src/config/mod.rs    | 70 ++++++++++++++++++++++++
 proxmox-network-api/src/config/parser.rs | 23 ++++++++
 5 files changed, 123 insertions(+)

proxmox-backup:

Christoph Heiss (1):
  api: network: reuse interface create/update methods from network-api

 src/api2/node/network.rs | 674 ++-------------------------------------
 1 file changed, 18 insertions(+), 656 deletions(-)





^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces
  2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
@ 2026-09-25 12:34 ` Christoph Heiss
  2026-11-09 10:15   ` Christian Ebner
  2026-09-25 12:34 ` [PATCH proxmox 2/3] fix #6121: network-api: config: add support for `bond-miimon` option Christoph Heiss
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Christoph Heiss @ 2026-09-25 12:34 UTC (permalink / raw)
  To: pbs-devel

Partially fixes #6121 [0].

Adds a new 'bond-miimon' option to the network interface API for
specifying the link monitoring interval.

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

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
 proxmox-network-api/src/api_impl.rs  |  9 +++++++++
 proxmox-network-api/src/api_types.rs | 18 ++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/proxmox-network-api/src/api_impl.rs b/proxmox-network-api/src/api_impl.rs
index 78f499c5..0a603017 100644
--- a/proxmox-network-api/src/api_impl.rs
+++ b/proxmox-network-api/src/api_impl.rs
@@ -162,6 +162,9 @@ pub fn create_interface(iface: String, config: InterfaceUpdater) -> Result<(), E
                     interface.bond_xmit_hash_policy = config.bond_xmit_hash_policy;
                 }
             }
+            if config.bond_miimon.is_some() {
+                interface.bond_miimon = config.bond_miimon;
+            }
             if let Some(slaves) = &config.slaves {
                 interface.set_bond_slave_list(slaves)?;
             }
@@ -295,6 +298,9 @@ pub fn update_interface(
                 DeletableInterfaceProperty::BondXmitHashPolicy => {
                     interface.bond_xmit_hash_policy = None
                 }
+                DeletableInterfaceProperty::BondMiimon => {
+                    interface.bond_miimon = None;
+                }
             }
         }
     }
@@ -335,6 +341,9 @@ pub fn update_interface(
             }
             interface.bond_xmit_hash_policy = update.bond_xmit_hash_policy;
         }
+        if update.bond_miimon.is_some() {
+            interface.bond_miimon = update.bond_miimon;
+        }
     }
 
     if let Some(cidr) = update.cidr {
diff --git a/proxmox-network-api/src/api_types.rs b/proxmox-network-api/src/api_types.rs
index f2467f1e..471f20e8 100644
--- a/proxmox-network-api/src/api_types.rs
+++ b/proxmox-network-api/src/api_types.rs
@@ -228,6 +228,12 @@ pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema =
             type: BondXmitHashPolicy,
             optional: true,
         },
+        "bond-miimon": {
+            description: "Link monitoring interval in milliseconds for bond interfaces.",
+            type: u8,
+            optional: true,
+            default: 100,
+        },
         altnames: {
             description: "List of altnames for this interface",
             type: Array,
@@ -302,6 +308,8 @@ pub struct Interface {
     pub bond_primary: Option<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
+    #[serde(rename = "bond-miimon", skip_serializing_if = "Option::is_none")]
+    pub bond_miimon: Option<u8>,
 
     #[serde(default, skip_serializing_if = "Vec::is_empty")]
     pub altnames: Vec<String>,
@@ -333,6 +341,7 @@ impl Interface {
             bond_mode: None,
             bond_primary: None,
             bond_xmit_hash_policy: None,
+            bond_miimon: None,
             altnames: Vec::new(),
         }
     }
@@ -425,6 +434,8 @@ pub enum DeletableInterfaceProperty {
     /// Delete bond transmit hash policy
     #[serde(rename = "bond_xmit_hash_policy")]
     BondXmitHashPolicy,
+    /// Delete bond miimon (set to default 100)
+    BondMiimon,
 }
 
 #[api(
@@ -509,6 +520,12 @@ pub enum DeletableInterfaceProperty {
                 type: BondXmitHashPolicy,
                 optional: true,
             },
+            "bond-miimon": {
+                description: "Link monitoring interval in milliseconds for bond interfaces.",
+                type: u8,
+                optional: true,
+                default: 100,
+            },
             slaves: {
                 schema: NETWORK_INTERFACE_LIST_SCHEMA,
                 optional: true,
@@ -542,5 +559,6 @@ pub struct InterfaceUpdater {
     pub bond_primary: Option<String>,
     #[serde(rename = "bond_xmit_hash_policy")]
     pub bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
+    pub bond_miimon: Option<u8>,
     pub slaves: Option<String>,
 }
-- 
2.55.0





^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH proxmox 2/3] fix #6121: network-api: config: add support for `bond-miimon` option
  2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
  2026-09-25 12:34 ` [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces Christoph Heiss
@ 2026-09-25 12:34 ` Christoph Heiss
  2026-09-25 12:34 ` [PATCH proxmox-backup 3/3] api: network: reuse interface create/update methods from network-api Christoph Heiss
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Christoph Heiss @ 2026-09-25 12:34 UTC (permalink / raw)
  To: pbs-devel

Fixes #6121 [0].

Adds support for the 'bond-miimon' option to the ifupdown(2) config
writer and parser.

The option is always written out for bonds, with a default value of 100
- much like PVE does it.

This is needed so that (at least) in active-backup mode, the bond
correctly switches over to the backup link if the active one goes down.

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

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
 proxmox-network-api/src/config/lexer.rs  |  3 +
 proxmox-network-api/src/config/mod.rs    | 70 ++++++++++++++++++++++++
 proxmox-network-api/src/config/parser.rs | 23 ++++++++
 3 files changed, 96 insertions(+)

diff --git a/proxmox-network-api/src/config/lexer.rs b/proxmox-network-api/src/config/lexer.rs
index 4729d462..2a646508 100644
--- a/proxmox-network-api/src/config/lexer.rs
+++ b/proxmox-network-api/src/config/lexer.rs
@@ -30,6 +30,7 @@ pub enum Token {
     BondMode,
     BondPrimary,
     BondXmitHashPolicy,
+    BondMiimon,
     EOF,
 }
 
@@ -62,6 +63,8 @@ static KEYWORDS: LazyLock<HashMap<&'static str, Token>> = LazyLock::new(|| {
     map.insert("bond_primary", Token::BondPrimary);
     map.insert("bond_xmit_hash_policy", Token::BondXmitHashPolicy);
     map.insert("bond-xmit-hash-policy", Token::BondXmitHashPolicy);
+    map.insert("bond-miimon", Token::BondMiimon);
+    map.insert("bond_miimon", Token::BondMiimon);
     map
 });
 
diff --git a/proxmox-network-api/src/config/mod.rs b/proxmox-network-api/src/config/mod.rs
index 09165bfb..3eff9284 100644
--- a/proxmox-network-api/src/config/mod.rs
+++ b/proxmox-network-api/src/config/mod.rs
@@ -89,6 +89,9 @@ fn write_iface_attributes(iface: &Interface, w: &mut dyn Write) -> Result<(), Er
                 }
             }
 
+            let miimon = iface.bond_miimon.unwrap_or(100);
+            writeln!(w, "\tbond-miimon {miimon}")?;
+
             let slaves = iface.slaves.as_ref().unwrap_or(&EMPTY_LIST);
             if slaves.is_empty() {
                 writeln!(w, "\tbond-slaves none")?;
@@ -791,4 +794,71 @@ iface individual_name inet manual
         assert_eq!(parse_vlan_raw_device_from_name("vmbr0"), None);
         assert_eq!(parse_vlan_raw_device_from_name("vmbr0.200"), Some("vmbr0"));
     }
+
+    #[test]
+    fn test_write_network_config_bond_default_miimon() {
+        let mut bond = Interface::new("bond0".to_owned());
+        bond.interface_type = NetworkInterfaceType::Bond;
+        bond.method = Some(NetworkConfigMethod::Manual);
+        bond.slaves = Some(vec![String::from("eth0"), String::from("eth1")]);
+        bond.bond_mode = Some(LinuxBondMode::ActiveBackup);
+
+        let mut eth0 = Interface::new("eth0".to_owned());
+        eth0.interface_type = NetworkInterfaceType::Eth;
+
+        let mut eth1 = Interface::new("eth1".to_owned());
+        eth1.interface_type = NetworkInterfaceType::Eth;
+
+        let nw_config = NetworkConfig {
+            interfaces: BTreeMap::from([
+                ("eth0".into(), eth0),
+                ("eth1".into(), eth1),
+                ("bond0".into(), bond),
+            ]),
+            order: vec![NetworkOrderEntry::Iface("bond0".to_owned())],
+        };
+        assert_eq!(
+            String::try_from(nw_config).unwrap().trim(),
+            r#"
+iface bond0 inet manual
+	bond-mode active-backup
+	bond-miimon 100
+	bond-slaves eth0 eth1"#
+                .trim()
+        );
+    }
+
+    #[test]
+    fn test_write_network_config_bond_explicit_miimon() {
+        let mut bond = Interface::new("bond0".to_owned());
+        bond.interface_type = NetworkInterfaceType::Bond;
+        bond.method = Some(NetworkConfigMethod::Manual);
+        bond.slaves = Some(vec![String::from("eth0"), String::from("eth1")]);
+        bond.bond_mode = Some(LinuxBondMode::ActiveBackup);
+        bond.bond_miimon = Some(250);
+
+        let mut eth0 = Interface::new("eth0".to_owned());
+        eth0.interface_type = NetworkInterfaceType::Eth;
+
+        let mut eth1 = Interface::new("eth1".to_owned());
+        eth1.interface_type = NetworkInterfaceType::Eth;
+
+        let nw_config = NetworkConfig {
+            interfaces: BTreeMap::from([
+                ("eth0".into(), eth0),
+                ("eth1".into(), eth1),
+                ("bond0".into(), bond),
+            ]),
+            order: vec![NetworkOrderEntry::Iface("bond0".to_owned())],
+        };
+        assert_eq!(
+            String::try_from(nw_config).unwrap().trim(),
+            r#"
+iface bond0 inet manual
+	bond-mode active-backup
+	bond-miimon 250
+	bond-slaves eth0 eth1"#
+                .trim()
+        );
+    }
 }
diff --git a/proxmox-network-api/src/config/parser.rs b/proxmox-network-api/src/config/parser.rs
index 71c9ec0f..2b789f64 100644
--- a/proxmox-network-api/src/config/parser.rs
+++ b/proxmox-network-api/src/config/parser.rs
@@ -378,6 +378,12 @@ impl<R: BufRead> NetworkParser<R> {
                     interface.bond_xmit_hash_policy = Some(policy);
                     self.eat(Token::Newline)?;
                 }
+                Token::BondMiimon => {
+                    self.eat(Token::BondMiimon)?;
+                    let miimon = self.next_text()?.parse()?;
+                    interface.bond_miimon = Some(miimon);
+                    self.eat(Token::Newline)?;
+                }
                 Token::VlanId => {
                     self.eat(Token::VlanId)?;
                     let vlan_id = self.next_text()?.parse()?;
@@ -918,4 +924,21 @@ iface individual_name inet static
         assert_eq!(iface.method, Some(NetworkConfigMethod::Static));
         assert_eq!(iface.cidr, Some(String::from("10.0.0.100/16")));
     }
+
+    #[test]
+    fn test_network_config_parser_bond_miimon() {
+        let input = r#"
+iface bond0 inet manual
+	bond-slaves eth0 eth1
+	bond-mode active-backup
+	bond-miimon 200
+"#;
+
+        let mut parser = NetworkParser::new(input.as_bytes());
+        let config = parser.parse_interfaces(None).unwrap();
+
+        let iface = config.interfaces.get("bond0").unwrap();
+        assert_eq!(iface.interface_type, NetworkInterfaceType::Bond);
+        assert_eq!(iface.bond_miimon, Some(200));
+    }
 }
-- 
2.55.0





^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH proxmox-backup 3/3] api: network: reuse interface create/update methods from network-api
  2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
  2026-09-25 12:34 ` [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces Christoph Heiss
  2026-09-25 12:34 ` [PATCH proxmox 2/3] fix #6121: network-api: config: add support for `bond-miimon` option Christoph Heiss
@ 2026-09-25 12:34 ` Christoph Heiss
  2026-11-05  9:47 ` [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
  2026-11-09 11:08 ` Christian Ebner
  4 siblings, 0 replies; 10+ messages in thread
From: Christoph Heiss @ 2026-09-25 12:34 UTC (permalink / raw)
  To: pbs-devel

They are nearly identical in parameters and implementation, only that the
network-api crate uses a struct instead of a long list of single
parameters.

The only real difference are bit more strict checks, namely:
- the 'auto' method is now rejected for IPv4, which is IPv6 only
- enforces that the method is 'static' when explicitly setting CIDR/GW

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
In combination w/ the earlier patches in the series; also fixes #6121
[0].

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

 src/api2/node/network.rs | 674 ++-------------------------------------
 1 file changed, 18 insertions(+), 656 deletions(-)

diff --git a/src/api2/node/network.rs b/src/api2/node/network.rs
index 07ef4bb64..591b4b6e8 100644
--- a/src/api2/node/network.rs
+++ b/src/api2/node/network.rs
@@ -1,5 +1,4 @@
-use anyhow::{Error, bail};
-use serde::{Deserialize, Serialize};
+use anyhow::Error;
 use serde_json::{Value, to_value};
 
 use proxmox_router::{ApiMethod, Permission, Router, RpcEnvironment};
@@ -9,86 +8,14 @@ use pbs_api_types::{
     Authid, NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA,
 };
 
+use proxmox_config_digest::ConfigDigest;
 use proxmox_network_api::{
-    self as network, BondXmitHashPolicy, CIDR_V4_SCHEMA, CIDR_V6_SCHEMA, IP_V4_SCHEMA,
-    IP_V6_SCHEMA, Interface, LinuxBondMode, NETWORK_INTERFACE_ARRAY_SCHEMA,
-    NETWORK_INTERFACE_LIST_SCHEMA, NETWORK_INTERFACE_NAME_SCHEMA, NetworkConfig,
-    NetworkConfigMethod, NetworkInterfaceType, parse_vlan_id_from_name,
-    parse_vlan_raw_device_from_name,
+    self as network, DeletableInterfaceProperty, Interface, InterfaceUpdater,
+    NETWORK_INTERFACE_NAME_SCHEMA,
 };
 
 use proxmox_rest_server::WorkerTask;
 
-fn split_interface_list(list: &str) -> Result<Vec<String>, Error> {
-    let value = NETWORK_INTERFACE_ARRAY_SCHEMA.parse_property_string(list)?;
-    Ok(value
-        .as_array()
-        .unwrap()
-        .iter()
-        .map(|v| v.as_str().unwrap().to_string())
-        .collect())
-}
-
-fn check_duplicate_gateway_v4(config: &NetworkConfig, iface: &str) -> Result<(), Error> {
-    let current_gateway_v4 = config
-        .interfaces
-        .iter()
-        .find(|(_, interface)| interface.gateway.is_some())
-        .map(|(name, _)| name.to_string());
-
-    if let Some(current_gateway_v4) = current_gateway_v4 {
-        if current_gateway_v4 != iface {
-            bail!(
-                "Default IPv4 gateway already exists on interface '{}'",
-                current_gateway_v4
-            );
-        }
-    }
-    Ok(())
-}
-
-fn check_duplicate_gateway_v6(config: &NetworkConfig, iface: &str) -> Result<(), Error> {
-    let current_gateway_v6 = config
-        .interfaces
-        .iter()
-        .find(|(_, interface)| interface.gateway6.is_some())
-        .map(|(name, _)| name.to_string());
-
-    if let Some(current_gateway_v6) = current_gateway_v6 {
-        if current_gateway_v6 != iface {
-            bail!(
-                "Default IPv6 gateway already exists on interface '{}'",
-                current_gateway_v6
-            );
-        }
-    }
-    Ok(())
-}
-
-fn set_bridge_ports(iface: &mut Interface, ports: Vec<String>) -> Result<(), Error> {
-    if iface.interface_type != NetworkInterfaceType::Bridge {
-        bail!(
-            "interface '{}' is no bridge (type is {:?})",
-            iface.name,
-            iface.interface_type
-        );
-    }
-    iface.bridge_ports = Some(ports);
-    Ok(())
-}
-
-fn set_bond_slaves(iface: &mut Interface, slaves: Vec<String>) -> Result<(), Error> {
-    if iface.interface_type != NetworkInterfaceType::Bond {
-        bail!(
-            "interface '{}' is no bond (type is {:?})",
-            iface.name,
-            iface.interface_type
-        );
-    }
-    iface.slaves = Some(slaves);
-    Ok(())
-}
-
 #[api(
     input: {
         properties: {
@@ -175,89 +102,9 @@ pub fn read_interface(iface: String) -> Result<Value, Error> {
             iface: {
                 schema: NETWORK_INTERFACE_NAME_SCHEMA,
             },
-            "type": {
-                type: NetworkInterfaceType,
-                optional: true,
-            },
-            autostart: {
-                description: "Autostart interface.",
-                type: bool,
-                optional: true,
-            },
-            method: {
-                type: NetworkConfigMethod,
-                optional: true,
-            },
-            method6: {
-                type: NetworkConfigMethod,
-                optional: true,
-            },
-            comments: {
-                description: "Comments (inet, may span multiple lines)",
-                type: String,
-                optional: true,
-            },
-            comments6: {
-                description: "Comments (inet5, may span multiple lines)",
-                type: String,
-                optional: true,
-            },
-            cidr: {
-                schema: CIDR_V4_SCHEMA,
-                optional: true,
-            },
-            cidr6: {
-                schema: CIDR_V6_SCHEMA,
-                optional: true,
-            },
-            gateway: {
-                schema: IP_V4_SCHEMA,
-                optional: true,
-            },
-            gateway6: {
-                schema: IP_V6_SCHEMA,
-                optional: true,
-            },
-            mtu: {
-                description: "Maximum Transmission Unit.",
-                optional: true,
-                minimum: 46,
-                maximum: 65535,
-                default: 1500,
-            },
-            bridge_ports: {
-                schema: NETWORK_INTERFACE_LIST_SCHEMA,
-                optional: true,
-            },
-            bridge_vlan_aware: {
-                description: "Enable bridge vlan support.",
-                type: bool,
-                optional: true,
-            },
-            "vlan-id": {
-                description: "VLAN ID.",
-                type: u16,
-                optional: true,
-            },
-            "vlan-raw-device": {
-                schema: NETWORK_INTERFACE_NAME_SCHEMA,
-                optional: true,
-            },
-            bond_mode: {
-                type: LinuxBondMode,
-                optional: true,
-            },
-            "bond-primary": {
-                schema: NETWORK_INTERFACE_NAME_SCHEMA,
-                optional: true,
-            },
-            bond_xmit_hash_policy: {
-                type: BondXmitHashPolicy,
-                optional: true,
-            },
-            slaves: {
-                schema: NETWORK_INTERFACE_LIST_SCHEMA,
-                optional: true,
+            config: {
+                type: InterfaceUpdater,
+                flatten: true,
             },
         },
     },
@@ -266,210 +113,8 @@ pub fn read_interface(iface: String) -> Result<Value, Error> {
     },
 )]
 /// Create network interface configuration.
-#[allow(clippy::too_many_arguments)]
-pub fn create_interface(
-    iface: String,
-    autostart: Option<bool>,
-    method: Option<NetworkConfigMethod>,
-    method6: Option<NetworkConfigMethod>,
-    comments: Option<String>,
-    comments6: Option<String>,
-    cidr: Option<String>,
-    gateway: Option<String>,
-    cidr6: Option<String>,
-    gateway6: Option<String>,
-    mtu: Option<u64>,
-    bridge_ports: Option<String>,
-    bridge_vlan_aware: Option<bool>,
-    vlan_id: Option<u16>,
-    vlan_raw_device: Option<String>,
-    bond_mode: Option<LinuxBondMode>,
-    bond_primary: Option<String>,
-    bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
-    slaves: Option<String>,
-    param: Value,
-) -> Result<(), Error> {
-    let interface_type = pbs_tools::json::required_string_param(&param, "type")?;
-    let interface_type: NetworkInterfaceType = serde_json::from_value(interface_type.into())?;
-
-    let _lock = network::lock_config()?;
-
-    let (mut config, _digest) = network::config()?;
-
-    if config.interfaces.contains_key(&iface) {
-        bail!("interface '{}' already exists", iface);
-    }
-
-    let mut interface = Interface::new(iface.clone());
-    interface.interface_type = interface_type;
-
-    if let Some(autostart) = autostart {
-        interface.autostart = autostart;
-    }
-    if method.is_some() {
-        interface.method = method;
-    }
-    if method6.is_some() {
-        interface.method6 = method6;
-    }
-    if mtu.is_some() {
-        interface.mtu = mtu;
-    }
-    if comments.is_some() {
-        interface.comments = comments;
-    }
-    if comments6.is_some() {
-        interface.comments6 = comments6;
-    }
-
-    if let Some(cidr) = cidr {
-        let (_, _, is_v6) = network::parse_cidr(&cidr)?;
-        if is_v6 {
-            bail!("invalid address type (expected IPv4, got IPv6)");
-        }
-        interface.cidr = Some(cidr);
-    }
-
-    if let Some(cidr6) = cidr6 {
-        let (_, _, is_v6) = network::parse_cidr(&cidr6)?;
-        if !is_v6 {
-            bail!("invalid address type (expected IPv6, got IPv4)");
-        }
-        interface.cidr6 = Some(cidr6);
-    }
-
-    if let Some(gateway) = gateway {
-        let is_v6 = gateway.contains(':');
-        if is_v6 {
-            bail!("invalid address type (expected IPv4, got IPv6)");
-        }
-        check_duplicate_gateway_v4(&config, &iface)?;
-        interface.gateway = Some(gateway);
-    }
-
-    if let Some(gateway6) = gateway6 {
-        let is_v6 = gateway6.contains(':');
-        if !is_v6 {
-            bail!("invalid address type (expected IPv6, got IPv4)");
-        }
-        check_duplicate_gateway_v6(&config, &iface)?;
-        interface.gateway6 = Some(gateway6);
-    }
-
-    match interface_type {
-        NetworkInterfaceType::Bridge => {
-            if let Some(ports) = bridge_ports {
-                let ports = split_interface_list(&ports)?;
-                set_bridge_ports(&mut interface, ports)?;
-            }
-            if bridge_vlan_aware.is_some() {
-                interface.bridge_vlan_aware = bridge_vlan_aware;
-            }
-        }
-        NetworkInterfaceType::Bond => {
-            if let Some(mode) = bond_mode {
-                interface.bond_mode = bond_mode;
-                if bond_primary.is_some() {
-                    if mode != LinuxBondMode::ActiveBackup {
-                        bail!("bond-primary is only valid with Active/Backup mode");
-                    }
-                    interface.bond_primary = bond_primary;
-                }
-                if bond_xmit_hash_policy.is_some() {
-                    if mode != LinuxBondMode::Ieee802_3ad && mode != LinuxBondMode::BalanceXor {
-                        bail!(
-                            "bond_xmit_hash_policy is only valid with LACP(802.3ad) or balance-xor mode"
-                        );
-                    }
-                    interface.bond_xmit_hash_policy = bond_xmit_hash_policy;
-                }
-            }
-            if let Some(slaves) = slaves {
-                let slaves = split_interface_list(&slaves)?;
-                set_bond_slaves(&mut interface, slaves)?;
-            }
-        }
-        NetworkInterfaceType::Vlan => {
-            if vlan_id.is_none() && parse_vlan_id_from_name(&iface).is_none() {
-                bail!("vlan-id must be set");
-            }
-            interface.vlan_id = vlan_id;
-
-            if let Some(dev) = vlan_raw_device
-                .as_deref()
-                .or_else(|| parse_vlan_raw_device_from_name(&iface))
-            {
-                if !config.interfaces.contains_key(dev) {
-                    bail!("vlan-raw-device {dev} does not exist");
-                }
-            } else {
-                bail!("vlan-raw-device must be set");
-            }
-            interface.vlan_raw_device = vlan_raw_device;
-        }
-        _ => bail!(
-            "creating network interface type '{:?}' is not supported",
-            interface_type
-        ),
-    }
-
-    if interface.cidr.is_some() || interface.gateway.is_some() {
-        interface.method = Some(NetworkConfigMethod::Static);
-    } else if interface.method.is_none() {
-        interface.method = Some(NetworkConfigMethod::Manual);
-    }
-
-    if interface.cidr6.is_some() || interface.gateway6.is_some() {
-        interface.method6 = Some(NetworkConfigMethod::Static);
-    } else if interface.method6.is_none() {
-        interface.method6 = Some(NetworkConfigMethod::Manual);
-    }
-
-    config.interfaces.insert(iface, interface);
-
-    network::save_config(&config)?;
-
-    Ok(())
-}
-
-#[api()]
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
-/// Deletable property name
-pub enum DeletableProperty {
-    /// Delete the IPv4 address property.
-    Cidr,
-    /// Delete the IPv6 address property.
-    Cidr6,
-    /// Delete the IPv4 gateway property.
-    Gateway,
-    /// Delete the IPv6 gateway property.
-    Gateway6,
-    /// Delete the whole IPv4 configuration entry.
-    Method,
-    /// Delete the whole IPv6 configuration entry.
-    Method6,
-    /// Delete IPv4 comments
-    Comments,
-    /// Delete IPv6 comments
-    Comments6,
-    /// Delete mtu.
-    Mtu,
-    /// Delete autostart flag
-    Autostart,
-    /// Delete bridge ports (set to 'none')
-    #[serde(rename = "bridge_ports")]
-    BridgePorts,
-    /// Delete bridge-vlan-aware flag
-    #[serde(rename = "bridge_vlan_aware")]
-    BridgeVlanAware,
-    /// Delete bond-slaves (set to 'none')
-    Slaves,
-    /// Delete bond-primary
-    BondPrimary,
-    /// Delete bond transmit hash policy
-    #[serde(rename = "bond_xmit_hash_policy")]
-    BondXmitHashPolicy,
+pub fn create_interface(iface: String, config: InterfaceUpdater) -> Result<(), Error> {
+    proxmox_network_api::create_interface(iface, config)
 }
 
 #[api(
@@ -482,101 +127,21 @@ pub enum DeletableProperty {
             iface: {
                 schema: NETWORK_INTERFACE_NAME_SCHEMA,
             },
-            "type": {
-                type: NetworkInterfaceType,
-                optional: true,
-            },
-            autostart: {
-                description: "Autostart interface.",
-                type: bool,
-                optional: true,
-            },
-            method: {
-                type: NetworkConfigMethod,
-                optional: true,
-            },
-            method6: {
-                type: NetworkConfigMethod,
-                optional: true,
-            },
-            comments: {
-                description: "Comments (inet, may span multiple lines)",
-                type: String,
-                optional: true,
-            },
-            comments6: {
-                description: "Comments (inet5, may span multiple lines)",
-                type: String,
-                optional: true,
-            },
-            cidr: {
-                schema: CIDR_V4_SCHEMA,
-                optional: true,
-            },
-            cidr6: {
-                schema: CIDR_V6_SCHEMA,
-                optional: true,
-            },
-            gateway: {
-                schema: IP_V4_SCHEMA,
-                optional: true,
-            },
-            gateway6: {
-                schema: IP_V6_SCHEMA,
-                optional: true,
-            },
-            mtu: {
-                description: "Maximum Transmission Unit.",
-                optional: true,
-                minimum: 46,
-                maximum: 65535,
-                default: 1500,
-            },
-            bridge_ports: {
-                schema: NETWORK_INTERFACE_LIST_SCHEMA,
-                optional: true,
-            },
-            bridge_vlan_aware: {
-                description: "Enable bridge vlan support.",
-                type: bool,
-                optional: true,
-            },
-            "vlan-id": {
-                description: "VLAN ID.",
-                type: u16,
-                optional: true,
-            },
-            "vlan-raw-device": {
-                schema: NETWORK_INTERFACE_NAME_SCHEMA,
-                optional: true,
-            },
-            bond_mode: {
-                type: LinuxBondMode,
-                optional: true,
-            },
-            "bond-primary": {
-                schema: NETWORK_INTERFACE_NAME_SCHEMA,
-                optional: true,
-            },
-            bond_xmit_hash_policy: {
-                type: BondXmitHashPolicy,
-                optional: true,
-            },
-            slaves: {
-                schema: NETWORK_INTERFACE_LIST_SCHEMA,
-                optional: true,
+            update: {
+                type: InterfaceUpdater,
+                flatten: true,
             },
             delete: {
                 description: "List of properties to delete.",
                 type: Array,
                 optional: true,
                 items: {
-                    type: DeletableProperty,
+                    type: DeletableInterfaceProperty,
                 }
             },
             digest: {
+                type: ConfigDigest,
                 optional: true,
-                schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
             },
         },
     },
@@ -585,216 +150,13 @@ pub enum DeletableProperty {
     },
 )]
 /// Update network interface config.
-#[allow(clippy::too_many_arguments)]
 pub fn update_interface(
     iface: String,
-    autostart: Option<bool>,
-    method: Option<NetworkConfigMethod>,
-    method6: Option<NetworkConfigMethod>,
-    comments: Option<String>,
-    comments6: Option<String>,
-    cidr: Option<String>,
-    gateway: Option<String>,
-    cidr6: Option<String>,
-    gateway6: Option<String>,
-    mtu: Option<u64>,
-    bridge_ports: Option<String>,
-    bridge_vlan_aware: Option<bool>,
-    vlan_id: Option<u16>,
-    vlan_raw_device: Option<String>,
-    bond_mode: Option<LinuxBondMode>,
-    bond_primary: Option<String>,
-    bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
-    slaves: Option<String>,
-    delete: Option<Vec<DeletableProperty>>,
-    digest: Option<String>,
-    param: Value,
+    update: InterfaceUpdater,
+    delete: Option<Vec<DeletableInterfaceProperty>>,
+    digest: Option<ConfigDigest>,
 ) -> Result<(), Error> {
-    let _lock = network::lock_config()?;
-
-    let (mut config, expected_digest) = network::config()?;
-
-    pbs_config::detect_modified_configuration_file(digest, &expected_digest)?;
-
-    if gateway.is_some() {
-        check_duplicate_gateway_v4(&config, &iface)?;
-    }
-    if gateway6.is_some() {
-        check_duplicate_gateway_v6(&config, &iface)?;
-    }
-
-    if let Some(dev) = vlan_raw_device
-        .as_deref()
-        .or_else(|| parse_vlan_raw_device_from_name(&iface))
-    {
-        if !config.interfaces.contains_key(dev) {
-            bail!("vlan-raw-device {dev} does not exist");
-        }
-    }
-
-    let interface = config.lookup_mut(&iface)?;
-
-    if let Some(interface_type) = param.get("type") {
-        let interface_type = NetworkInterfaceType::deserialize(interface_type)?;
-        if interface_type != interface.interface_type {
-            bail!(
-                "got unexpected interface type ({:?} != {:?})",
-                interface_type,
-                interface.interface_type
-            );
-        }
-    }
-
-    if let Some(delete) = delete {
-        for delete_prop in delete {
-            match delete_prop {
-                DeletableProperty::Cidr => {
-                    interface.cidr = None;
-                }
-                DeletableProperty::Cidr6 => {
-                    interface.cidr6 = None;
-                }
-                DeletableProperty::Gateway => {
-                    interface.gateway = None;
-                }
-                DeletableProperty::Gateway6 => {
-                    interface.gateway6 = None;
-                }
-                DeletableProperty::Method => {
-                    interface.method = None;
-                }
-                DeletableProperty::Method6 => {
-                    interface.method6 = None;
-                }
-                DeletableProperty::Comments => {
-                    interface.comments = None;
-                }
-                DeletableProperty::Comments6 => {
-                    interface.comments6 = None;
-                }
-                DeletableProperty::Mtu => {
-                    interface.mtu = None;
-                }
-                DeletableProperty::Autostart => {
-                    interface.autostart = false;
-                }
-                DeletableProperty::BridgePorts => {
-                    set_bridge_ports(interface, Vec::new())?;
-                }
-                DeletableProperty::BridgeVlanAware => {
-                    interface.bridge_vlan_aware = None;
-                }
-                DeletableProperty::Slaves => {
-                    set_bond_slaves(interface, Vec::new())?;
-                }
-                DeletableProperty::BondPrimary => {
-                    interface.bond_primary = None;
-                }
-                DeletableProperty::BondXmitHashPolicy => interface.bond_xmit_hash_policy = None,
-            }
-        }
-    }
-
-    if let Some(autostart) = autostart {
-        interface.autostart = autostart;
-    }
-    if method.is_some() {
-        interface.method = method;
-    }
-    if method6.is_some() {
-        interface.method6 = method6;
-    }
-    if mtu.is_some() {
-        interface.mtu = mtu;
-    }
-    if let Some(ports) = bridge_ports {
-        let ports = split_interface_list(&ports)?;
-        set_bridge_ports(interface, ports)?;
-    }
-    if bridge_vlan_aware.is_some() {
-        interface.bridge_vlan_aware = bridge_vlan_aware;
-    }
-    if let Some(slaves) = slaves {
-        let slaves = split_interface_list(&slaves)?;
-        set_bond_slaves(interface, slaves)?;
-    }
-    if let Some(mode) = bond_mode {
-        interface.bond_mode = bond_mode;
-        if bond_primary.is_some() {
-            if mode != LinuxBondMode::ActiveBackup {
-                bail!("bond-primary is only valid with Active/Backup mode");
-            }
-            interface.bond_primary = bond_primary;
-        }
-        if bond_xmit_hash_policy.is_some() {
-            if mode != LinuxBondMode::Ieee802_3ad && mode != LinuxBondMode::BalanceXor {
-                bail!("bond_xmit_hash_policy is only valid with LACP(802.3ad) or balance-xor mode");
-            }
-            interface.bond_xmit_hash_policy = bond_xmit_hash_policy;
-        }
-    }
-
-    if let Some(cidr) = cidr {
-        let (_, _, is_v6) = network::parse_cidr(&cidr)?;
-        if is_v6 {
-            bail!("invalid address type (expected IPv4, got IPv6)");
-        }
-        interface.cidr = Some(cidr);
-    }
-
-    if let Some(cidr6) = cidr6 {
-        let (_, _, is_v6) = network::parse_cidr(&cidr6)?;
-        if !is_v6 {
-            bail!("invalid address type (expected IPv6, got IPv4)");
-        }
-        interface.cidr6 = Some(cidr6);
-    }
-
-    if let Some(gateway) = gateway {
-        let is_v6 = gateway.contains(':');
-        if is_v6 {
-            bail!("invalid address type (expected IPv4, got IPv6)");
-        }
-        interface.gateway = Some(gateway);
-    }
-
-    if let Some(gateway6) = gateway6 {
-        let is_v6 = gateway6.contains(':');
-        if !is_v6 {
-            bail!("invalid address type (expected IPv6, got IPv4)");
-        }
-        interface.gateway6 = Some(gateway6);
-    }
-
-    if comments.is_some() {
-        interface.comments = comments;
-    }
-    if comments6.is_some() {
-        interface.comments6 = comments6;
-    }
-
-    if interface.cidr.is_some() || interface.gateway.is_some() {
-        interface.method = Some(NetworkConfigMethod::Static);
-    } else {
-        interface.method = Some(NetworkConfigMethod::Manual);
-    }
-
-    if interface.cidr6.is_some() || interface.gateway6.is_some() {
-        interface.method6 = Some(NetworkConfigMethod::Static);
-    } else if interface.method6.is_none() {
-        interface.method6 = Some(NetworkConfigMethod::Manual);
-    }
-
-    if vlan_id.is_some() {
-        interface.vlan_id = vlan_id;
-    }
-    if vlan_raw_device.is_some() {
-        interface.vlan_raw_device = vlan_raw_device;
-    }
-
-    network::save_config(&config)?;
-
-    Ok(())
+    proxmox_network_api::update_interface(iface, update, delete, digest)
 }
 
 #[api(
-- 
2.55.0





^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces
  2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
                   ` (2 preceding siblings ...)
  2026-09-25 12:34 ` [PATCH proxmox-backup 3/3] api: network: reuse interface create/update methods from network-api Christoph Heiss
@ 2026-11-05  9:47 ` Christoph Heiss
  2026-11-09 11:08 ` Christian Ebner
  4 siblings, 0 replies; 10+ messages in thread
From: Christoph Heiss @ 2026-11-05  9:47 UTC (permalink / raw)
  To: pbs-devel

Ping, still applies.

On 9/25/26 14:35, Christoph Heiss wrote:
> Fixes #6121 [0], for both PBS and (through proxmox-network-api) PDM.
> 
> Adds a new 'bond-miimon' option to the network interface API for
> specifying the link monitoring interval.
> 
> This is needed so that (at least) in active-backup mode, the bond
> correctly switches over to the backup link if the active one goes down.
> 
> [0] https://bugzilla.proxmox.com/show_bug.cgi?id=6121
> 
> proxmox:
> 
> Christoph Heiss (2):
>    fix #6121: network-api: api: add `bond-miimon` option for interfaces
>    fix #6121: network-api: config: add support for `bond-miimon` option
> 
>   proxmox-network-api/src/api_impl.rs      |  9 +++
>   proxmox-network-api/src/api_types.rs     | 18 ++++++
>   proxmox-network-api/src/config/lexer.rs  |  3 +
>   proxmox-network-api/src/config/mod.rs    | 70 ++++++++++++++++++++++++
>   proxmox-network-api/src/config/parser.rs | 23 ++++++++
>   5 files changed, 123 insertions(+)
> 
> proxmox-backup:
> 
> Christoph Heiss (1):
>    api: network: reuse interface create/update methods from network-api
> 
>   src/api2/node/network.rs | 674 ++-------------------------------------
>   1 file changed, 18 insertions(+), 656 deletions(-)





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces
  2026-09-25 12:34 ` [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces Christoph Heiss
@ 2026-11-09 10:15   ` Christian Ebner
  2026-11-09 13:28     ` Christoph Heiss
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Ebner @ 2026-11-09 10:15 UTC (permalink / raw)
  To: Christoph Heiss, pbs-devel

one question inline.

On 9/25/26 2:35 PM, Christoph Heiss wrote:
> Partially fixes #6121 [0].
> 
> Adds a new 'bond-miimon' option to the network interface API for
> specifying the link monitoring interval.
> 
> [0] https://bugzilla.proxmox.com/show_bug.cgi?id=6121
> 
> Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
> ---
>   proxmox-network-api/src/api_impl.rs  |  9 +++++++++
>   proxmox-network-api/src/api_types.rs | 18 ++++++++++++++++++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/proxmox-network-api/src/api_impl.rs b/proxmox-network-api/src/api_impl.rs
> index 78f499c5..0a603017 100644
> --- a/proxmox-network-api/src/api_impl.rs
> +++ b/proxmox-network-api/src/api_impl.rs
> @@ -162,6 +162,9 @@ pub fn create_interface(iface: String, config: InterfaceUpdater) -> Result<(), E
>                       interface.bond_xmit_hash_policy = config.bond_xmit_hash_policy;
>                   }
>               }
> +            if config.bond_miimon.is_some() {
> +                interface.bond_miimon = config.bond_miimon;
> +            }
>               if let Some(slaves) = &config.slaves {
>                   interface.set_bond_slave_list(slaves)?;
>               }
> @@ -295,6 +298,9 @@ pub fn update_interface(
>                   DeletableInterfaceProperty::BondXmitHashPolicy => {
>                       interface.bond_xmit_hash_policy = None
>                   }
> +                DeletableInterfaceProperty::BondMiimon => {
> +                    interface.bond_miimon = None;
> +                }
>               }
>           }
>       }
> @@ -335,6 +341,9 @@ pub fn update_interface(
>               }
>               interface.bond_xmit_hash_policy = update.bond_xmit_hash_policy;
>           }
> +        if update.bond_miimon.is_some() {
> +            interface.bond_miimon = update.bond_miimon;
> +        }
>       }
>   
>       if let Some(cidr) = update.cidr {
> diff --git a/proxmox-network-api/src/api_types.rs b/proxmox-network-api/src/api_types.rs
> index f2467f1e..471f20e8 100644
> --- a/proxmox-network-api/src/api_types.rs
> +++ b/proxmox-network-api/src/api_types.rs
> @@ -228,6 +228,12 @@ pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema =
>               type: BondXmitHashPolicy,
>               optional: true,
>           },
> +        "bond-miimon": {
> +            description: "Link monitoring interval in milliseconds for bond interfaces.",
> +            type: u8,

isn't this to restrictive?

At least the Kernel seem to accept larger values AFAICT:
- 
https://github.com/torvalds/linux/blob/master/drivers/net/bonding/bond_options.c#L149
- 
https://github.com/torvalds/linux/blob/master/drivers/net/bonding/bond_main.c#L6174

> +            optional: true,
> +            default: 100,
> +        },
>           altnames: {
>               description: "List of altnames for this interface",
>               type: Array,
> @@ -302,6 +308,8 @@ pub struct Interface {
>       pub bond_primary: Option<String>,
>       #[serde(skip_serializing_if = "Option::is_none")]
>       pub bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
> +    #[serde(rename = "bond-miimon", skip_serializing_if = "Option::is_none")]
> +    pub bond_miimon: Option<u8>,
>   
>       #[serde(default, skip_serializing_if = "Vec::is_empty")]
>       pub altnames: Vec<String>,
> @@ -333,6 +341,7 @@ impl Interface {
>               bond_mode: None,
>               bond_primary: None,
>               bond_xmit_hash_policy: None,
> +            bond_miimon: None,
>               altnames: Vec::new(),
>           }
>       }
> @@ -425,6 +434,8 @@ pub enum DeletableInterfaceProperty {
>       /// Delete bond transmit hash policy
>       #[serde(rename = "bond_xmit_hash_policy")]
>       BondXmitHashPolicy,
> +    /// Delete bond miimon (set to default 100)
> +    BondMiimon,
>   }
>   
>   #[api(
> @@ -509,6 +520,12 @@ pub enum DeletableInterfaceProperty {
>                   type: BondXmitHashPolicy,
>                   optional: true,
>               },
> +            "bond-miimon": {
> +                description: "Link monitoring interval in milliseconds for bond interfaces.",
> +                type: u8,
> +                optional: true,
> +                default: 100,
> +            },
>               slaves: {
>                   schema: NETWORK_INTERFACE_LIST_SCHEMA,
>                   optional: true,
> @@ -542,5 +559,6 @@ pub struct InterfaceUpdater {
>       pub bond_primary: Option<String>,
>       #[serde(rename = "bond_xmit_hash_policy")]
>       pub bond_xmit_hash_policy: Option<BondXmitHashPolicy>,
> +    pub bond_miimon: Option<u8>,
>       pub slaves: Option<String>,
>   }





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces
  2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
                   ` (3 preceding siblings ...)
  2026-11-05  9:47 ` [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
@ 2026-11-09 11:08 ` Christian Ebner
  4 siblings, 0 replies; 10+ messages in thread
From: Christian Ebner @ 2026-11-09 11:08 UTC (permalink / raw)
  To: Christoph Heiss, pbs-devel

On 9/25/26 2:35 PM, Christoph Heiss wrote:
> Fixes #6121 [0], for both PBS and (through proxmox-network-api) PDM.
> 
> Adds a new 'bond-miimon' option to the network interface API for
> specifying the link monitoring interval.
> 
> This is needed so that (at least) in active-backup mode, the bond
> correctly switches over to the backup link if the active one goes down.
> 
> [0] https://bugzilla.proxmox.com/show_bug.cgi?id=6121

With the to restrictive u8 type for bond-miimon fixed, consider:

Reviewed-by: Christian Ebner <c.ebner@proxmox.com>
Tested-by: Christian Ebner <c.ebner@proxmox.com>




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces
  2026-11-09 10:15   ` Christian Ebner
@ 2026-11-09 13:28     ` Christoph Heiss
  2026-11-09 14:05       ` Christian Ebner
  0 siblings, 1 reply; 10+ messages in thread
From: Christoph Heiss @ 2026-11-09 13:28 UTC (permalink / raw)
  To: Christian Ebner; +Cc: pbs-devel

Thanks for the review!

On 11/9/26 11:15, Christian Ebner wrote:
> one question inline.
> 
> On 9/25/26 2:35 PM, Christoph Heiss wrote:
>> [..]
>> --- a/proxmox-network-api/src/api_types.rs
>> +++ b/proxmox-network-api/src/api_types.rs
>> @@ -228,6 +228,12 @@ pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema =
>>               type: BondXmitHashPolicy,
>>               optional: true,
>>           },
>> +        "bond-miimon": {
>> +            description: "Link monitoring interval in milliseconds 
>> for bond interfaces.",
>> +            type: u8,
> 
> isn't this to restrictive?
> 
> At least the Kernel seem to accept larger values AFAICT:
> - https://github.com/torvalds/linux/blob/master/drivers/net/bonding/ 
> bond_options.c#L149
> - https://github.com/torvalds/linux/blob/master/drivers/net/bonding/ 
> bond_main.c#L6174

Good catch.

At least ifupdown2 says that the value range should be to 0-255 [0] - 
which is what I did go off - but actually never enforces that. I.e. the 
value is never validated against `validrange`, it's just a documentation 
thing at the end.

The netlink interface also indeed accepts a u32 [1] FWIW, so that's the 
right thing to do.

E.g. setting up `/etc/network/interfaces` with

   auto bond0
   iface bond0 inet manual
     bond-slaves nic1 foo
     bond-miimon 5000
     bond-mode 802.3ad

works just fine, `cat /sys/class/net/bond0/bonding/miimon` also shows 
the correct value.

I'll quickly send a v2 with that changed.

[0] 
https://github.com/CumulusNetworks/ifupdown2/blob/master/ifupdown2/addons/bond.py#L80-L85 

[1] 
https://github.com/torvalds/linux/blob/7475ea8b58616b33c04afb976cf0fbaad9dd63fb/drivers/net/bonding/bond_netlink.c#L255

> 
>> +            optional: true,
>> +            default: 100,
>> +        },





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces
  2026-11-09 13:28     ` Christoph Heiss
@ 2026-11-09 14:05       ` Christian Ebner
  2026-11-09 14:10         ` Christoph Heiss
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Ebner @ 2026-11-09 14:05 UTC (permalink / raw)
  To: Christoph Heiss; +Cc: pbs-devel

On 11/9/26 2:28 PM, Christoph Heiss wrote:
> Thanks for the review!
> 
> On 11/9/26 11:15, Christian Ebner wrote:
>> one question inline.
>>
>> On 9/25/26 2:35 PM, Christoph Heiss wrote:
>>> [..]
>>> --- a/proxmox-network-api/src/api_types.rs
>>> +++ b/proxmox-network-api/src/api_types.rs
>>> @@ -228,6 +228,12 @@ pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema =
>>>               type: BondXmitHashPolicy,
>>>               optional: true,
>>>           },
>>> +        "bond-miimon": {
>>> +            description: "Link monitoring interval in milliseconds 
>>> for bond interfaces.",
>>> +            type: u8,
>>
>> isn't this to restrictive?
>>
>> At least the Kernel seem to accept larger values AFAICT:
>> - https://github.com/torvalds/linux/blob/master/drivers/net/bonding/ 
>> bond_options.c#L149
>> - https://github.com/torvalds/linux/blob/master/drivers/net/bonding/ 
>> bond_main.c#L6174
> 
> Good catch.
> 
> At least ifupdown2 says that the value range should be to 0-255 [0] - 
> which is what I did go off - but actually never enforces that. I.e. the 
> value is never validated against `validrange`, it's just a documentation 
> thing at the end.
> 
> The netlink interface also indeed accepts a u32 [1] FWIW, so that's the 
> right thing to do.
> 
> E.g. setting up `/etc/network/interfaces` with
> 
>    auto bond0
>    iface bond0 inet manual
>      bond-slaves nic1 foo
>      bond-miimon 5000
>      bond-mode 802.3ad
> 
> works just fine, `cat /sys/class/net/bond0/bonding/miimon` also shows 
> the correct value.
> 
> I'll quickly send a v2 with that changed.
> 
> [0] https://github.com/CumulusNetworks/ifupdown2/blob/master/ifupdown2/ 
> addons/bond.py#L80-L85
> [1] https://github.com/torvalds/linux/ 
> blob/7475ea8b58616b33c04afb976cf0fbaad9dd63fb/drivers/net/bonding/ 
> bond_netlink.c#L255
The actual limit enforced is i32::MAX afaict, so best to store as u32 
and check for i32::MAX not being exceeded?




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces
  2026-11-09 14:05       ` Christian Ebner
@ 2026-11-09 14:10         ` Christoph Heiss
  0 siblings, 0 replies; 10+ messages in thread
From: Christoph Heiss @ 2026-11-09 14:10 UTC (permalink / raw)
  To: Christian Ebner; +Cc: pbs-devel

On 11/9/26 15:05, Christian Ebner wrote:
> On 11/9/26 2:28 PM, Christoph Heiss wrote:
>> [..]
>>
>> Good catch.
>>
>> At least ifupdown2 says that the value range should be to 0-255 [0] - 
>> which is what I did go off - but actually never enforces that. I.e. 
>> the value is never validated against `validrange`, it's just a 
>> documentation thing at the end.
>>
>> The netlink interface also indeed accepts a u32 [1] FWIW, so that's 
>> the right thing to do.
>>
>> E.g. setting up `/etc/network/interfaces` with
>>
>>    auto bond0
>>    iface bond0 inet manual
>>      bond-slaves nic1 foo
>>      bond-miimon 5000
>>      bond-mode 802.3ad
>>
>> works just fine, `cat /sys/class/net/bond0/bonding/miimon` also shows 
>> the correct value.
>>
>> I'll quickly send a v2 with that changed.
>>
>> [0] https://github.com/CumulusNetworks/ifupdown2/blob/master/ 
>> ifupdown2/ addons/bond.py#L80-L85
>> [1] https://github.com/torvalds/linux/ 
>> blob/7475ea8b58616b33c04afb976cf0fbaad9dd63fb/drivers/net/bonding/ 
>> bond_netlink.c#L255
> The actual limit enforced is i32::MAX afaict, so best to store as u32 
> and check for i32::MAX not being exceeded?

Yep, that will be exactly my approach :^)




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-11-09 14:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-25 12:34 [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
2026-09-25 12:34 ` [PATCH proxmox 1/3] fix #6121: network-api: api: add `bond-miimon` option for interfaces Christoph Heiss
2026-11-09 10:15   ` Christian Ebner
2026-11-09 13:28     ` Christoph Heiss
2026-11-09 14:05       ` Christian Ebner
2026-11-09 14:10         ` Christoph Heiss
2026-09-25 12:34 ` [PATCH proxmox 2/3] fix #6121: network-api: config: add support for `bond-miimon` option Christoph Heiss
2026-09-25 12:34 ` [PATCH proxmox-backup 3/3] api: network: reuse interface create/update methods from network-api Christoph Heiss
2026-11-05  9:47 ` [PATCH proxmox{,-backup} 0/3] fix #6121: add 'bond-miimon' option for network interfaces Christoph Heiss
2026-11-09 11:08 ` Christian Ebner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal