1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/openeuler-stratovirt

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
tap.rs 6.7 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
yexiao Отправлено год назад 8c394a6
// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use std::fs::{File, OpenOptions};
use std::io::{Read, Result as IoResult, Write};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc;
use anyhow::{anyhow, bail, Context, Result};
use log::error;
use nix::fcntl::{fcntl, FcntlArg, OFlag};
use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val};
use vmm_sys_util::{ioctl_ioc_nr, ioctl_ior_nr, ioctl_iow_nr};
const IFF_ATTACH_QUEUE: u16 = 0x0200;
const IFF_DETACH_QUEUE: u16 = 0x0400;
pub const TUN_F_CSUM: u32 = 1;
pub const TUN_F_TSO4: u32 = 2;
pub const TUN_F_TSO6: u32 = 4;
pub const TUN_F_TSO_ECN: u32 = 8;
pub const TUN_F_UFO: u32 = 16;
pub const TUN_F_VIRTIO: u32 = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO;
const IFF_TAP: u16 = 0x02;
pub const IFF_MULTI_QUEUE: u16 = 0x100;
const IFF_NO_PI: u16 = 0x1000;
const IFF_VNET_HDR: u16 = 0x4000;
const TUNTAP_PATH: &str = "/dev/net/tun";
const IFNAME_SIZE: usize = 16;
ioctl_iow_nr!(TUNSETIFF, 84, 202, ::std::os::raw::c_int);
ioctl_ior_nr!(TUNGETFEATURES, 84, 207, ::std::os::raw::c_uint);
ioctl_iow_nr!(TUNSETOFFLOAD, 84, 208, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETVNETHDRSZ, 84, 216, ::std::os::raw::c_int);
ioctl_iow_nr!(TUNSETQUEUE, 84, 217, ::std::os::raw::c_int);
#[repr(C)]
pub struct IfReq {
ifr_name: [u8; IFNAME_SIZE],
ifr_flags: u16,
}
#[derive(Clone)]
pub struct Tap {
pub file: Arc<File>,
pub enabled: bool,
}
impl Tap {
pub fn new(name: Option<&str>, fd: Option<RawFd>, queue_pairs: u16) -> Result<Self> {
let file;
if let Some(name) = name {
if name.len() > IFNAME_SIZE - 1 {
return Err(anyhow!("Open tap {} failed, name too long.", name));
}
let mut ifr_name = [0_u8; IFNAME_SIZE];
let (left, _) = ifr_name.split_at_mut(name.len());
left.copy_from_slice(name.as_bytes());
let mut if_req = IfReq {
ifr_name,
ifr_flags: IFF_TAP | IFF_NO_PI | IFF_VNET_HDR,
};
if queue_pairs > 1 {
if_req.ifr_flags |= IFF_MULTI_QUEUE;
}
let file_ = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(libc::O_CLOEXEC | libc::O_NONBLOCK)
.open(TUNTAP_PATH)
.with_context(|| format!("Open {} failed.", TUNTAP_PATH))?;
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
let ret = unsafe { ioctl_with_mut_ref(&file_, TUNSETIFF(), &mut if_req) };
if ret < 0 {
return Err(anyhow!(
"Failed to set tap ifr flags, error is {}",
std::io::Error::last_os_error()
));
}
file = file_;
} else if let Some(fd) = fd {
let fcnt_arg = FcntlArg::F_SETFL(OFlag::from_bits(libc::O_NONBLOCK).unwrap());
fcntl(fd, fcnt_arg)?;
// SAFETY: The fd has been verified.
file = unsafe { File::from_raw_fd(fd) };
} else {
return Err(anyhow!(
"Open tap failed, unsupported operation, error is {}",
std::io::Error::last_os_error()
));
}
let mut features = 0;
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
let ret = unsafe { ioctl_with_mut_ref(&file, TUNGETFEATURES(), &mut features) };
if ret < 0 {
return Err(anyhow!(
"Failed to get tap features, error is {}.",
std::io::Error::last_os_error()
));
}
if (features & IFF_MULTI_QUEUE == 0) && queue_pairs > 1 {
bail!("Needs multiqueue, but no kernel support for IFF_MULTI_QUEUE available");
}
Ok(Tap {
file: Arc::new(file),
enabled: true,
})
}
pub fn set_offload(&self, flags: u32) -> Result<()> {
let ret =
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
unsafe { ioctl_with_val(self.file.as_ref(), TUNSETOFFLOAD(), flags as libc::c_ulong) };
if ret < 0 {
return Err(anyhow!("ioctl TUNSETOFFLOAD failed.".to_string()));
}
Ok(())
}
pub fn set_hdr_size(&self, len: u32) -> Result<()> {
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
let ret = unsafe { ioctl_with_ref(self.file.as_ref(), TUNSETVNETHDRSZ(), &len) };
if ret < 0 {
return Err(anyhow!("ioctl TUNSETVNETHDRSZ failed.".to_string()));
}
Ok(())
}
pub fn has_ufo(&self) -> bool {
let flags = TUN_F_CSUM | TUN_F_UFO;
(
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
unsafe { ioctl_with_val(self.file.as_ref(), TUNSETOFFLOAD(), flags as libc::c_ulong) }
) >= 0
}
pub fn set_queue(&mut self, enable: bool) -> i32 {
if enable == self.enabled {
return 0;
}
let ifr_flags = if enable {
IFF_ATTACH_QUEUE
} else {
IFF_DETACH_QUEUE
};
let mut if_req = IfReq {
ifr_name: [0_u8; IFNAME_SIZE],
ifr_flags,
};
// SAFETY: The parameter of file can be guaranteed to be legal, and other parameters are constant.
let ret = unsafe { ioctl_with_mut_ref(self.file.as_ref(), TUNSETQUEUE(), &mut if_req) };
if ret == 0 {
self.enabled = enable;
} else {
error!(
"Failed to set queue, flags is {}, error is {}",
ifr_flags,
std::io::Error::last_os_error()
);
}
ret
}
pub fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
self.file.as_ref().read(buf)
}
pub fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
self.file.as_ref().write(buf)
}
pub fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/openeuler-stratovirt.git
git@gitlife.ru:oschina-mirror/openeuler-stratovirt.git
oschina-mirror
openeuler-stratovirt
openeuler-stratovirt
master