mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 03:12:27 +00:00
vmm: Add support for multiple virtio-net devices
Until now, the VMM was only accepting a single instance of virtio-net device. This commit extends the virtio-net support by allowing several devices to be created for a single VM. Fixes #71 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
a2947f9a9f
commit
f0a76ad424
78
src/main.rs
78
src/main.rs
@ -58,7 +58,8 @@ fn main() {
|
|||||||
"Network parameters \"tap=<if_name>,\
|
"Network parameters \"tap=<if_name>,\
|
||||||
ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>\"",
|
ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>\"",
|
||||||
)
|
)
|
||||||
.takes_value(true),
|
.takes_value(true)
|
||||||
|
.min_values(1),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("rng")
|
Arg::with_name("rng")
|
||||||
@ -104,7 +105,7 @@ fn main() {
|
|||||||
.expect("Missing argument: disk. Provide at least one")
|
.expect("Missing argument: disk. Provide at least one")
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let net = cmd_arguments.value_of("net");
|
let net: Option<Vec<&str>> = cmd_arguments.values_of("net").map(|x| x.collect());
|
||||||
|
|
||||||
// This .unwrap() cannot fail as there is a default value defined
|
// This .unwrap() cannot fail as there is a default value defined
|
||||||
let rng = cmd_arguments.value_of("rng").unwrap();
|
let rng = cmd_arguments.value_of("rng").unwrap();
|
||||||
@ -297,7 +298,10 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -325,7 +329,10 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -350,7 +357,10 @@ mod tests {
|
|||||||
.args(&["--memory", "size=5120M"])
|
.args(&["--memory", "size=5120M"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -375,7 +385,10 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -413,7 +426,7 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -455,7 +468,7 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
.args(&["--cmdline", "root=PARTUUID=3cb0e0a5-925d-405e-bc55-edf0cec8f10a console=tty0 console=ttyS0,115200n8 console=hvc0 quiet init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp cryptomgr.notests rootfstype=ext4,btrfs,xfs kvm-intel.nested=1 rw"])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -491,7 +504,10 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -538,7 +554,7 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M,file=/dev/shm"])
|
.args(&["--memory", "size=512M,file=/dev/shm"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
.args(&[
|
.args(&[
|
||||||
"--fs",
|
"--fs",
|
||||||
format!(
|
format!(
|
||||||
@ -608,7 +624,7 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
.args(&[
|
.args(&[
|
||||||
"--pmem",
|
"--pmem",
|
||||||
format!(
|
format!(
|
||||||
@ -676,7 +692,7 @@ mod tests {
|
|||||||
.args(&["--memory", "size=512M"])
|
.args(&["--memory", "size=512M"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[1]])
|
.args(&["--disk", disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
.args(&[
|
.args(&[
|
||||||
"--pmem",
|
"--pmem",
|
||||||
format!(
|
format!(
|
||||||
@ -702,4 +718,42 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_network_interfaces() {
|
||||||
|
test_block!(tb, "", {
|
||||||
|
let (disks, fw_path) = prepare_files();
|
||||||
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
|
.args(&["--cpus", "1"])
|
||||||
|
.args(&["--memory", "size=512M"])
|
||||||
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
|
.args(&[
|
||||||
|
"--net",
|
||||||
|
"tap=,mac=12:34:56:78:90:ab,ip=192.168.2.1,mask=255.255.255.0",
|
||||||
|
"tap=,mac=8a:6b:6f:5a:de:ac,ip=192.168.3.1,mask=255.255.255.0",
|
||||||
|
"tap=,mac=fe:1f:9e:e1:60:f2,ip=192.168.4.1,mask=255.255.255.0",
|
||||||
|
])
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
thread::sleep(std::time::Duration::new(10, 0));
|
||||||
|
|
||||||
|
// 3 network interfaces + default localhost ==> 4 interfaces
|
||||||
|
aver_eq!(
|
||||||
|
tb,
|
||||||
|
ssh_command("ip -o link | wc -l")
|
||||||
|
.trim()
|
||||||
|
.parse::<u32>()
|
||||||
|
.unwrap(),
|
||||||
|
4
|
||||||
|
);
|
||||||
|
|
||||||
|
ssh_command("sudo reboot");
|
||||||
|
thread::sleep(std::time::Duration::new(10, 0));
|
||||||
|
let _ = child.kill();
|
||||||
|
let _ = child.wait();
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ write_files:
|
|||||||
permissions: 0644
|
permissions: 0644
|
||||||
content: |
|
content: |
|
||||||
[Match]
|
[Match]
|
||||||
Name=en*
|
MACAddress=12:34:56:78:90:ab
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
Address=192.168.2.2/24
|
Address=192.168.2.2/24
|
||||||
|
@ -59,7 +59,7 @@ pub struct VmParams<'a> {
|
|||||||
pub kernel: &'a str,
|
pub kernel: &'a str,
|
||||||
pub cmdline: Option<&'a str>,
|
pub cmdline: Option<&'a str>,
|
||||||
pub disks: Vec<&'a str>,
|
pub disks: Vec<&'a str>,
|
||||||
pub net: Option<&'a str>,
|
pub net: Option<Vec<&'a str>>,
|
||||||
pub rng: &'a str,
|
pub rng: &'a str,
|
||||||
pub fs: Option<Vec<&'a str>>,
|
pub fs: Option<Vec<&'a str>>,
|
||||||
pub pmem: Option<Vec<&'a str>>,
|
pub pmem: Option<Vec<&'a str>>,
|
||||||
@ -192,13 +192,9 @@ pub struct NetConfig<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NetConfig<'a> {
|
impl<'a> NetConfig<'a> {
|
||||||
pub fn parse(net: Option<&'a str>) -> Result<Option<Self>> {
|
pub fn parse(net: &'a str) -> Result<Self> {
|
||||||
if net.is_none() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the parameters based on the comma delimiter
|
// Split the parameters based on the comma delimiter
|
||||||
let params_list: Vec<&str> = net.unwrap().split(',').collect();
|
let params_list: Vec<&str> = net.split(',').collect();
|
||||||
|
|
||||||
let mut tap_str: &str = "";
|
let mut tap_str: &str = "";
|
||||||
let mut ip_str: &str = "";
|
let mut ip_str: &str = "";
|
||||||
@ -235,7 +231,7 @@ impl<'a> NetConfig<'a> {
|
|||||||
mac = MacAddr::parse_str(mac_str).map_err(Error::ParseNetMacParam)?;
|
mac = MacAddr::parse_str(mac_str).map_err(Error::ParseNetMacParam)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(NetConfig { tap, ip, mask, mac }))
|
Ok(NetConfig { tap, ip, mask, mac })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +344,7 @@ pub struct VmConfig<'a> {
|
|||||||
pub kernel: KernelConfig<'a>,
|
pub kernel: KernelConfig<'a>,
|
||||||
pub cmdline: CmdlineConfig,
|
pub cmdline: CmdlineConfig,
|
||||||
pub disks: Vec<DiskConfig<'a>>,
|
pub disks: Vec<DiskConfig<'a>>,
|
||||||
pub net: Option<NetConfig<'a>>,
|
pub net: Option<Vec<NetConfig<'a>>>,
|
||||||
pub rng: RngConfig<'a>,
|
pub rng: RngConfig<'a>,
|
||||||
pub fs: Option<Vec<FsConfig<'a>>>,
|
pub fs: Option<Vec<FsConfig<'a>>>,
|
||||||
pub pmem: Option<Vec<PmemConfig<'a>>>,
|
pub pmem: Option<Vec<PmemConfig<'a>>>,
|
||||||
@ -361,6 +357,15 @@ impl<'a> VmConfig<'a> {
|
|||||||
disks.push(DiskConfig::parse(disk)?);
|
disks.push(DiskConfig::parse(disk)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut net: Option<Vec<NetConfig>> = None;
|
||||||
|
if let Some(net_list) = &vm_params.net {
|
||||||
|
let mut net_config_list = Vec::new();
|
||||||
|
for item in net_list.iter() {
|
||||||
|
net_config_list.push(NetConfig::parse(item)?);
|
||||||
|
}
|
||||||
|
net = Some(net_config_list);
|
||||||
|
}
|
||||||
|
|
||||||
let mut fs: Option<Vec<FsConfig>> = None;
|
let mut fs: Option<Vec<FsConfig>> = None;
|
||||||
if let Some(fs_list) = &vm_params.fs {
|
if let Some(fs_list) = &vm_params.fs {
|
||||||
let mut fs_config_list = Vec::new();
|
let mut fs_config_list = Vec::new();
|
||||||
@ -385,7 +390,7 @@ impl<'a> VmConfig<'a> {
|
|||||||
kernel: KernelConfig::parse(vm_params.kernel)?,
|
kernel: KernelConfig::parse(vm_params.kernel)?,
|
||||||
cmdline: CmdlineConfig::parse(vm_params.cmdline)?,
|
cmdline: CmdlineConfig::parse(vm_params.cmdline)?,
|
||||||
disks,
|
disks,
|
||||||
net: NetConfig::parse(vm_params.net)?,
|
net,
|
||||||
rng: RngConfig::parse(vm_params.rng)?,
|
rng: RngConfig::parse(vm_params.rng)?,
|
||||||
fs,
|
fs,
|
||||||
pmem,
|
pmem,
|
||||||
|
@ -567,28 +567,30 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add virtio-net if required
|
// Add virtio-net if required
|
||||||
if let Some(net_cfg) = &vm_cfg.net {
|
if let Some(net_list_cfg) = &vm_cfg.net {
|
||||||
let mut virtio_net_device: vm_virtio::Net;
|
for net_cfg in net_list_cfg.iter() {
|
||||||
|
let mut virtio_net_device: vm_virtio::Net;
|
||||||
|
|
||||||
if let Some(tap_if_name) = net_cfg.tap {
|
if let Some(tap_if_name) = net_cfg.tap {
|
||||||
let tap = Tap::open_named(tap_if_name).map_err(DeviceManagerError::OpenTap)?;
|
let tap = Tap::open_named(tap_if_name).map_err(DeviceManagerError::OpenTap)?;
|
||||||
virtio_net_device = vm_virtio::Net::new_with_tap(tap, Some(&net_cfg.mac))
|
virtio_net_device = vm_virtio::Net::new_with_tap(tap, Some(&net_cfg.mac))
|
||||||
.map_err(DeviceManagerError::CreateVirtioNet)?;
|
|
||||||
} else {
|
|
||||||
virtio_net_device =
|
|
||||||
vm_virtio::Net::new(net_cfg.ip, net_cfg.mask, Some(&net_cfg.mac))
|
|
||||||
.map_err(DeviceManagerError::CreateVirtioNet)?;
|
.map_err(DeviceManagerError::CreateVirtioNet)?;
|
||||||
}
|
} else {
|
||||||
|
virtio_net_device =
|
||||||
|
vm_virtio::Net::new(net_cfg.ip, net_cfg.mask, Some(&net_cfg.mac))
|
||||||
|
.map_err(DeviceManagerError::CreateVirtioNet)?;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceManager::add_virtio_pci_device(
|
DeviceManager::add_virtio_pci_device(
|
||||||
Box::new(virtio_net_device),
|
Box::new(virtio_net_device),
|
||||||
memory.clone(),
|
memory.clone(),
|
||||||
allocator,
|
allocator,
|
||||||
vm_fd,
|
vm_fd,
|
||||||
&mut pci,
|
&mut pci,
|
||||||
&mut mmio_bus,
|
&mut mmio_bus,
|
||||||
&interrupt_info,
|
&interrupt_info,
|
||||||
)?;
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add virtio-rng if required
|
// Add virtio-rng if required
|
||||||
|
Loading…
x
Reference in New Issue
Block a user