vhost_user_net: Use config::OptionParser to simplify net backend parsing

Switch to using the recently added OptionParser in the code that parses
the network backend.

Whilst doing this also update the net-backend syntax to use "sock"
rather than socket.

Fixes: #1092
Partially fixes: #1091

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-05-08 16:43:56 +01:00 committed by Sebastien Boeuf
parent f3f398eb44
commit 592de97fbd
5 changed files with 53 additions and 68 deletions

1
Cargo.lock generated
View File

@ -1415,6 +1415,7 @@ dependencies = [
"virtio-bindings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm-memory",
"vm-virtio",
"vmm",
"vmm-sys-util",
]

View File

@ -444,12 +444,12 @@ mod tests {
// Start the daemon
let net_params = if let Some(tap_str) = tap {
format!(
"tap={},ip={},mask=255.255.255.0,sock={},num_queues={},queue_size=1024",
"tap={},ip={},mask=255.255.255.0,socket={},num_queues={},queue_size=1024",
tap_str, ip, vunet_socket_path, num_queues
)
} else {
format!(
"ip={},mask=255.255.255.0,sock={},num_queues={},queue_size=1024",
"ip={},mask=255.255.255.0,socket={},num_queues={},queue_size=1024",
ip, vunet_socket_path, num_queues
)
};

View File

@ -15,4 +15,5 @@ vhost_rs = { git = "https://github.com/cloud-hypervisor/vhost", branch = "dragon
virtio-bindings = "0.1.0"
vm-memory = "0.2.0"
vm-virtio = { path = "../vm-virtio" }
vmm = { path = "../vmm" }
vmm-sys-util = ">=0.3.1"

View File

@ -11,6 +11,7 @@ extern crate net_util;
extern crate vhost_rs;
extern crate vhost_user_backend;
extern crate vm_virtio;
extern crate vmm;
use epoll;
use libc::{self, EAGAIN, EFD_NONBLOCK};
@ -31,6 +32,7 @@ use virtio_bindings::bindings::virtio_net::*;
use vm_memory::GuestMemoryMmap;
use vm_virtio::net_util::{open_tap, RxVirtio, TxVirtio};
use vm_virtio::Queue;
use vmm::config::{OptionParser, OptionParserError};
use vmm_sys_util::eventfd::EventFd;
pub type VhostUserResult<T> = std::result::Result<T, VhostUserError>;
@ -51,6 +53,8 @@ pub enum Error {
EpollCreateFd,
/// Failed to read Tap.
FailedReadTap,
/// Failed to parse configuration string
FailedConfigParse(OptionParserError),
/// Failed to signal used queue.
FailedSignalingUsedQueue,
/// Failed to handle event other than input event.
@ -63,22 +67,14 @@ pub enum Error {
NoVringCallFdNotify,
/// No memory configured.
NoMemoryConfigured,
/// Failed to parse sock parameter.
ParseSockParam,
/// Failed to parse ip parameter.
ParseIpParam(std::net::AddrParseError),
/// Failed to parse mask parameter.
ParseMaskParam(std::net::AddrParseError),
/// Failed to parse queue number.
ParseQueueNumParam(std::num::ParseIntError),
/// Failed to parse queue size.
ParseQueueSizeParam(std::num::ParseIntError),
/// Open tap device failed.
OpenTap(vm_virtio::net_util::Error),
/// No socket provided
SocketParameterMissing,
}
pub const SYNTAX: &str = "vhost-user-net backend parameters \
\"ip=<ip_addr>,mask=<net_mask>,sock=<socket_path>,\
\"ip=<ip_addr>,mask=<net_mask>,socket=<socket_path>,\
num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,tap=<if_name>\"";
impl fmt::Display for Error {
@ -353,71 +349,52 @@ impl VhostUserBackend for VhostUserNetBackend {
}
}
pub struct VhostUserNetBackendConfig<'a> {
pub struct VhostUserNetBackendConfig {
pub ip: Ipv4Addr,
pub mask: Ipv4Addr,
pub sock: &'a str,
pub socket: String,
pub num_queues: usize,
pub queue_size: u16,
pub tap: Option<&'a str>,
pub tap: Option<String>,
}
impl<'a> VhostUserNetBackendConfig<'a> {
pub fn parse(backend: &'a str) -> Result<Self> {
let params_list: Vec<&str> = backend.split(',').collect();
impl VhostUserNetBackendConfig {
pub fn parse(backend: &str) -> Result<Self> {
let mut parser = OptionParser::new();
let mut ip_str: &str = "";
let mut mask_str: &str = "";
let mut sock: &str = "";
let mut num_queues_str: &str = "";
let mut queue_size_str: &str = "";
let mut tap_str: &str = "";
parser
.add("tap")
.add("ip")
.add("mask")
.add("queue_size")
.add("num_queues")
.add("socket");
for param in params_list.iter() {
if param.starts_with("ip=") {
ip_str = &param[3..];
} else if param.starts_with("mask=") {
mask_str = &param[5..];
} else if param.starts_with("sock=") {
sock = &param[5..];
} else if param.starts_with("num_queues=") {
num_queues_str = &param[11..];
} else if param.starts_with("queue_size=") {
queue_size_str = &param[11..];
} else if param.starts_with("tap=") {
tap_str = &param[4..];
}
}
parser.parse(backend).map_err(Error::FailedConfigParse)?;
let mut ip: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 1);
let mut mask: Ipv4Addr = Ipv4Addr::new(255, 255, 255, 0);
let mut num_queues: usize = 2;
let mut queue_size: u16 = 256;
let mut tap: Option<&str> = None;
if sock.is_empty() {
return Err(Error::ParseSockParam);
}
if !ip_str.is_empty() {
ip = ip_str.parse().map_err(Error::ParseIpParam)?;
}
if !mask_str.is_empty() {
mask = mask_str.parse().map_err(Error::ParseMaskParam)?;
}
if !num_queues_str.is_empty() {
num_queues = num_queues_str.parse().map_err(Error::ParseQueueNumParam)?;
}
if !queue_size_str.is_empty() {
queue_size = queue_size_str.parse().map_err(Error::ParseQueueSizeParam)?;
}
if !tap_str.is_empty() {
tap = Some(tap_str);
}
let tap = parser.get("tap");
let ip = parser
.convert("ip")
.map_err(Error::FailedConfigParse)?
.unwrap_or_else(|| Ipv4Addr::new(192, 168, 100, 1));
let mask = parser
.convert("mask")
.map_err(Error::FailedConfigParse)?
.unwrap_or_else(|| Ipv4Addr::new(255, 255, 255, 0));
let queue_size = parser
.convert("queue_size")
.map_err(Error::FailedConfigParse)?
.unwrap_or(256);
let num_queues = parser
.convert("num_queues")
.map_err(Error::FailedConfigParse)?
.unwrap_or(2);
let socket = parser.get("socket").ok_or(Error::SocketParameterMissing)?;
Ok(VhostUserNetBackendConfig {
ip,
mask,
sock,
socket,
num_queues,
queue_size,
tap,
@ -434,20 +411,26 @@ pub fn start_net_backend(backend_command: &str) {
}
};
let tap = if let Some(tap) = backend_config.tap.as_ref() {
Some(tap.as_str())
} else {
None
};
let net_backend = Arc::new(RwLock::new(
VhostUserNetBackend::new(
backend_config.ip,
backend_config.mask,
backend_config.num_queues,
backend_config.queue_size,
backend_config.tap,
tap,
)
.unwrap(),
));
let mut net_daemon = VhostUserDaemon::new(
"vhost-user-net-backend".to_string(),
backend_config.sock.to_string(),
backend_config.socket.to_string(),
net_backend.clone(),
)
.unwrap();

View File

@ -1392,7 +1392,7 @@ impl DeviceManager {
.args(&[
"--net-backend",
&format!(
"ip={},mask={},sock={},num_queues={},queue_size={}",
"ip={},mask={},socket={},num_queues={},queue_size={}",
net_cfg.ip, net_cfg.mask, &sock, net_cfg.num_queues, net_cfg.queue_size
),
])