vmm, vm-virtio: Stop always autogenerating a host MAC address

This removes the need to use CAP_NET_ADMIN privileges and instead the
host MAC addres is either provided by the user or alternatively it is
retrieved from the kernel.

TEST=Run cloud-hypervisor without CAP_NET_ADMIN permission and a
preconfigured tap device:

sudo ip tuntap add name tap0 mode tap
sudo ifconfig tap0 192.168.249.1 netmask 255.255.255.0 up
cargo clean
cargo build
target/debug/cloud-hypervisor --serial tty --console off --kernel ~/src/rust-hypervisor-firmware/target/target/release/hypervisor-fw --disk path=~/workloads/clear-33190-kvm.img --net tap=tap0

VM was also rebooted to check that works correctly.

Fixes: #1274

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-06-05 12:00:34 +01:00 committed by Sebastien Boeuf
parent 1f8b6fa947
commit 9b71ba20ac
5 changed files with 25 additions and 20 deletions

View File

@ -141,7 +141,7 @@ impl VhostUserNetBackend {
ifname,
Some(ip_addr),
Some(netmask),
Some(host_mac),
&mut Some(host_mac),
num_queues / 2,
)
.map_err(Error::OpenTap)?;

View File

@ -465,7 +465,7 @@ impl Net {
ip_addr: Option<Ipv4Addr>,
netmask: Option<Ipv4Addr>,
guest_mac: Option<MacAddr>,
host_mac: Option<MacAddr>,
host_mac: &mut Option<MacAddr>,
iommu: bool,
num_queues: usize,
queue_size: u16,

View File

@ -122,6 +122,8 @@ pub enum Error {
TapSetNetmask(TapError),
/// Setting MAC address failed
TapSetMac(TapError),
/// Getting MAC address failed
TapGetMac(TapError),
/// Setting tap interface offload flags failed.
TapSetOffload(TapError),
/// Setting vnet header size failed.
@ -539,7 +541,7 @@ pub fn open_tap(
if_name: Option<&str>,
ip_addr: Option<Ipv4Addr>,
netmask: Option<Ipv4Addr>,
host_mac: Option<MacAddr>,
host_mac: &mut Option<MacAddr>,
num_rx_q: usize,
) -> Result<Vec<Tap>> {
let mut taps: Vec<Tap> = Vec::new();
@ -568,7 +570,9 @@ pub fn open_tap(
tap.set_netmask(mask).map_err(Error::TapSetNetmask)?;
}
if let Some(mac) = host_mac {
tap.set_mac_addr(mac).map_err(Error::TapSetMac)?
tap.set_mac_addr(*mac).map_err(Error::TapSetMac)?
} else {
*host_mac = Some(tap.get_mac_addr().map_err(Error::TapGetMac)?)
}
tap.enable().map_err(Error::TapEnable)?;
tap.set_offload(flag).map_err(Error::TapSetOffload)?;

View File

@ -683,8 +683,8 @@ pub struct NetConfig {
pub mask: Ipv4Addr,
#[serde(default = "default_netconfig_mac")]
pub mac: MacAddr,
#[serde(default = "default_netconfig_mac")]
pub host_mac: MacAddr,
#[serde(default)]
pub host_mac: Option<MacAddr>,
#[serde(default)]
pub iommu: bool,
#[serde(default = "default_netconfig_num_queues")]
@ -729,7 +729,7 @@ impl Default for NetConfig {
ip: default_netconfig_ip(),
mask: default_netconfig_mask(),
mac: default_netconfig_mac(),
host_mac: default_netconfig_mac(),
host_mac: None,
iommu: false,
num_queues: default_netconfig_num_queues(),
queue_size: default_netconfig_queue_size(),
@ -776,10 +776,7 @@ impl NetConfig {
.convert("mac")
.map_err(Error::ParseNetwork)?
.unwrap_or_else(default_netconfig_mac);
let host_mac = parser
.convert("host_mac")
.map_err(Error::ParseNetwork)?
.unwrap_or_else(default_netconfig_mac);
let host_mac = parser.convert("host_mac").map_err(Error::ParseNetwork)?;
let iommu = parser
.convert::<Toggle>("iommu")
.map_err(Error::ParseNetwork)?
@ -1633,7 +1630,7 @@ mod tests {
NetConfig::parse("mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef")?,
NetConfig {
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
host_mac: MacAddr::parse_str("12:34:de:ad:be:ef").unwrap(),
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
..Default::default()
}
);
@ -1642,7 +1639,7 @@ mod tests {
NetConfig::parse("mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef,id=mynet0")?,
NetConfig {
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
host_mac: MacAddr::parse_str("12:34:de:ad:be:ef").unwrap(),
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
id: Some("mynet0".to_owned()),
..Default::default()
}
@ -1654,7 +1651,7 @@ mod tests {
)?,
NetConfig {
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
host_mac: MacAddr::parse_str("12:34:de:ad:be:ef").unwrap(),
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
tap: Some("tap0".to_owned()),
ip: "192.168.100.1".parse().unwrap(),
mask: "255.255.255.128".parse().unwrap(),
@ -1668,7 +1665,7 @@ mod tests {
)?,
NetConfig {
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
host_mac: MacAddr::parse_str("12:34:de:ad:be:ef").unwrap(),
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
vhost_user: true,
vhost_socket: Some("/tmp/sock".to_owned()),
..Default::default()
@ -1679,7 +1676,7 @@ mod tests {
NetConfig::parse("mac=de:ad:be:ef:12:34,host_mac=12:34:de:ad:be:ef,num_queues=4,queue_size=1024,iommu=on")?,
NetConfig {
mac: MacAddr::parse_str("de:ad:be:ef:12:34").unwrap(),
host_mac: MacAddr::parse_str("12:34:de:ad:be:ef").unwrap(),
host_mac: Some(MacAddr::parse_str("12:34:de:ad:be:ef").unwrap()),
num_queues: 4,
queue_size: 1024,
iommu: true,

View File

@ -1512,13 +1512,17 @@ impl DeviceManager {
.args(&[
"--net-backend",
&format!(
"ip={},mask={},socket={},num_queues={},queue_size={},host_mac={}",
"ip={},mask={},socket={},num_queues={},queue_size={}{}",
net_cfg.ip,
net_cfg.mask,
&socket,
net_cfg.num_queues,
net_cfg.queue_size,
net_cfg.host_mac
if let Some(mac) = net_cfg.host_mac {
format!(",host_mac={:}", mac)
} else {
"".to_owned()
}
),
])
.spawn()
@ -1583,7 +1587,7 @@ impl DeviceManager {
None,
None,
Some(net_cfg.mac),
Some(net_cfg.host_mac),
&mut net_cfg.host_mac,
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,
@ -1598,7 +1602,7 @@ impl DeviceManager {
Some(net_cfg.ip),
Some(net_cfg.mask),
Some(net_cfg.mac),
Some(net_cfg.host_mac),
&mut net_cfg.host_mac,
net_cfg.iommu,
net_cfg.num_queues,
net_cfg.queue_size,