Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support adding vhost-net network devices #27

Merged
merged 2 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,208 changes: 951 additions & 257 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dragonball = { git = "https://github.com/kata-containers/kata-containers", branc
"virtio-fs",
"virtio-vsock",
"virtio-net",
"vhost-net",
"hotplug",
"dbs-upcall",
] }
Expand Down
65 changes: 44 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
>
> [[简体中文版]](README_zh.md)

# 1. Examples:
## Examples

See all options:

```
./dbs-cli --help
```

A simple example:
### Basic examples

```bash
./dbs-cli create \
Expand Down Expand Up @@ -68,9 +68,9 @@ Create a virtio-vsock tunnel for Guest-to-Host communication.
--vsock /tmp/vsock.sock
```

Create virtio-net devices.
Create virtio-blk devices.

> The type of the `--virnets` receives an array of VirtioNetDeviceConfigInfo in the
> The type of the `--virblks` receives an array of BlockDeviceConfigInfo in the
> format of JSON.

```
Expand All @@ -79,26 +79,47 @@ Create virtio-net devices.
--kernel-path ~/path/to/kernel/vmlinux.bin \
--rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \
--boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \
--virnets "[{\"iface_id\":\"eth0\",\"host_dev_name\":\"tap0\",\"num_queues\":2,\"queue_size\":0,\"guest_mac\":\"43:2D:9C:13:71:48\",\"allow_duplicate_mac\":true}]"
--virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]'
```

Create virtio-blk devices.
### Networking

> The type of the `--virblks` receives an array of BlockDeviceConfigInfo in the
> format of JSON.
Start a Dragonball VMM with a virtio-based network device. `--virnets`
receives an array of `NetworkInterfaceConfig` in the format of JSON.

```
./dbs-cli create \
--log-file dbs-cli.log --log-level ERROR \
--kernel-path ~/path/to/kernel/vmlinux.bin \
--rootfs ~/path/to/rootfs/bionic.rootfs.ext4 \
--boot-args "console=ttyS0 console=ttyS1 earlyprintk=ttyS1 tty0 reboot=k debug panic=1 pci=off root=/dev/vda1" \
--virblks '[{"drive_id":"testblk","device_type":"RawBlock","path_on_host":"/path/to/test.img","is_root_device":false,"is_read_only":false,"is_direct":false,"no_drop":false,"num_queues":1,"queue_size":1024}]'
--virnets '[{"guest_mac":"43:2D:9C:13:71:48","backend":{"type":"vhost","iface_id":"eth0","host_dev_name":"tap0","allow_duplicate_mac":true}}]'
```

# 2. Usage
The supported network devices include:

## 1. Create API Server and Update VM
```
// Virtio-net
{
"guest_mac": "43:2D:9C:13:71:48",
"backend": {
"type": "virtio",
"iface_id": "eth0",
"host_dev_name": "tap0",
"allow_duplicate_mac": true
}
}

// Vhost-net
{
"guest_mac": "43:2D:9C:13:71:48",
"backend": {
"type": "vhost",
"iface_id": "eth0",
"host_dev_name": "tap0",
"allow_duplicate_mac": true
}
}
```

## Advanced Usage

### Create API Server and Update VM

An API Server could be created by adding `--api-sock-path [socket path]` into dbs-cli creation command.

Expand All @@ -110,6 +131,8 @@ Cpu Hotplug via API Server:

Create hot-plug virtio-net devices via API Server:

**TODO: Needs to be updated**

> The type of the `--hotplug-virnets` receives an array of
> VirtioNetDeviceConfigInfo in the format of JSON.

Expand All @@ -132,11 +155,11 @@ sudo ./dbs-cli \

TODO : add document for hot-plug virtio-fs

## 2. Exit vm
### Exit VM

> If you want to exit vm, just input `reboot` in vm's console.
If you want to exit vm, just input `reboot` in vm's console.

