(fd: RawFd, num_queue_pairs: usize)
| 239 | } |
| 240 | |
| 241 | pub fn from_tap_fd(fd: RawFd, num_queue_pairs: usize) -> Result<Tap> { |
| 242 | // Ensure that the file is opened non-blocking, this is particularly |
| 243 | // needed when opened via the shell for macvtap. |
| 244 | // SAFETY: FFI call |
| 245 | let ret = unsafe { |
| 246 | let mut flags = libc::fcntl(fd, libc::F_GETFL); |
| 247 | flags |= libc::O_NONBLOCK; |
| 248 | libc::fcntl(fd, libc::F_SETFL, flags) |
| 249 | }; |
| 250 | if ret < 0 { |
| 251 | return Err(Error::ConfigureTap(IoError::last_os_error())); |
| 252 | } |
| 253 | |
| 254 | // SAFETY: fd is a tap fd |
| 255 | let tap_file = unsafe { File::from_raw_fd(fd) }; |
| 256 | let mut ifreq: libc::ifreq = ifreq { |
| 257 | ifr_name: [0; libc::IFNAMSIZ], |
| 258 | ifr_ifru: __c_anonymous_ifr_ifru { ifru_flags: 0 }, |
| 259 | }; |
| 260 | |
| 261 | // Get current config including name |
| 262 | // SAFETY: IOCTL with correct arguments |
| 263 | unsafe { Self::ioctl_with_mut_ref(&tap_file, libc::TUNGETIFF as c_ulong, &mut ifreq)? }; |
| 264 | |
| 265 | let if_name = { |
| 266 | let ifr_ptr = ifreq.ifr_name.as_ptr(); |
| 267 | // SAFETY: The `ifr_name` field of the union is a valid, nul-terminated C string since it |
| 268 | // was just set by the ioctl call, and we checked for errors. |
| 269 | // We immediately convert the `CStr` to the owned `CString, so the memory of the union field |
| 270 | // is not accessed or mutated during the lifetime of the `Cstr`. |
| 271 | unsafe { CStr::from_ptr(ifr_ptr).to_owned() } |
| 272 | }; |
| 273 | |
| 274 | // Try and update flags. Depending on how the tap was created (macvtap |
| 275 | // or via open_named()) this might return -EEXIST so we just ignore that. |
| 276 | // SAFETY: access union fields |
| 277 | unsafe { |
| 278 | ifreq.ifr_ifru.ifru_flags = |
| 279 | (libc::IFF_TAP | libc::IFF_NO_PI | libc::IFF_VNET_HDR) as c_short; |
| 280 | if num_queue_pairs > 1 { |
| 281 | ifreq.ifr_ifru.ifru_flags |= libc::IFF_MULTI_QUEUE as c_short; |
| 282 | } |
| 283 | } |
| 284 | // SAFETY: IOCTL with correct arguments |
| 285 | let ret = unsafe { ioctl_with_mut_ref(&tap_file, libc::TUNSETIFF as c_ulong, &mut ifreq) }; |
| 286 | if ret < 0 && IoError::last_os_error().raw_os_error().unwrap() != libc::EEXIST { |
| 287 | return Err(Error::ConfigureTap(IoError::last_os_error())); |
| 288 | } |
| 289 | |
| 290 | let tap = Tap { tap_file, if_name }; |
| 291 | let vnet_hdr_size = vnet_hdr_len() as i32; |
| 292 | tap.set_vnet_hdr_size(vnet_hdr_size)?; |
| 293 | |
| 294 | Ok(tap) |
| 295 | } |
| 296 | |
| 297 | /// Set the host-side IP address for the tap interface. |
| 298 | pub fn set_ip_addr(&self, ip_addr: IpAddr, netmask: Option<IpAddr>) -> Result<()> { |
nothing calls this directly
no test coverage detected