* [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
* 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 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
* [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(¶m, "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{,-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
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.