## 3. For developers
### For developers

If you wish to modify some details or debug to figure out the fault of codes, you can do as follow to see whether the program act expectedly or not.

Expand All @@ -152,7 +175,7 @@ To see some help:
cargo run -- --help
```

## 3. Some off-topic remarks
### Some off-topic remarks

Regarding the dependency issue of the upstream library, it is recommended to build the `build` target of Makefile to avoid it temporally.

Expand All @@ -162,6 +185,6 @@ make build

If the self-defined `dragonball` dependency is supposed to be used, please refer to [dependency document](docs/dependency.md)

# License
## License

`DBS-CLI` is licensed under [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0.
6 changes: 3 additions & 3 deletions src/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ fn request_cpu_resize(vcpu_resize_num: usize) -> Value {
})
}

/// Insert virtio-net devices
fn request_virtio_net(virtio_net_config: &str) -> Value {
/// Insert virtio network devices
fn request_virtio_net(net_config: &str) -> Value {
json!({
"action": "insert_virnets",
"config": virtio_net_config,
"config": net_config,
})
}

Expand Down
16 changes: 10 additions & 6 deletions src/api_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use std::sync::{Arc, Mutex};

use anyhow::{anyhow, Context, Result};
use crossbeam_channel::{Receiver, Sender};
use dragonball::api::v1::{VmmRequest, VmmResponse};
use dragonball::api::v1::{NetworkInterfaceConfig, VmmRequest, VmmResponse};
use dragonball::device_manager::blk_dev_mgr::BlockDeviceConfigInfo;
use dragonball::device_manager::fs_dev_mgr::FsMountConfigInfo;
use dragonball::device_manager::virtio_net_dev_mgr::VirtioNetDeviceConfigInfo;
use dragonball::vcpu::VcpuResizeInfo;
use serde_json::Value;
use vmm_sys_util::eventfd::EventFd;

use crate::utils;
use crate::vmm_comm_trait::VMMComm;

pub struct ApiServer {
Expand Down Expand Up @@ -85,11 +85,15 @@ impl ApiServer {
Some(config_json) => config_json,
None => return Err(anyhow!("The config of virtio-net device is required")),
};
let configs: Vec<VirtioNetDeviceConfigInfo> = serde_json::from_str(config_json)
.context("Parse virtio-net device config from json")?;
let configs: Vec<NetworkInterfaceConfig> = serde_json::from_str(config_json)
.context("Parse NetworkInterfaceConfig from JSON")?;
for config in configs.iter() {
self.insert_virnet(config.clone())
.context("Insert a virtio-net device to the Dragonball")?;
self.insert_virnet(config.clone()).with_context(|| {
format!(
"Insert a {} device to the Dragonball",
utils::net_device_name(config)
)
})?;
}
}
Some("insert_virblks") => {
Expand Down
14 changes: 8 additions & 6 deletions src/cli_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ use vmm_sys_util::eventfd::EventFd;

use dragonball::{
api::v1::{
BlockDeviceConfigInfo, BootSourceConfig, InstanceInfo, VmmRequest, VmmResponse,
VsockDeviceConfigInfo,
BlockDeviceConfigInfo, BootSourceConfig, InstanceInfo, NetworkInterfaceConfig, VmmRequest,
VmmResponse, VsockDeviceConfigInfo,
},
device_manager::fs_dev_mgr::FsDeviceConfigInfo,
device_manager::virtio_net_dev_mgr::VirtioNetDeviceConfigInfo,
vm::{CpuTopology, VmConfigInfo},
};

Expand Down Expand Up @@ -154,12 +153,15 @@ impl CliInstance {
.expect("failed to set vsock socket path");
}

// Virtio devices
if !args.virnets.is_empty() {
let configs: Vec<VirtioNetDeviceConfigInfo> = serde_json::from_str(&args.virnets)
.expect("failed to parse virtio-net devices from JSON");
let configs: Vec<NetworkInterfaceConfig> = serde_json::from_str(&args.virnets)
.unwrap_or_else(|err| {
panic!("Failed to parse NetworkInterfaceConfig from JSON: {}", err)
});
for config in configs.into_iter() {
self.insert_virnet(config)
.expect("failed to insert a virtio-net device");
.expect("Failed to insert a virtio device");
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/parser/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,7 @@ pub struct CreateArgs {
long,
value_parser,
default_value = "",
help = r#"Insert virtio-net devices into the Dragonball.
The type of it is an array of VirtioNetDeviceConfigInfo, e.g.
--virnets '[{"iface_id":"eth0","host_dev_name":"tap0","num_queues":2,"queue_size":0,"allow_duplicate_mac":true}]'"#,
help = r#"Insert virtio devices into the Dragonball before launched. The supported devices are virtio-net and vhost-net."#,
display_order = 2
)]
pub virnets: String,
Expand Down
14 changes: 14 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use dragonball::api::v1::NetworkInterfaceConfig;
use slog::Drain;
use slog::*;
use slog_scope::set_global_logger;
Expand Down Expand Up @@ -25,3 +26,16 @@ pub fn setup_db_log(log_file_path: &String, log_level: &str) {
guard.cancel_reset();
slog_stdlog::init().unwrap();
}

#[inline]
/// Get net device name from `NetworkInterfaceConfig`.
pub(crate) fn net_device_name(config: &NetworkInterfaceConfig) -> String {
match &config.backend {
dragonball::api::v1::Backend::Virtio(config) => {
format!("virtio-net({})", config.host_dev_name)
}
dragonball::api::v1::Backend::Vhost(config) => {
format!("vhost-net({})", config.host_dev_name)
}
}
}
37 changes: 21 additions & 16 deletions src/vmm_comm_trait.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use crossbeam_channel::{Receiver, Sender};
use vmm_sys_util::eventfd::EventFd;

use anyhow::{anyhow, Context, Result};
use std::sync::{Arc, Mutex};

use dragonball::{
api::v1::{
BlockDeviceConfigInfo, BootSourceConfig, VmmAction, VmmActionError, VmmData, VmmRequest,
VmmResponse, VsockDeviceConfigInfo,
},
device_manager::fs_dev_mgr::{FsDeviceConfigInfo, FsMountConfigInfo},
device_manager::virtio_net_dev_mgr::VirtioNetDeviceConfigInfo,
vcpu::VcpuResizeInfo,
vm::VmConfigInfo,
use anyhow::{anyhow, Context, Result};
use crossbeam_channel::{Receiver, Sender};
use dragonball::api::v1::{
BlockDeviceConfigInfo, BootSourceConfig, NetworkInterfaceConfig, VmmAction, VmmActionError,
VmmData, VmmRequest, VmmResponse, VsockDeviceConfigInfo,
};
use dragonball::device_manager::fs_dev_mgr::{FsDeviceConfigInfo, FsMountConfigInfo};
use dragonball::vcpu::VcpuResizeInfo;
use dragonball::vm::VmConfigInfo;
use vmm_sys_util::eventfd::EventFd;

use crate::utils;

pub enum Request {
Sync(VmmAction),
Expand Down Expand Up @@ -135,9 +133,16 @@ pub trait VMMComm {
Ok(())
}

fn insert_virnet(&self, config: VirtioNetDeviceConfigInfo) -> Result<()> {
self.handle_request(Request::Sync(VmmAction::InsertNetworkDevice(config)))
.context("Request to insert a virtio-net device")?;
fn insert_virnet(&self, config: NetworkInterfaceConfig) -> Result<()> {
self.handle_request(Request::Sync(VmmAction::InsertNetworkDevice(
config.clone(),
)))
.with_context(|| {
format!(
"Request to insert a {} device",
utils::net_device_name(&config)
)
})?;
Ok(())
}

Expand Down
Loading