MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / from_tap_fd

Method from_tap_fd

net_util/src/tap.rs:241–295  ·  view source on GitHub ↗
(fd: RawFd, num_queue_pairs: usize)

Source from the content-addressed store, hash-verified

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<()> {

Callers

nothing calls this directly

Calls 3

fcntlFunction · 0.85
vnet_hdr_lenFunction · 0.85
set_vnet_hdr_sizeMethod · 0.80

Tested by

no test coverage detected