-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds the automatic creation of a tap network interface on the host when a VMM is started. Those network interfaces are named `tapletX`. Two new CLI arguments were added to configure this interface, `--network-host-ip` and `--network-host-netmask`, which configures the IP address of the tap interface on the host side. Code was taken and adapted from the [cloud-hypervisor project](https://github.com/cloud-hypervisor/cloud-hypervisor/tree/main/net_util/src). Signed-off-by: Kuruyia <github@kuruyia.net>
- Loading branch information
1 parent
823743d
commit 951a189
Showing
14 changed files
with
2,615 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the THIRD-PARTY file. | ||
|
||
use std::fmt; | ||
use std::io; | ||
use std::str::FromStr; | ||
|
||
pub const MAC_ADDR_LEN: usize = 6; | ||
|
||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
pub struct MacAddr { | ||
bytes: [u8; MAC_ADDR_LEN], | ||
} | ||
|
||
impl MacAddr { | ||
pub fn parse_str<S>(s: &S) -> Result<MacAddr, io::Error> | ||
where | ||
S: AsRef<str> + ?Sized, | ||
{ | ||
let v: Vec<&str> = s.as_ref().split(':').collect(); | ||
let mut bytes = [0u8; MAC_ADDR_LEN]; | ||
let common_err = Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("parsing of {} into a MAC address failed", s.as_ref()), | ||
)); | ||
|
||
if v.len() != MAC_ADDR_LEN { | ||
return common_err; | ||
} | ||
|
||
for i in 0..MAC_ADDR_LEN { | ||
if v[i].len() != 2 { | ||
return common_err; | ||
} | ||
bytes[i] = u8::from_str_radix(v[i], 16).map_err(|e| { | ||
io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("parsing of {} into a MAC address failed: {}", s.as_ref(), e), | ||
) | ||
})?; | ||
} | ||
|
||
Ok(MacAddr { bytes }) | ||
} | ||
|
||
// Does not check whether src.len() == MAC_ADDR_LEN. | ||
#[inline] | ||
pub fn from_bytes_unchecked(src: &[u8]) -> MacAddr { | ||
// TODO: using something like std::mem::uninitialized could avoid the extra initialization, | ||
// if this ever becomes a performance bottleneck. | ||
let mut bytes = [0u8; MAC_ADDR_LEN]; | ||
bytes[..].copy_from_slice(src); | ||
|
||
MacAddr { bytes } | ||
} | ||
|
||
// An error can only occur if the slice length is different from MAC_ADDR_LEN. | ||
#[inline] | ||
pub fn from_bytes(src: &[u8]) -> Result<MacAddr, io::Error> { | ||
if src.len() != MAC_ADDR_LEN { | ||
return Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("invalid length of slice: {} vs {}", src.len(), MAC_ADDR_LEN), | ||
)); | ||
} | ||
Ok(MacAddr::from_bytes_unchecked(src)) | ||
} | ||
|
||
#[inline] | ||
pub fn get_bytes(&self) -> &[u8] { | ||
&self.bytes | ||
} | ||
} | ||
|
||
impl fmt::Display for MacAddr { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
let b = &self.bytes; | ||
write!( | ||
f, | ||
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", | ||
b[0], b[1], b[2], b[3], b[4], b[5] | ||
) | ||
} | ||
} | ||
|
||
pub enum MacAddrParseError { | ||
InvalidValue(String), | ||
} | ||
|
||
impl FromStr for MacAddr { | ||
type Err = MacAddrParseError; | ||
|
||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { | ||
MacAddr::parse_str(s).map_err(|_| MacAddrParseError::InvalidValue(s.to_owned())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the THIRD-PARTY file. | ||
|
||
use std::{io, mem, net, os::fd::FromRawFd}; | ||
|
||
use virtio_bindings::virtio_net::virtio_net_hdr_v1; | ||
|
||
pub(crate) mod mac; | ||
pub(crate) mod net_gen; | ||
pub(crate) mod open_tap; | ||
pub(crate) mod tap; | ||
|
||
#[derive(Debug)] | ||
pub enum Error { | ||
CreateSocket(io::Error), | ||
} | ||
|
||
/// Create a sockaddr_in from an IPv4 address, and expose it as | ||
/// an opaque sockaddr suitable for usage by socket ioctls. | ||
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr { | ||
// IPv4 addresses big-endian (network order), but Ipv4Addr will give us | ||
// a view of those bytes directly so we can avoid any endian trickiness. | ||
let addr_in = net_gen::sockaddr_in { | ||
sin_family: net_gen::AF_INET as u16, | ||
sin_port: 0, | ||
// SAFETY: ip_addr can be safely transmute to in_addr | ||
sin_addr: unsafe { mem::transmute(ip_addr.octets()) }, | ||
__pad: [0; 8usize], | ||
}; | ||
|
||
// SAFETY: addr_in can be safely transmute to sockaddr | ||
unsafe { mem::transmute(addr_in) } | ||
} | ||
|
||
fn create_inet_socket() -> Result<net::UdpSocket, Error> { | ||
// SAFETY: we check the return value. | ||
let sock = unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) }; | ||
if sock < 0 { | ||
return Err(Error::CreateSocket(io::Error::last_os_error())); | ||
} | ||
|
||
// SAFETY: nothing else will use or hold onto the raw sock fd. | ||
Ok(unsafe { net::UdpSocket::from_raw_fd(sock) }) | ||
} | ||
|
||
fn create_unix_socket() -> Result<net::UdpSocket, Error> { | ||
// SAFETY: we check the return value. | ||
let sock = unsafe { libc::socket(libc::AF_UNIX, libc::SOCK_DGRAM, 0) }; | ||
if sock < 0 { | ||
return Err(Error::CreateSocket(io::Error::last_os_error())); | ||
} | ||
|
||
// SAFETY: nothing else will use or hold onto the raw sock fd. | ||
Ok(unsafe { net::UdpSocket::from_raw_fd(sock) }) | ||
} | ||
|
||
fn vnet_hdr_len() -> usize { | ||
std::mem::size_of::<virtio_net_hdr_v1>() | ||
} |
Oops, something went wrong.