mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
vmm: Leverage virtio-net to provide connectivity
This patch expand the device registration to add a new virtio-net device in case the user provide the appropriate flag --net from the command line. If the flag is provided, the code will parse the TAP interface name and the expected MAC address from the command line. The VM will be connected to the provided TAP interface, and it will communicate the MAC address to the virtio-net driver. If the flag is not provided, the VM will not register any virtio-net device, therefore it will not have any connectivity with the host. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
53f5295454
commit
c0be6642ad
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -460,6 +460,7 @@ dependencies = [
|
||||
"kvm-ioctls 0.1.0 (git+https://github.com/rust-vmm/kvm-ioctls)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linux-loader 0.1.0 (git+https://github.com/sameo/linux-loader)",
|
||||
"net_util 0.1.0",
|
||||
"pci 0.1.0",
|
||||
"qcow 0.1.0",
|
||||
"vm-allocator 0.1.0",
|
||||
|
14
src/main.rs
14
src/main.rs
@ -37,6 +37,12 @@ fn main() {
|
||||
.help("Path to VM disk image")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("net")
|
||||
.long("net")
|
||||
.help("Network parameters \"tap=<if_name>,mac=<mac_addr>\"")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("cpus")
|
||||
.long("cpus")
|
||||
@ -68,6 +74,11 @@ fn main() {
|
||||
.expect("Missing argument: disk");
|
||||
let disk_path = disk_arg.as_path();
|
||||
|
||||
let mut net_params = None;
|
||||
if let Some(net) = cmd_arguments.value_of("net") {
|
||||
net_params = Some(net.to_string());
|
||||
}
|
||||
|
||||
let mut vcpus = DEFAULT_VCPUS;
|
||||
if let Some(cpus) = cmd_arguments.value_of("cpus") {
|
||||
vcpus = cpus.parse::<u8>().unwrap();
|
||||
@ -81,7 +92,8 @@ fn main() {
|
||||
println!("VM [{} vCPUS {} MB of memory]", vcpus, memory);
|
||||
println!("Booting {:?}...", kernel_path);
|
||||
|
||||
let vm_config = VmConfig::new(kernel_path, disk_path, cmdline, vcpus, memory).unwrap();
|
||||
let vm_config =
|
||||
VmConfig::new(kernel_path, disk_path, cmdline, net_params, vcpus, memory).unwrap();
|
||||
|
||||
vmm::boot_kernel(vm_config).unwrap();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ epoll = "=4.0.1"
|
||||
kvm-bindings = "0.1"
|
||||
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls" }
|
||||
libc = ">=0.2.39"
|
||||
net_util = { path = "../net_util" }
|
||||
pci = {path = "../pci"}
|
||||
qcow = { path = "../qcow" }
|
||||
linux-loader = { git = "https://github.com/sameo/linux-loader" }
|
||||
|
@ -15,6 +15,7 @@ extern crate epoll;
|
||||
extern crate kvm_ioctls;
|
||||
extern crate libc;
|
||||
extern crate linux_loader;
|
||||
extern crate net_util;
|
||||
extern crate vm_allocator;
|
||||
extern crate vm_memory;
|
||||
extern crate vm_virtio;
|
||||
@ -25,6 +26,7 @@ use kvm_ioctls::*;
|
||||
use libc::{c_void, siginfo_t, EFD_NONBLOCK};
|
||||
use linux_loader::cmdline;
|
||||
use linux_loader::loader::KernelLoader;
|
||||
use net_util::{MacAddr, Tap};
|
||||
use pci::{PciConfigIo, PciDevice, PciInterruptPin, PciRoot};
|
||||
use std::ffi::CString;
|
||||
use std::fs::{File, OpenOptions};
|
||||
@ -153,8 +155,14 @@ pub enum Error {
|
||||
/// Cannot create virtio-blk device
|
||||
CreateVirtioBlock(io::Error),
|
||||
|
||||
/// Cannot create virtio-net device
|
||||
CreateVirtioNet(vm_virtio::net::Error),
|
||||
|
||||
/// Cannot create the system allocator
|
||||
CreateSystemAllocator,
|
||||
|
||||
/// Failed parsing network parameters
|
||||
ParseNetworkParameters,
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@ -219,7 +227,7 @@ pub struct VmConfig<'a> {
|
||||
disk_path: &'a Path,
|
||||
cmdline: cmdline::Cmdline,
|
||||
cmdline_addr: GuestAddress,
|
||||
|
||||
net_params: Option<String>,
|
||||
memory_size: GuestUsize,
|
||||
vcpu_count: u8,
|
||||
}
|
||||
@ -229,6 +237,7 @@ impl<'a> VmConfig<'a> {
|
||||
kernel_path: &'a Path,
|
||||
disk_path: &'a Path,
|
||||
cmdline_str: String,
|
||||
net_params: Option<String>,
|
||||
vcpus: u8,
|
||||
memory_size: GuestUsize,
|
||||
) -> Result<Self> {
|
||||
@ -240,12 +249,37 @@ impl<'a> VmConfig<'a> {
|
||||
disk_path,
|
||||
cmdline,
|
||||
cmdline_addr: CMDLINE_OFFSET,
|
||||
net_params,
|
||||
memory_size,
|
||||
vcpu_count: vcpus,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_net_params(net_params: &str) -> Result<(&str, &str)> {
|
||||
// Split the parameters based on the comma delimiter
|
||||
let params_list: Vec<&str> = net_params.split(',').collect();
|
||||
|
||||
let mut if_name: Option<&str> = None;
|
||||
let mut mac: Option<&str> = None;
|
||||
|
||||
for param in params_list.iter() {
|
||||
if param.starts_with("tap=") {
|
||||
if_name = Some(¶m[4..]);
|
||||
} else if param.starts_with("mac=") {
|
||||
mac = Some(¶m[4..]);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(if_name) = if_name {
|
||||
if let Some(mac) = mac {
|
||||
return Ok((if_name, mac));
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::ParseNetworkParameters)
|
||||
}
|
||||
|
||||
struct DeviceManager {
|
||||
io_bus: devices::Bus,
|
||||
mmio_bus: devices::Bus,
|
||||
@ -291,18 +325,18 @@ impl DeviceManager {
|
||||
.open(&vm_cfg.disk_path)
|
||||
.map_err(Error::Disk)?;
|
||||
|
||||
// Add virtio-blk
|
||||
let virtio_block_device =
|
||||
vm_virtio::Block::new(raw_img, false).map_err(Error::CreateVirtioBlock)?;
|
||||
let virtio_block_device = Box::new(virtio_block_device);
|
||||
let mut virtio_pci_device =
|
||||
VirtioPciDevice::new(memory, virtio_block_device).map_err(|_| Error::VirtioDevice)?;
|
||||
let mut virtio_pci_device = VirtioPciDevice::new(memory.clone(), virtio_block_device)
|
||||
.map_err(|_| Error::VirtioDevice)?;
|
||||
let bars = virtio_pci_device
|
||||
.allocate_bars(allocator)
|
||||
.map_err(Error::AllocateBars)?;
|
||||
|
||||
for (event, addr, _) in virtio_pci_device.ioeventfds() {
|
||||
let io_addr = IoEventAddress::Mmio(addr);
|
||||
println!("Register ioevent at 0x{:x}", addr);
|
||||
vm_fd
|
||||
.register_ioevent(event.as_raw_fd(), &io_addr, NoDatamatch)
|
||||
.map_err(Error::RegisterIoevent)?;
|
||||
@ -323,6 +357,44 @@ impl DeviceManager {
|
||||
.add_device(virtio_pci_device.clone(), &mut mmio_bus, bars)
|
||||
.map_err(Error::AddPciDevice)?;
|
||||
|
||||
// Add virtio-net if required
|
||||
if let Some(net_params) = &vm_cfg.net_params {
|
||||
if let Ok((tap_if_name, mac_addr)) = parse_net_params(net_params) {
|
||||
let mac = MacAddr::parse_str(mac_addr).unwrap();
|
||||
let tap = Tap::open_named(tap_if_name).unwrap();
|
||||
let virtio_net_device = vm_virtio::Net::new_with_tap(tap, Some(&mac))
|
||||
.map_err(Error::CreateVirtioNet)?;
|
||||
let virtio_net_device = Box::new(virtio_net_device);
|
||||
let mut virtio_pci_device = VirtioPciDevice::new(memory.clone(), virtio_net_device)
|
||||
.map_err(|_| Error::VirtioDevice)?;
|
||||
let bars = virtio_pci_device
|
||||
.allocate_bars(allocator)
|
||||
.map_err(Error::AllocateBars)?;
|
||||
|
||||
for (event, addr, _) in virtio_pci_device.ioeventfds() {
|
||||
let io_addr = IoEventAddress::Mmio(addr);
|
||||
vm_fd
|
||||
.register_ioevent(event.as_raw_fd(), &io_addr, NoDatamatch)
|
||||
.map_err(Error::RegisterIoevent)?;
|
||||
}
|
||||
|
||||
// Assign IRQ to the virtio-blk device
|
||||
let irqfd = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFd)?;
|
||||
let irq_num = allocator.allocate_irq().ok_or(Error::AllocateIrq)?;
|
||||
vm_fd
|
||||
.register_irqfd(irqfd.as_raw_fd(), irq_num)
|
||||
.map_err(Error::Irq)?;
|
||||
// Let's use irq line INTA for now.
|
||||
virtio_pci_device.assign_irq(irqfd, irq_num as u32, PciInterruptPin::IntA);
|
||||
|
||||
let virtio_pci_device = Arc::new(Mutex::new(virtio_pci_device));
|
||||
|
||||
pci_root
|
||||
.add_device(virtio_pci_device.clone(), &mut mmio_bus, bars)
|
||||
.map_err(Error::AddPciDevice)?;
|
||||
}
|
||||
}
|
||||
|
||||
let pci = Arc::new(Mutex::new(PciConfigIo::new(pci_root)));
|
||||
|
||||
Ok(DeviceManager {
|
||||
|
Loading…
Reference in New Issue
Block a user