diff --git a/Cargo.toml b/Cargo.toml index 00ca3fc..953f54c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ figment = { version = "0.10", features = ["toml", "env", "json"] } futures = "0.3.29" human-bandwidth = { version = "0.1.1", features = ["serde"] } netem-trace = { version = "0.3.3", features = ["serde", "human", "mahimahi"] } -nix = "0.26.2" +nix = { version = "0.29.0", features = ["time", "net", "event", "ioctl", "mount", "sched"]} once_cell = "1.19" rand = "0.8.5" serde = { version = "1.0.160", features = ["derive"] } diff --git a/rattan-core/src/metal/ioctl.rs b/rattan-core/src/metal/ioctl.rs index 38b2dbb..689d59a 100644 --- a/rattan-core/src/metal/ioctl.rs +++ b/rattan-core/src/metal/ioctl.rs @@ -1,3 +1,5 @@ +use std::os::fd::AsRawFd; + use libc::{__c_anonymous_ifr_ifru, c_char, c_uint, ifreq}; use nix::{ errno::Errno, @@ -108,7 +110,7 @@ pub fn get_feature_flag(name: &str) -> Result<[u32; OFF_FLAG_DEF_SIZE], VethErro eval.data = 0; ifr.ifr_ifru.ifru_data = &mut eval as *mut EthtoolValue as *mut c_char; - let res = unsafe { ethtool_ioctl(fd, &mut ifr) }; + let res = unsafe { ethtool_ioctl(fd.as_raw_fd(), &mut ifr) }; match res { Ok(_) => { flags[i] = eval.data; @@ -147,7 +149,7 @@ pub fn disable_checksum_offload(name: &str) -> Result<(), VethError> { eval.data = 0; ifr.ifr_ifru.ifru_data = &mut eval as *mut EthtoolValue as *mut c_char; - let res = unsafe { ethtool_ioctl(fd, &mut ifr) }; + let res = unsafe { ethtool_ioctl(fd.as_raw_fd(), &mut ifr) }; match res { Ok(_) => {} Err(Errno::EOPNOTSUPP) => {} diff --git a/rattan-core/src/metal/netns.rs b/rattan-core/src/metal/netns.rs index bdc964b..c233618 100644 --- a/rattan-core/src/metal/netns.rs +++ b/rattan-core/src/metal/netns.rs @@ -1,4 +1,5 @@ use std::fs::File; +use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::fs::MetadataExt; use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; @@ -217,6 +218,12 @@ impl AsRawFd for NetNs { } } +impl AsFd for NetNs { + fn as_fd(&self) -> BorrowedFd<'_> { + self.file.as_fd() + } +} + impl std::fmt::Display for NetNs { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { if let Ok(meta) = self.file.metadata() { @@ -276,7 +283,7 @@ impl NetNs { pub fn enter(&self) -> Result>, NsError> { let current_ns = self.env.clone().current()?; trace!("entering netns: {}", self.path.to_string_lossy()); - setns(self.as_raw_fd(), CloneFlags::CLONE_NEWNET).map_err(NsError::SetNsError)?; + setns(self.as_fd(), CloneFlags::CLONE_NEWNET).map_err(NsError::SetNsError)?; Ok(current_ns) } diff --git a/rattan-core/src/metal/timer.rs b/rattan-core/src/metal/timer.rs index 15ba3d8..2edc403 100644 --- a/rattan-core/src/metal/timer.rs +++ b/rattan-core/src/metal/timer.rs @@ -1,4 +1,4 @@ -use std::os::fd::AsRawFd; +use std::os::fd::{AsFd, AsRawFd}; use nix::sys::{ time::TimeSpec, @@ -10,16 +10,24 @@ use crate::metal::error::MetalError; // High-resolution timer pub struct Timer { - timer: AsyncFd, + timer: AsyncFd, +} + +pub struct WrapperTimer(pub TimerFd); + +impl AsRawFd for WrapperTimer { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + self.0.as_fd().as_raw_fd() + } } impl Timer { pub fn new() -> Result { Ok(Self { - timer: AsyncFd::new(TimerFd::new( + timer: AsyncFd::new(WrapperTimer(TimerFd::new( ClockId::CLOCK_MONOTONIC, TimerFlags::TFD_NONBLOCK, - )?)?, + )?))?, }) } @@ -28,7 +36,7 @@ impl Timer { if duration.as_nanos() == 0 { return Ok(()); } - self.timer.get_mut().set( + self.timer.get_mut().0.set( Expiration::OneShot(TimeSpec::from_duration(duration)), TimerSetTimeFlags::empty(), )?; diff --git a/rattan-core/tests/external/af_packet.rs b/rattan-core/tests/external/af_packet.rs index 76819c8..f15996b 100644 --- a/rattan-core/tests/external/af_packet.rs +++ b/rattan-core/tests/external/af_packet.rs @@ -2,10 +2,11 @@ /// CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER='sudo -E' cargo test af_packet -- --ignored --nocapture use libc::{c_void, size_t, sockaddr, sockaddr_ll, socklen_t}; use nix::errno::Errno; -use nix::sys::epoll::{epoll_create, epoll_ctl, epoll_wait, EpollEvent, EpollFlags}; +use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags, EpollTimeout}; use nix::sys::socket::{AddressFamily, SockType}; use rattan_core::env::{get_std_env, StdNetEnvConfig}; use rattan_core::metal::veth::{MacAddr, VethCell}; +use std::os::fd::{FromRawFd, OwnedFd}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::{mem, ptr}; @@ -166,34 +167,27 @@ fn af_packet_test() -> anyhow::Result<()> { ) }; - let epoll_fd = epoll_create().unwrap(); - - epoll_ctl( - epoll_fd, - nix::sys::epoll::EpollOp::EpollCtlAdd, - left_sniffer, - Some(&mut EpollEvent::new( - EpollFlags::EPOLLIN, - left_sniffer as u64, - )), - ) - .unwrap(); - - epoll_ctl( - epoll_fd, - nix::sys::epoll::EpollOp::EpollCtlAdd, - right_sniffer, - Some(&mut EpollEvent::new( - EpollFlags::EPOLLIN, - right_sniffer as u64, - )), - ) - .unwrap(); + let left_sniffer_fd = unsafe { OwnedFd::from_raw_fd(left_sniffer) }; + let epoll_instance = Epoll::new(EpollCreateFlags::empty()).unwrap(); + epoll_instance + .add( + left_sniffer_fd, + EpollEvent::new(EpollFlags::EPOLLIN, left_sniffer as u64), + ) + .unwrap(); + let right_sniffer_fd = unsafe { OwnedFd::from_raw_fd(right_sniffer) }; + epoll_instance + .add( + right_sniffer_fd, + EpollEvent::new(EpollFlags::EPOLLIN, right_sniffer as u64), + ) + .unwrap(); // Large enough to receive frame of localhost. let mut buf = [0u8; 65537]; let mut events = [EpollEvent::empty(); 100]; let timeout_ms = 1000; + let epoll_timeout = EpollTimeout::try_from(timeout_ms).unwrap(); let running = Arc::new(AtomicBool::new(true)); let rclone = running.clone(); @@ -203,7 +197,7 @@ fn af_packet_test() -> anyhow::Result<()> { .expect("unable to install ctrl+c handler"); while running.load(Ordering::Acquire) { - let _num_events = epoll_wait(epoll_fd, &mut events, timeout_ms).unwrap(); + let _num_events = epoll_instance.wait(&mut events, epoll_timeout).unwrap(); for event in events { let fd = event.data() as i32;