Skip to content

Commit

Permalink
Implement smoltcp with VirtIO NIC (#229)
Browse files Browse the repository at this point in the history
* Pcie

* continued work. Working on share function. DMA appears to work properly

* Moved device detection into transport layer

* cargo fmt

* commented out logln! in full interrupt queue message

* made some variables immutable to squash warnings.

* cleanup warnings and debug prints

* make things public, comment out prints

* cleaned up old lines in qemu.rs

* Compiles with main merged in. Moved the tcp implementations into the lib folder.

* cargo fmt

* Removed commented out log in kernel/interrupt, and restored a log that was mistakenly commnented out by me. Removed white space from lib/virtio-net/hal

* deleted log I thought I mistakently commented out, which was actually already commented out on main.
  • Loading branch information
TheTadLands authored Dec 30, 2024
1 parent 4683e39 commit 648a0c3
Show file tree
Hide file tree
Showing 13 changed files with 1,117 additions and 7 deletions.
149 changes: 147 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"src/bin/pager",
"src/bin/mnemosyne",
"src/bin/stdfs_demo",
"src/bin/virtio",
"src/kernel",
"src/lib/twizzler-queue-raw",
"src/lib/twizzler-queue",
Expand All @@ -32,7 +33,8 @@ members = [
"src/abi/types",
"src/lib/logboi",
"src/srv/logboi-srv",
"src/bin/logboi-test",
"src/bin/logboi-test",
"src/lib/virtio-net",
]

exclude = ["toolchain/src/rust"]
Expand All @@ -44,6 +46,7 @@ initrd = [
"crate:init",
"crate:devmgr",
"crate:pager",
"crate:virtio",
"lib:twz-rt",
"crate:monitor",
"crate:montest",
Expand Down
19 changes: 19 additions & 0 deletions src/bin/virtio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "virtio"
version = "0.1.0"
edition = "2021"

[dependencies]

virtio-net = { path = "../../lib/virtio-net" }

[dependencies.smoltcp]
version = "0.11.0"
optional = false
default-features = true
features = [
"alloc", "log",
"medium-ethernet",
"proto-ipv4",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp",
]
100 changes: 100 additions & 0 deletions src/bin/virtio/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use core::{cell::RefCell, str::FromStr};
use std::{borrow::ToOwned, rc::Rc, vec, vec::Vec};

use smoltcp::{
iface::{Config, Interface, SocketSet},
phy::{Device, DeviceCapabilities, Medium},
socket::tcp,
time::Instant,
wire::{EthernetAddress, HardwareAddress, IpAddress, IpCidr, Ipv4Address},
};
use virtio_net::{get_device, DeviceWrapper};

const IP: &str = "10.0.2.15"; // QEMU user networking default IP
const GATEWAY: &str = "10.0.2.2"; // QEMU user networking gateway
const PORT: u16 = 5555;

fn main() {
test_echo_server();
}

fn test_echo_server() {
let mut device = get_device();

if device.capabilities().medium != Medium::Ethernet {
panic!("This implementation only supports virtio-net which is an ethernet device");
}

let hardware_addr = HardwareAddress::Ethernet(device.mac_address());

// Create interface
let mut config = Config::new(hardware_addr);
config.random_seed = 0x2333;

let mut iface = Interface::new(config, &mut device, Instant::now());
iface.update_ip_addrs(|ip_addrs| {
ip_addrs
.push(IpCidr::new(IpAddress::from_str(IP).unwrap(), 24))
.unwrap();
});

iface
.routes_mut()
.add_default_ipv4_route(Ipv4Address::from_str(GATEWAY).unwrap())
.unwrap();

// Create sockets
let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 1024]);
let tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);

let mut sockets = SocketSet::new(vec![]);
let tcp_handle = sockets.add(tcp_socket);

println!("start a echo server...");
let mut tcp_active = false;
loop {
let timestamp = Instant::now();

iface.poll(timestamp, &mut device, &mut sockets);

let socket = sockets.get_mut::<tcp::Socket>(tcp_handle);
if !socket.is_open() {
println!("listening on port {}...", PORT);
socket.listen(PORT).unwrap();
}

if socket.is_active() && !tcp_active {
println!("tcp:{} connected", PORT);
} else if !socket.is_active() && tcp_active {
println!("tcp:{} disconnected", PORT);
}
tcp_active = socket.is_active();

if socket.may_recv() {
let data = socket
.recv(|buffer| {
let recvd_len = buffer.len();
if !buffer.is_empty() {
println!("tcp:{} recv {} bytes: {:?}", PORT, recvd_len, buffer);
let lines = buffer
.split(|&b| b == b'\n')
.map(ToOwned::to_owned)
.collect::<Vec<_>>();
let data = lines.join(&b'\n');
(recvd_len, data)
} else {
(0, vec![])
}
})
.unwrap();
if socket.can_send() && !data.is_empty() {
println!("tcp:{} send data: {:?}", PORT, data);
socket.send_slice(&data[..]).unwrap();
}
} else if socket.may_send() {
println!("tcp:{} close", PORT);
socket.close();
}
}
}
2 changes: 0 additions & 2 deletions src/kernel/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ pub fn handle_interrupt(number: u32) {
let gi = get_global_interrupts();
gi.ints[number as usize].raise();
if number != 43 {
//logln!("external device interrupt {}", number);
}
}

Expand All @@ -174,7 +173,6 @@ impl InterruptQueue {
fn enqueue(&mut self, int: u32) {
if self.is_full() {
// TODO: extend this mechanism to avoid dropping interrupts
logln!("dropped interrupt {}", int);
return;
}
self.queue[self.head] = int;
Expand Down
Loading

0 comments on commit 648a0c3

Please sign in to comment.