Skip to content

Commit

Permalink
Merge branch 'virt-do:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
charley04310 authored Apr 8, 2024
2 parents ad1f93f + 951a189 commit 0c1e8d6
Show file tree
Hide file tree
Showing 14 changed files with 2,615 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/vmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ linux-loader = { version = "0.11.0", features = ["bzimage", "elf"] }
log = "0.4.20"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
virtio-bindings = "0.2.2"
vm-device = "0.1.0"
vm-memory = { version = "0.14.0", features = ["backend-mmap"] }
vm-superio = "0.7.0"
Expand Down
10 changes: 9 additions & 1 deletion src/vmm/src/args.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Command-line arguments.
use std::path::PathBuf;
use std::{net::Ipv4Addr, path::PathBuf};

use clap::Parser;
use clap_verbosity_flag::{InfoLevel, Verbosity};
Expand All @@ -21,6 +21,14 @@ pub struct CliArguments {
#[clap(short, long, env, default_value = "512")]
pub memory: u32,

/// IPv4 address of the host tap interface.
#[clap(long, env)]
pub network_host_ip: Ipv4Addr,

/// Subnet mask of the host tap interface.
#[clap(long, env)]
pub network_host_netmask: Ipv4Addr,

/// Verbosity level.
#[command(flatten)]
pub verbose: Verbosity<InfoLevel>,
Expand Down
5 changes: 5 additions & 0 deletions src/vmm/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ extern crate vm_superio;
use linux_loader::loader;
use std::io;

use self::network::open_tap;

mod cpu;
mod devices;
mod epoll_context;
mod kernel;
mod network;
pub mod vmm;

#[derive(Debug)]
Expand Down Expand Up @@ -48,6 +51,8 @@ pub enum Error {
StdinWrite(vm_superio::serial::Error<io::Error>),
/// Terminal configuration error
TerminalConfigure(kvm_ioctls::Error),
// Tap open error
OpenTap(open_tap::Error),
}

/// Dedicated [`Result`](https://doc.rust-lang.org/std/result/) type.
Expand Down
100 changes: 100 additions & 0 deletions src/vmm/src/core/network/mac.rs
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()))
}
}
63 changes: 63 additions & 0 deletions src/vmm/src/core/network/mod.rs
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>()
}
Loading

0 comments on commit 0c1e8d6

Please sign in to comment.