mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 17:35:19 +00:00
vmm: Add support for letting the VMM create the TAP interface
Until now, the only way to get some networking with cloud-hypervisor was to let the user create a TAP interface first, and then to provide the name of this interface to the VMM. This patch extend the previous behavior by adding the support for the creation of a brand new TAP interface from the VMM itself. In case no interface name is provided through "tap=<if_name>", we will assume the user wants the VMM to create and set the interface on its behalf, no matter the value of other parameters (ip, mask, and mac). In this same scenario, because the user expects the VMM to create the TAP interface, he can also provide the associated IP address and subnet mask associated with it. In case those values are not provided, some default ones will be picked. No matter the value of "tap", the MAC address will always be set, and if no value is provided, the VMM will come up with a default value for it. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
0c4c330843
commit
5934f30fde
10
src/main.rs
10
src/main.rs
@ -40,7 +40,7 @@ fn main() {
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("net")
|
Arg::with_name("net")
|
||||||
.long("net")
|
.long("net")
|
||||||
.help("Network parameters \"tap=<if_name>,mac=<mac_addr>\"")
|
.help("Network parameters \"tap=<if_name>,ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>\"")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -81,8 +81,12 @@ fn main() {
|
|||||||
let disk_path = disk_arg.as_path();
|
let disk_path = disk_arg.as_path();
|
||||||
|
|
||||||
let mut net_params = None;
|
let mut net_params = None;
|
||||||
if let Some(net) = cmd_arguments.value_of("net") {
|
if cmd_arguments.is_present("net") {
|
||||||
net_params = Some(net.to_string());
|
if let Some(net) = cmd_arguments.value_of("net") {
|
||||||
|
net_params = Some(net.to_string());
|
||||||
|
} else {
|
||||||
|
net_params = Some(String::new())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rng_path = match cmd_arguments.occurrences_of("rng") {
|
let rng_path = match cmd_arguments.occurrences_of("rng") {
|
||||||
|
@ -31,6 +31,7 @@ use pci::{PciConfigIo, PciDevice, PciInterruptPin, PciRoot};
|
|||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{self, stdout};
|
use std::io::{self, stdout};
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
@ -166,6 +167,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Failed parsing network parameters
|
/// Failed parsing network parameters
|
||||||
ParseNetworkParameters,
|
ParseNetworkParameters,
|
||||||
|
|
||||||
|
/// Cannot open tap interface
|
||||||
|
OpenTap(net_util::TapError),
|
||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
@ -262,28 +266,59 @@ impl<'a> VmConfig<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_net_params(net_params: &str) -> Result<(&str, &str)> {
|
#[derive(Debug)]
|
||||||
|
struct NetParams<'a> {
|
||||||
|
tap_if_name: Option<&'a str>,
|
||||||
|
ip_addr: Ipv4Addr,
|
||||||
|
net_mask: Ipv4Addr,
|
||||||
|
mac_addr: MacAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_net_params(net_params: &str) -> Result<NetParams> {
|
||||||
// Split the parameters based on the comma delimiter
|
// Split the parameters based on the comma delimiter
|
||||||
let params_list: Vec<&str> = net_params.split(',').collect();
|
let params_list: Vec<&str> = net_params.split(',').collect();
|
||||||
|
|
||||||
let mut if_name: Option<&str> = None;
|
let mut tap: &str = "";
|
||||||
let mut mac: Option<&str> = None;
|
let mut ip: &str = "";
|
||||||
|
let mut mask: &str = "";
|
||||||
|
let mut mac: &str = "";
|
||||||
|
|
||||||
for param in params_list.iter() {
|
for param in params_list.iter() {
|
||||||
if param.starts_with("tap=") {
|
if param.starts_with("tap=") {
|
||||||
if_name = Some(¶m[4..]);
|
tap = ¶m[4..];
|
||||||
|
} else if param.starts_with("ip=") {
|
||||||
|
ip = ¶m[3..];
|
||||||
|
} else if param.starts_with("mask=") {
|
||||||
|
mask = ¶m[5..];
|
||||||
} else if param.starts_with("mac=") {
|
} else if param.starts_with("mac=") {
|
||||||
mac = Some(¶m[4..]);
|
mac = ¶m[4..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(if_name) = if_name {
|
let mut tap_if_name: Option<&str> = None;
|
||||||
if let Some(mac) = mac {
|
let mut ip_addr: Ipv4Addr = "192.168.249.1".parse().unwrap();
|
||||||
return Ok((if_name, mac));
|
let mut net_mask: Ipv4Addr = "255.255.255.0".parse().unwrap();
|
||||||
}
|
let mut mac_addr: MacAddr = MacAddr::parse_str("12:34:56:78:90:ab").unwrap();
|
||||||
|
|
||||||
|
if !tap.is_empty() {
|
||||||
|
tap_if_name = Some(tap);
|
||||||
|
}
|
||||||
|
if !ip.is_empty() {
|
||||||
|
ip_addr = ip.parse().unwrap();
|
||||||
|
}
|
||||||
|
if !mask.is_empty() {
|
||||||
|
net_mask = mask.parse().unwrap();
|
||||||
|
}
|
||||||
|
if !mac.is_empty() {
|
||||||
|
mac_addr = MacAddr::parse_str(mac).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::ParseNetworkParameters)
|
Ok(NetParams {
|
||||||
|
tap_if_name,
|
||||||
|
ip_addr,
|
||||||
|
net_mask,
|
||||||
|
mac_addr,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DeviceManager {
|
struct DeviceManager {
|
||||||
@ -346,11 +381,22 @@ impl DeviceManager {
|
|||||||
|
|
||||||
// Add virtio-net if required
|
// Add virtio-net if required
|
||||||
if let Some(net_params) = &vm_cfg.net_params {
|
if let Some(net_params) = &vm_cfg.net_params {
|
||||||
if let Ok((tap_if_name, mac_addr)) = parse_net_params(net_params) {
|
if let Ok(net_params) = parse_net_params(net_params) {
|
||||||
let mac = MacAddr::parse_str(mac_addr).unwrap();
|
let mut virtio_net_device: vm_virtio::Net;
|
||||||
let tap = Tap::open_named(tap_if_name).unwrap();
|
|
||||||
let virtio_net_device = vm_virtio::Net::new_with_tap(tap, Some(&mac))
|
if let Some(tap_if_name) = net_params.tap_if_name {
|
||||||
|
let tap = Tap::open_named(tap_if_name).map_err(Error::OpenTap)?;
|
||||||
|
virtio_net_device =
|
||||||
|
vm_virtio::Net::new_with_tap(tap, Some(&net_params.mac_addr))
|
||||||
|
.map_err(Error::CreateVirtioNet)?;
|
||||||
|
} else {
|
||||||
|
virtio_net_device = vm_virtio::Net::new(
|
||||||
|
net_params.ip_addr,
|
||||||
|
net_params.net_mask,
|
||||||
|
Some(&net_params.mac_addr),
|
||||||
|
)
|
||||||
.map_err(Error::CreateVirtioNet)?;
|
.map_err(Error::CreateVirtioNet)?;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceManager::add_virtio_pci_device(
|
DeviceManager::add_virtio_pci_device(
|
||||||
Box::new(virtio_net_device),
|
Box::new(virtio_net_device),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user