//! Intel 10Gb Network Adapter 82599 i.e. ixgbe network driver //! Datasheet: https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; use alloc::collections::BTreeMap; use isomorphic_drivers::net::ethernet::intel::ixgbe; use log::*; use rcore_memory::paging::PageTable; use rcore_memory::PAGE_SIZE; use smoltcp::iface::*; use smoltcp::phy::{self, Checksum, DeviceCapabilities}; use smoltcp::time::Instant; use smoltcp::wire::EthernetAddress; use smoltcp::wire::*; use smoltcp::Result; use crate::memory::active_table; use crate::net::SOCKETS; use crate::sync::FlagsGuard; use crate::sync::SpinNoIrqLock as Mutex; use super::super::{provider::Provider, DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; #[derive(Clone)] struct IXGBEDriver { inner: ixgbe::IXGBEDriver, header: usize, size: usize, mtu: usize, } pub struct IXGBEInterface { iface: Mutex>, driver: IXGBEDriver, ifname: String, irq: Option, id: String, } impl Driver for IXGBEInterface { fn try_handle_interrupt(&self, irq: Option) -> bool { if irq.is_some() && self.irq.is_some() && irq != self.irq { // not ours, skip it return false; } let handled = { let _ = FlagsGuard::no_irq_region(); self.driver.inner.try_handle_interrupt() }; if handled { let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64); let mut sockets = SOCKETS.lock(); match self.iface.lock().poll(&mut sockets, timestamp) { Ok(_) => { SOCKET_ACTIVITY.notify_all(); } Err(err) => { debug!("poll got err {}", err); } } } return handled; } fn device_type(&self) -> DeviceType { DeviceType::Net } fn get_id(&self) -> String { self.ifname.clone() } fn get_mac(&self) -> EthernetAddress { self.iface.lock().ethernet_addr() } fn get_ifname(&self) -> String { self.ifname.clone() } fn ipv4_address(&self) -> Option { self.iface.lock().ipv4_address() } fn poll(&self) { let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64); let mut sockets = SOCKETS.lock(); match self.iface.lock().poll(&mut sockets, timestamp) { Ok(_) => { SOCKET_ACTIVITY.notify_all(); } Err(err) => { debug!("poll got err {}", err); } } } } pub struct IXGBERxToken(Vec); pub struct IXGBETxToken(IXGBEDriver); impl<'a> phy::Device<'a> for IXGBEDriver { type RxToken = IXGBERxToken; type TxToken = IXGBETxToken; fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { let _ = FlagsGuard::no_irq_region(); if self.inner.can_send() { if let Some(data) = self.inner.recv() { Some((IXGBERxToken(data), IXGBETxToken(self.clone()))) } else { None } } else { None } } fn transmit(&'a mut self) -> Option { let _ = FlagsGuard::no_irq_region(); if self.inner.can_send() { Some(IXGBETxToken(self.clone())) } else { None } } fn capabilities(&self) -> DeviceCapabilities { let mut caps = DeviceCapabilities::default(); // do not use max MTU by default //caps.max_transmission_unit = ixgbe::IXGBEDriver::get_mtu(); // max MTU caps.max_transmission_unit = self.mtu; caps.max_burst_size = Some(256); // IP Rx checksum is offloaded with RXCSUM caps.checksum.ipv4 = Checksum::Tx; caps } } impl phy::RxToken for IXGBERxToken { fn consume(self, _timestamp: Instant, f: F) -> Result where F: FnOnce(&[u8]) -> Result, { f(&self.0) } } impl phy::TxToken for IXGBETxToken { fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result, { let _ = FlagsGuard::no_irq_region(); let mut buffer = [0u8; ixgbe::IXGBEDriver::get_mtu()]; let result = f(&mut buffer[..len]); if result.is_ok() { (self.0).inner.send(&buffer[..len]); } result } } pub fn ixgbe_init( name: String, irq: Option, header: usize, size: usize, ) -> Arc { let _ = FlagsGuard::no_irq_region(); let ixgbe = ixgbe::IXGBEDriver::init(Provider::new(), header, size); ixgbe.enable_irq(); let ethernet_addr = EthernetAddress::from_bytes(&ixgbe.get_mac().as_bytes()); let net_driver = IXGBEDriver { inner: ixgbe, header, size, mtu: 1500, }; let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 0, 2), 24)]; let neighbor_cache = NeighborCache::new(BTreeMap::new()); let mut routes = Routes::new(BTreeMap::new()); routes .add_default_ipv4_route(Ipv4Address::new(10, 0, 0, 1)) .unwrap(); let mut iface = EthernetInterfaceBuilder::new(net_driver.clone()) .ethernet_addr(ethernet_addr) .ip_addrs(ip_addrs) .neighbor_cache(neighbor_cache) .routes(routes) .finalize(); info!("ixgbe: interface {} up", &name); let ixgbe_iface = IXGBEInterface { iface: Mutex::new(iface), driver: net_driver.clone(), ifname: name.clone(), id: name, irq, }; let driver = Arc::new(ixgbe_iface); DRIVERS.write().push(driver.clone()); NET_DRIVERS.write().push(driver.clone()); driver }