网络与存储
概述
Cube Hypervisor 提供多种网络和存储设备模型,满足不同场景的性能和功能需求。
网络设备
Virtio-net
Virtio-net 是标准的半虚拟化网络设备:
配置示例
json
{
"net": [
{
"tap": "tap0",
"ip": "192.168.1.1",
"mac": "00:11:22:33:44:55",
"mask": "255.255.255.0",
"num_queues": 2,
"queue_size": 256
}
]
}源码结构
rust
// virtio-devices/src/net.rs
pub struct Net {
common: VirtioCommon,
net: NetQueuePair,
ctrl_queue: Option<CtrlQueue>,
taps: Vec<Tap>,
config: VirtioNetConfig,
}
pub struct NetQueuePair {
tap: Tap,
rx: RxVirtio,
tx: TxVirtio,
counter: NetCounters,
}Vhost-user-net
Vhost-user-net 将网络后端运行在独立进程中:
配置示例
json
{
"net": [
{
"vhost_user": true,
"socket": "/tmp/vhost-net.sock",
"mac": "00:11:22:33:44:55"
}
]
}TAP 设备管理
rust
// net_util/src/lib.rs
pub struct Tap {
tap_file: File,
if_name: String,
// ...
}
impl Tap {
pub fn new(name: &str) -> Result<Tap> {
// 打开 /dev/net/tun
let tap_file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/net/tun")?;
// 配置 TAP 设备
let ifr = IfreqBuilder::new(name)?
.iff_flags(IFF_TAP | IFF_NO_PI)
.build();
unsafe {
ioctl::tun_set_iff(tap_file.as_raw_fd(), &ifr)?;
}
Ok(Self { tap_file, if_name: name.to_string() })
}
pub fn set_ip(&self, ip: Ipv4Addr) -> Result<()> {
// 设置 IP 地址
// ...
Ok(())
}
pub fn set_netmask(&self, mask: Ipv4Addr) -> Result<()> {
// 设置子网掩码
// ...
Ok(())
}
}存储设备
Virtio-blk
Virtio-blk 是标准的半虚拟化块设备:
配置示例
json
{
"disks": [
{
"path": "/path/to/rootfs.ext4",
"readonly": false,
"direct": true,
"io_uring": true,
"queue_size": 128
}
]
}源码结构
rust
// virtio-devices/src/block.rs
pub struct Block {
common: VirtioCommon,
disk_image: Box<dyn DiskFile>,
disk_path: PathBuf,
rate_limiter: Option<RateLimiter>,
read_only: bool,
serial: Vec<u8>,
config: VirtioBlockConfig,
}
impl Block {
pub fn new(
disk_path: PathBuf,
read_only: bool,
direct: bool,
io_uring: bool,
rate_limiter: Option<RateLimiter>,
) -> Result<Self> {
// 检测磁盘格式
let image_type = detect_image_type(&disk_path)?;
// 创建磁盘文件
let disk_image: Box<dyn DiskFile> = match image_type {
ImageType::Raw => {
if io_uring && block_io_uring_is_supported() {
Box::new(RawFileDisk::new(file, direct))
} else {
Box::new(RawFileDiskSync::new(file, direct))
}
}
ImageType::Qcow2 => {
Box::new(QcowDiskSync::new(file))
}
ImageType::FixedVhd => {
if io_uring {
Box::new(FixedVhdDiskAsync::new(file))
} else {
Box::new(FixedVhdDiskSync::new(file))
}
}
ImageType::Vhdx => {
Box::new(VhdxDiskSync::new(file))
}
};
Ok(Self {
disk_image,
read_only,
// ...
})
}
}Vhost-user-blk
Vhost-user-blk 将块设备后端运行在独立进程中:
Virtio-fs
Virtio-fs 允许 Guest 直接访问 Host 文件系统:
配置示例
json
{
"fs": [
{
"tag": "shared",
"socket": "/tmp/virtiofs.sock",
"shared_dir": "/path/to/shared",
"cache": "auto",
"xattr": true
}
]
}源码结构
rust
// virtio-devices/src/fs.rs
pub struct Fs {
common: VirtioCommon,
fs: PassthroughFs,
cache: CachePolicy,
thread_pool_size: usize,
xattr: XattrMap,
config: VirtioFsConfig,
}
pub struct PassthroughFs {
inodes: RwLock<InodeStore>,
handles: RwLock<HandleStore>,
mountinfo: MountInfo,
}Pmem (持久内存)
Pmem 将 Host 文件映射为 Guest 的持久内存:
json
{
"pmem": [
{
"file": "/path/to/pmem.img",
"size": 1073741824,
"iommu": false
}
]
}磁盘格式支持
支持的格式
| 格式 | 说明 | 特性 |
|---|---|---|
| Raw | 原始格式 | 简单、高性能 |
| QCOW2 | QEMU 格式 | 压缩、快照、加密 |
| VHD | 虚拟硬盘 | 动态扩展 |
| VHDX | VHD 扩展 | 更大容量、日志 |
| VMDK | VMware 格式 | 兼容性 |
格式检测
rust
// block_util/src/lib.rs
pub fn detect_image_type(path: &Path) -> Result<ImageType> {
let mut file = File::open(path)?;
let mut header = [0u8; 4];
file.read_exact(&mut header)?;
match header {
// QCOW2 魔数
[0x51, 0x46, 0x49, 0xFB] => Ok(ImageType::Qcow2),
// VHD 魔数
[0x63, 0x6F, 0x6E, 0x65] => Ok(ImageType::FixedVhd),
// VHDX 魔数
[0x76, 0x68, 0x64, 0x78] => Ok(ImageType::Vhdx),
// 默认为 Raw
_ => Ok(ImageType::Raw),
}
}I/O 优化
io_uring
io_uring 是 Linux 的异步 I/O 接口,提供更低的延迟:
rust
// block_util/src/raw_async.rs
pub struct RawFileDisk {
file: File,
io_uring: IoUring,
}
impl AsyncIo for RawFileDisk {
fn push_request(&mut self, request: Request) -> Result<()> {
// 提交 io_uring 请求
let entry = IoUringEntry {
opcode: IORING_OP_READ,
fd: self.file.as_raw_fd(),
addr: request.addr,
len: request.len,
offset: request.offset,
};
self.io_uring.submit(entry)?;
Ok(())
}
fn pop_request(&mut self) -> Result<Option<CompletedRequest>> {
// 获取完成的请求
self.io_uring.complete()
}
}直接 I/O
直接 I/O 绕过页缓存,减少内存拷贝:
rust
// block_util/src/raw_sync.rs
pub struct RawFileDiskSync {
file: File,
direct: bool,
}
impl RawFileDiskSync {
pub fn new(path: &Path, direct: bool) -> Result<Self> {
let file = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(if direct { libc::O_DIRECT } else { 0 })
.open(path)?;
Ok(Self { file, direct })
}
}限流器
Rate Limiter
Rate Limiter 限制设备的 I/O 速率:
rust
// rate_limiter/src/lib.rs
pub struct RateLimiter {
ops: TokenBucket,
bytes: TokenBucket,
}
pub struct TokenBucket {
size: u64,
one_time_burst: u64,
refill_time_ms: u64,
budget: u64,
last_update: Instant,
}
impl RateLimiter {
pub fn new(
ops_limit: u64,
bytes_limit: u64,
) -> Self {
Self {
ops: TokenBucket::new(ops_limit),
bytes: TokenBucket::new(bytes_limit),
}
}
pub fn consume(&mut self, ops: u64, bytes: u64) -> bool {
// 检查是否有足够的 token
if self.ops.consume(ops) && self.bytes.consume(bytes) {
true
} else {
// 回滚
self.ops.rollback(ops);
self.bytes.rollback(bytes);
false
}
}
}配置示例
json
{
"disks": [
{
"path": "/path/to/disk.img",
"rate_limiter": {
"ops": {
"one_time_burst": 1000,
"refill_time": 100,
"size": 100
},
"bytes": {
"one_time_burst": 1048576,
"refill_time": 100,
"size": 1048576
}
}
}
]
}性能对比
网络性能
| 设备类型 | 吞吐量 | 延迟 | CPU 开销 |
|---|---|---|---|
| Virtio-net | 高 | 低 | 中 |
| Vhost-user-net | 高 | 低 | 低 |
| VFIO NIC | 极高 | 极低 | 极低 |
存储性能
| 设备类型 | IOPS | 延迟 | CPU 开销 |
|---|---|---|---|
| Virtio-blk | 高 | 低 | 中 |
| Vhost-user-blk | 高 | 低 | 低 |
| VFIO NVMe | 极高 | 极低 | 极低 |
最佳实践
选择合适的设备类型
- 通用场景使用 Virtio
- 高性能场景使用 VFIO
- 自定义后端使用 vhost-user
启用异步 I/O
- 使用 io_uring 提升性能
- 启用直接 I/O 减少拷贝
配置限流器
- 防止单个 VM 独占资源
- 设置合理的限流阈值
选择合适的磁盘格式
- 生产环境使用 QCOW2 或 VHD
- 高性能场景使用 Raw 格式
下一步
- 深入 Virtio 设备源码
- 了解 设备管理源码