vmm: allow net devices without ip and mask
This change enables easier integration with third-party tools by removing the requirement for a dummy IP address when configuring tap devices. The modification applies to both CLI and API interactions. Previously, cloud-hypervisor would automatically set a default static IP address (192.168.249.1) if none was provided. This could lead to: * multiple devices without explicit IP configurations would end up with the same default IP * unnecessary inclusion of this IP in firewall rules * the IP address could clash with host networking and routing This introduces a new constraint: When providing an IP, the mask must also be provided. Removes warnings introduced in #7179. Closes issue #7083. Signed-off-by: Maximilian Güntner <code@mguentner.de>
This commit is contained in:
parent
d28d9eb34e
commit
66aa0743f0
5 changed files with 58 additions and 51 deletions
|
|
@ -36,7 +36,7 @@ struct OptionParserValue {
|
|||
requires_value: bool,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum OptionParserError {
|
||||
#[error("unknown option: {0}")]
|
||||
UnknownOption(String),
|
||||
|
|
|
|||
14
src/main.rs
14
src/main.rs
|
|
@ -1336,20 +1336,6 @@ mod unit_tests {
|
|||
}"#,
|
||||
true,
|
||||
),
|
||||
(
|
||||
vec![
|
||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||
"--net",
|
||||
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4",
|
||||
],
|
||||
r#"{
|
||||
"payload": {"kernel": "/path/to/kernel"},
|
||||
"net": [
|
||||
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4"}
|
||||
]
|
||||
}"#,
|
||||
true,
|
||||
),
|
||||
(
|
||||
vec![
|
||||
"cloud-hypervisor", "--kernel", "/path/to/kernel",
|
||||
|
|
|
|||
|
|
@ -357,6 +357,10 @@ pub enum ValidationError {
|
|||
InvalidIvshmemPath,
|
||||
#[error("Payload configuration is not bootable")]
|
||||
PayloadError(#[from] PayloadConfigError),
|
||||
#[error("Mask provided without an IP")]
|
||||
MaskProvidedWithoutIp,
|
||||
#[error("IP provided without a mask")]
|
||||
IpProvidedWithoutMask,
|
||||
}
|
||||
|
||||
type ValidationResult<T> = std::result::Result<T, ValidationError>;
|
||||
|
|
@ -1331,14 +1335,9 @@ impl NetConfig {
|
|||
parser.parse(net).map_err(Error::ParseNetwork)?;
|
||||
|
||||
let tap = parser.get("tap");
|
||||
let ip = parser
|
||||
.convert("ip")
|
||||
.map_err(Error::ParseNetwork)?
|
||||
.unwrap_or_else(default_netconfig_ip);
|
||||
let mask = parser
|
||||
.convert("mask")
|
||||
.map_err(Error::ParseNetwork)?
|
||||
.unwrap_or_else(default_netconfig_mask);
|
||||
let ip = parser.convert("ip").map_err(Error::ParseNetwork)?;
|
||||
let mask = parser.convert("mask").map_err(Error::ParseNetwork)?;
|
||||
|
||||
let mac = parser
|
||||
.convert("mac")
|
||||
.map_err(Error::ParseNetwork)?
|
||||
|
|
@ -1515,6 +1514,14 @@ impl NetConfig {
|
|||
return Err(ValidationError::NoHardwareChecksumOffload);
|
||||
}
|
||||
|
||||
if self.mask.is_some() && self.ip.is_none() {
|
||||
return Err(ValidationError::MaskProvidedWithoutIp);
|
||||
}
|
||||
|
||||
if self.ip.is_some() && self.mask.is_none() {
|
||||
return Err(ValidationError::IpProvidedWithoutMask);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -3177,7 +3184,6 @@ impl Drop for VmConfig {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use net_util::MacAddr;
|
||||
|
|
@ -3507,8 +3513,8 @@ mod tests {
|
|||
fn net_fixture() -> NetConfig {
|
||||
NetConfig {
|
||||
tap: None,
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 249, 1)),
|
||||
mask: IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0)),
|
||||
ip: None,
|
||||
mask: None,
|
||||
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
|
||||
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
|
||||
mtu: None,
|
||||
|
|
@ -3550,8 +3556,8 @@ mod tests {
|
|||
)?,
|
||||
NetConfig {
|
||||
tap: Some("tap0".to_owned()),
|
||||
ip: "192.168.100.1".parse().unwrap(),
|
||||
mask: "255.255.255.128".parse().unwrap(),
|
||||
ip: Some("192.168.100.1".parse().unwrap()),
|
||||
mask: Some("255.255.255.128".parse().unwrap()),
|
||||
..net_fixture()
|
||||
}
|
||||
);
|
||||
|
|
@ -3589,6 +3595,15 @@ mod tests {
|
|||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
NetConfig::parse("mac=de:ad:be:ef:12:34,mask=255.255.255.0")?,
|
||||
NetConfig {
|
||||
mask: Some("255.255.255.0".parse().unwrap()),
|
||||
host_mac: None,
|
||||
..net_fixture()
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -4289,6 +4304,28 @@ mod tests {
|
|||
Err(ValidationError::NoHardwareChecksumOffload)
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.net = Some(vec![NetConfig {
|
||||
ip: None,
|
||||
mask: Some("255.255.255.0".parse().unwrap()),
|
||||
..net_fixture()
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::MaskProvidedWithoutIp)
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.net = Some(vec![NetConfig {
|
||||
ip: Some("192.1.33.7".parse().unwrap()),
|
||||
mask: None,
|
||||
..net_fixture()
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::IpProvidedWithoutMask)
|
||||
);
|
||||
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.fs = Some(vec![fs_fixture()]);
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -2904,8 +2904,8 @@ impl DeviceManager {
|
|||
virtio_devices::Net::new(
|
||||
id.clone(),
|
||||
Some(tap_if_name),
|
||||
Some(net_cfg.ip),
|
||||
Some(net_cfg.mask),
|
||||
net_cfg.ip,
|
||||
net_cfg.mask,
|
||||
Some(net_cfg.mac),
|
||||
&mut net_cfg.host_mac,
|
||||
net_cfg.mtu,
|
||||
|
|
@ -2955,8 +2955,8 @@ impl DeviceManager {
|
|||
virtio_devices::Net::new(
|
||||
id.clone(),
|
||||
None,
|
||||
Some(net_cfg.ip),
|
||||
Some(net_cfg.mask),
|
||||
net_cfg.ip,
|
||||
net_cfg.mask,
|
||||
Some(net_cfg.mac),
|
||||
&mut net_cfg.host_mac,
|
||||
net_cfg.mtu,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::net::IpAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
use std::str::FromStr;
|
||||
|
|
@ -303,10 +303,8 @@ pub fn default_diskconfig_queue_size() -> u16 {
|
|||
pub struct NetConfig {
|
||||
#[serde(default = "default_netconfig_tap")]
|
||||
pub tap: Option<String>,
|
||||
#[serde(default = "default_netconfig_ip")]
|
||||
pub ip: IpAddr,
|
||||
#[serde(default = "default_netconfig_mask")]
|
||||
pub mask: IpAddr,
|
||||
pub ip: Option<IpAddr>,
|
||||
pub mask: Option<IpAddr>,
|
||||
#[serde(default = "default_netconfig_mac")]
|
||||
pub mac: MacAddr,
|
||||
#[serde(default)]
|
||||
|
|
@ -352,20 +350,6 @@ pub fn default_netconfig_tap() -> Option<String> {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn default_netconfig_ip() -> IpAddr {
|
||||
warn!(
|
||||
"Deprecation warning: No IP address provided. A default IP address is assigned. This behavior will be deprecated soon."
|
||||
);
|
||||
IpAddr::V4(Ipv4Addr::new(192, 168, 249, 1))
|
||||
}
|
||||
|
||||
pub fn default_netconfig_mask() -> IpAddr {
|
||||
warn!(
|
||||
"Deprecation warning: No network mask provided. A default network mask is assigned. This behavior will be deprecated soon."
|
||||
);
|
||||
IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0))
|
||||
}
|
||||
|
||||
pub fn default_netconfig_mac() -> MacAddr {
|
||||
MacAddr::local_random()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue