You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.8 KiB

//! 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<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>,
driver: IXGBEDriver,
ifname: String,
irq: Option<u32>,
id: String,
}
impl Driver for IXGBEInterface {
fn try_handle_interrupt(&self, irq: Option<u32>) -> 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<Ipv4Address> {
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<u8>);
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<Self::TxToken> {
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<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&[u8]) -> Result<R>,
{
f(&self.0)
}
}
impl phy::TxToken for IXGBETxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
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<u32>,
header: usize,
size: usize,
) -> Arc<IXGBEInterface> {
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
}