mirror of
https://git.checksum.fail/alec/erythros
synced 2025-12-13 14:39:54 +02:00
173 lines
5.9 KiB
Plaintext
173 lines
5.9 KiB
Plaintext
import devices::virtio { VirtIO, VirtIOReg }
|
|
|
|
import lib::util { Util }
|
|
|
|
import os::os { OS }
|
|
import os::pci { PCI, PCIDevice }
|
|
import os::time { Time }
|
|
|
|
import tcpip { TCPIP }
|
|
|
|
class NetDevices {
|
|
public virtio: VirtIO
|
|
public fn create(pci_device: PCIDevice) throws -> NetDevices {
|
|
return NetDevices(
|
|
virtio: VirtIO(pci_device, rq_index: 0, rq_size: 0, rq: 0, tq_size: 0, tq: 0)
|
|
)
|
|
}
|
|
}
|
|
|
|
class Net {
|
|
public device: NetDevices
|
|
public mac_address: [u8]
|
|
public tcpip: TCPIP
|
|
public pci_device: PCIDevice
|
|
public fn init(config: [String:String]) throws -> Net {
|
|
let pci_device = PCI::find_device_by_class_code(0x020000)
|
|
mut net = Net(
|
|
device: NetDevices::create(pci_device)
|
|
mac_address: []
|
|
tcpip: TCPIP(
|
|
ipv4_address: Util::get_ipv4_u8_array_from_address_string(config["tcpip.ipv4_address"])
|
|
ipv4_netmask: Util::get_ipv4_u8_array_from_address_string(config["tcpip.ipv4_netmask"])
|
|
ipv4_network: Util::get_ipv4_u8_array_from_address_string(config["tcpip.ipv4_network"])
|
|
ipv4_gateway: Util::get_ipv4_u8_array_from_address_string(config["tcpip.ipv4_gateway"])
|
|
dns_server_address: Util::get_ipv4_u8_array_from_address_string(config["tcpip.ipv4_dns_server_address"])
|
|
dns_server_port: config["tcpip.ipv4_dns_server_port"].to_number<u32>().value() as! u16
|
|
mss_size: config["tcpip.mss_size"].to_number<u32>().value() as! u16
|
|
tx_queue: []
|
|
ttl: 64
|
|
arp_cache: Dictionary()
|
|
bound_sockets: Dictionary()
|
|
dns_cache: Dictionary()
|
|
tcp_sessions: []
|
|
pending_dns_lookups: Dictionary()
|
|
pending_dns_cached_entries: Dictionary()
|
|
pending_icmp_requests: Dictionary()
|
|
timestamp_last_arp_request: 0
|
|
rx_bytes: 0
|
|
rx_frames: 0
|
|
tx_bytes: 0
|
|
tx_frames: 0
|
|
)
|
|
pci_device
|
|
)
|
|
if net.pci_device.vendor_id() == 0x1af4 and net.pci_device.device_id() == 0x1000 {
|
|
println("[net] Found device: virtio-net, QEMU")
|
|
for i in 0u16..6u16 {
|
|
net.mac_address.push(net.pci_device.io_read_u8(VirtIOReg::config as! u16 + i))
|
|
}
|
|
net.device.virtio.init()
|
|
return net
|
|
}
|
|
println("[net] No supported vendor ids found")
|
|
OS::exit()
|
|
return net
|
|
}
|
|
fn process_ethernet_frame(mut this, anon frame: [u8]) throws {
|
|
let ethertype: u16 = (frame[12] as! u16 * 256) + frame[13] as! u16
|
|
match ethertype {
|
|
0x0806 => {
|
|
//println("ARP")
|
|
.tcpip.process_arp_packet(.mac_address, frame)
|
|
}
|
|
0x0800 => {
|
|
//println("IPv4")
|
|
.tcpip.process_ipv4_packet(.mac_address, frame)
|
|
}
|
|
0x86dd => {
|
|
//.tcpip.process_ipv6_packet(frame)
|
|
}
|
|
0x8035 => {
|
|
//.tcpip.process_rarp_packet(frame)
|
|
}
|
|
else => {
|
|
// unsupported
|
|
}
|
|
}
|
|
}
|
|
public fn process_events(mut this) throws {
|
|
mut received_frame = .rx_frame()
|
|
if received_frame.size() > 0 {
|
|
.tcpip.rx_bytes += received_frame.size() as! u64
|
|
.tcpip.rx_frames++
|
|
.process_ethernet_frame(received_frame)
|
|
}
|
|
.tcpip.tcp_transmit_pending_data_for_existing_sessions()
|
|
for frame in .tcpip.tx_queue {
|
|
.tx_frame(frame)
|
|
}
|
|
if .tcpip.tx_queue.size() > 0 {
|
|
.tcpip.tx_queue.shrink(0)
|
|
}
|
|
.tcpip.tcp_process_bind_request()
|
|
.tcpip.tcp_process_client_socket_request(.mac_address)
|
|
.tcpip.tcp_process_client_received_data()
|
|
.tcpip.tcp_process_client_send_requests(.mac_address)
|
|
.tcpip.dns_process_client_request(.mac_address)
|
|
.tcpip.icmp_process_client_request(.mac_address)
|
|
.tcpip.netinfo_process_client_request(.mac_address)
|
|
}
|
|
fn rx_frame(mut this) throws -> [u8] {
|
|
mut frame: [u8] = []
|
|
if .pci_device.vendor_id() == 0x1af4 and .pci_device.device_id() == 0x1000 {
|
|
frame = .device.virtio.rx_frame()
|
|
}
|
|
return frame
|
|
}
|
|
fn tx_frame(mut this, anon mut data: [u8]) throws {
|
|
if data.size() < 1 {
|
|
return
|
|
}
|
|
while data.size() < 60 {
|
|
data.push(0u8)
|
|
}
|
|
.tcpip.tx_bytes += data.size() as! u64
|
|
.tcpip.tx_frames++
|
|
if .pci_device.vendor_id() == 0x1af4 and .pci_device.device_id() == 0x1000 {
|
|
.device.virtio.tx_frame(data)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
println("$WW,1$")
|
|
mut config = Util::get_dictionary_from_json_file("M:/System/Config/Net.json")
|
|
mut net = Net::init(config)
|
|
|
|
println("[net] PCI device is {}", net.pci_device)
|
|
print("[net] MAC address is ")
|
|
for i in 0u16..5u16 {
|
|
print("{:0>2x}:", net.mac_address[i])
|
|
}
|
|
println("{:0>2x}", net.mac_address[5])
|
|
print("[net] IPv4 address is ")
|
|
for i in 0u16..3u16 {
|
|
print("{:d}.", net.tcpip.ipv4_address[i])
|
|
}
|
|
println("{:d}", net.tcpip.ipv4_address[3])
|
|
println(" ")
|
|
|
|
// Update the ARP cache entry for IPv4 gateway address
|
|
net.tcpip.send_arp_request(net.mac_address, net.tcpip.ipv4_gateway)
|
|
|
|
mut prev_rx_frames = net.tcpip.rx_frames
|
|
mut prev_tx_frames = net.tcpip.tx_frames
|
|
mut prev_jiffies = Time::jiffies()
|
|
|
|
while true {
|
|
net.process_events()
|
|
if (prev_rx_frames != net.tcpip.rx_frames) or (prev_tx_frames != net.tcpip.tx_frames) {
|
|
prev_rx_frames = net.tcpip.rx_frames
|
|
prev_tx_frames = net.tcpip.tx_frames
|
|
prev_jiffies = Time::jiffies()
|
|
}
|
|
if Time::jiffies() < prev_jiffies + 250 {
|
|
Time::sleep(0)
|
|
} else {
|
|
Time::sleep(1)
|
|
}
|
|
}
|
|
|
|
OS::exit()
|
|
} |