eth: collect some stats

eth-stats
Astro 2020-07-30 19:19:43 +02:00
parent 1f05e6977e
commit 4158906122
3 changed files with 66 additions and 8 deletions

View File

@ -160,6 +160,7 @@ pub fn main_core0() {
flash = flash_io.stop();
}
if false {
let core1 = boot::Core1::start(false);
let (mut core1_req, rx) = sync_channel!(usize, 10);
@ -174,20 +175,21 @@ pub fn main_core0() {
}
});
core1.disable();
}
let eth = zynq::eth::Eth::default(HWADDR.clone());
println!("Eth on");
const RX_LEN: usize = 4096;
const RX_LEN: usize = 8192;
// Number of transmission buffers (minimum is two because with
// one, duplicate packet transmission occurs)
const TX_LEN: usize = 4096;
const TX_LEN: usize = 8192;
let eth = eth.start_rx(RX_LEN);
let mut eth = eth.start_tx(TX_LEN);
let ethernet_addr = EthernetAddress(HWADDR);
// IP stack
let local_addr = IpAddress::v4(192, 168, 1, 51);
let local_addr = IpAddress::v4(192, 168, 1, 54);
let mut ip_addrs = [IpCidr::new(local_addr, 24)];
let routes = Routes::new(BTreeMap::new());
let neighbor_cache = NeighborCache::new(BTreeMap::new());
@ -228,7 +230,7 @@ pub fn main_core0() {
});
let stats_rx = stats.clone();
task::spawn(async move {
while let Ok(stream) = TcpStream::accept(TCP_PORT+1, 0x10_0000, 0x10_0000).await {
while let Ok(stream) = TcpStream::accept(TCP_PORT+1, 4096, 4096).await {
let stats_rx = stats_rx.clone();
task::spawn(async move {
loop {
@ -262,7 +264,16 @@ pub fn main_core0() {
}
});
Sockets::run(&mut iface, || {
let mut last_stats_time = 0;
Sockets::run(&mut iface, |iface| {
let t = timer.get_time().0;
if t - last_stats_time >= 1000 {
let stats = &mut iface.device_mut().stats;
info!("eth stats: {:?}", stats);
stats.reset();
last_stats_time = t;
}
Instant::from_millis(timer.get_time().0 as i64)
})
}

View File

@ -43,11 +43,11 @@ impl Sockets {
/// iface
pub fn run<'b, 'c, 'e, D: for<'d> Device<'d>>(
iface: &mut EthernetInterface<'b, 'c, 'e, D>,
mut get_time: impl FnMut() -> Instant,
mut get_time: impl FnMut(&mut EthernetInterface<'b, 'c, 'e, D>) -> Instant,
) -> ! {
task::block_on(async {
loop {
let instant = get_time();
let instant = get_time(iface);
Self::instance().poll(iface, instant);
task::r#yield().await;
}

View File

@ -140,11 +140,43 @@ fn calculate_tx_divisors(tx_clock: u32) -> (u8, u8) {
result
}
#[derive(Debug)]
pub struct EthStats {
frame_recd: usize,
no_frame_recd: usize,
rx_idle: usize,
tx_send: usize,
tx_overflow: usize,
}
impl EthStats {
pub fn new() -> Self {
EthStats {
frame_recd: 0,
no_frame_recd: 0,
rx_idle: 0,
tx_send: 0,
tx_overflow: 0,
}
}
pub fn reset(&mut self) {
*self = EthStats {
frame_recd: 0,
no_frame_recd: 0,
rx_idle: 0,
tx_send: 0,
tx_overflow: 0,
};
}
}
pub struct Eth<GEM: Gem, RX, TX> {
rx: RX,
tx: TX,
inner: EthInner<GEM>,
phy: Phy,
pub stats: EthStats,
}
impl Eth<Gem0, (), ()> {
@ -303,6 +335,7 @@ impl<GEM: Gem> Eth<GEM, (), ()> {
inner.configure(macaddr);
let phy = Phy::find(&mut inner).expect("phy");
info!("Eth: found PHY {}", phy.name());
phy.reset(&mut inner);
phy.restart_autoneg(&mut inner);
@ -311,6 +344,7 @@ impl<GEM: Gem> Eth<GEM, (), ()> {
tx: (),
inner,
phy,
stats: EthStats::new(),
}
}
}
@ -322,6 +356,7 @@ impl<GEM: Gem, RX, TX> Eth<GEM, RX, TX> {
tx: self.tx,
inner: self.inner,
phy: self.phy,
stats: self.stats,
};
let list_addr = new_self.rx.list_addr();
assert!(list_addr & 0b11 == 0);
@ -341,6 +376,7 @@ impl<GEM: Gem, RX, TX> Eth<GEM, RX, TX> {
tx: tx::DescList::new(tx_size),
inner: self.inner,
phy: self.phy,
stats: self.stats,
};
let list_addr = &new_self.tx.list_addr();
assert!(list_addr & 0b11 == 0);
@ -387,16 +423,19 @@ impl<GEM: Gem, TX> Eth<GEM, rx::DescList, TX> {
let result = self.rx.recv_next();
match result {
Ok(None) => {
self.stats.no_frame_recd += 1;
// No packet, clear status bit
GEM::regs().rx_status.write(
regs::RxStatus::zeroed()
.frame_recd(true)
);
}
Ok(Some(_)) => self.stats.frame_recd += 1,
_ => {}
}
result
} else {
self.stats.rx_idle += 1;
self.inner.check_link_change(&self.phy);
Ok(None)
}
@ -405,7 +444,13 @@ impl<GEM: Gem, TX> Eth<GEM, rx::DescList, TX> {
impl<GEM: Gem, RX> Eth<GEM, RX, tx::DescList> {
pub fn send<'s: 'p, 'p>(&'s mut self, length: usize) -> Option<tx::PktRef<'p>> {
self.tx.send(GEM::regs(), length)
let result = self.tx.send(GEM::regs(), length);
if result.is_some() {
self.stats.tx_send += 1;
} else {
self.stats.tx_overflow += 1;
}
result
}
}
@ -432,6 +477,7 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth<GEM, rx::DescList, tx::
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
match self.rx.recv_next() {
Ok(Some(pktref)) => {
self.stats.frame_recd += 1;
let tx_token = tx::Token {
regs: GEM::regs(),
desc_list: &mut self.tx,
@ -439,6 +485,7 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth<GEM, rx::DescList, tx::
Some((pktref, tx_token))
}
Ok(None) => {
self.stats.rx_idle += 1;
self.inner.check_link_change(&self.phy);
None
}