[rust][ethernet] Distinguish tx_echo from rx
If listen_tx is enabled for the client, it is impossible to tell whether
a Receive event is caused by tx echo or a packet that is received. So
include the flags as part of the Receive event.
Test: Verified behavior with eth-rs
Change-Id: Ice7c2353f5b634bea30ee181eb8113b345940377
diff --git a/bin/recovery_netstack/src/eventloop.rs b/bin/recovery_netstack/src/eventloop.rs
index dfe749b..285f6f8 100644
--- a/bin/recovery_netstack/src/eventloop.rs
+++ b/bin/recovery_netstack/src/eventloop.rs
@@ -95,7 +95,7 @@
let status = await!(ctx.dispatcher().eth_client.get_status())?;
println!("ethernet status: {:?}", status);
}
- eth::Event::Receive(rx) => {
+ eth::Event::Receive(rx, _flags) => {
let len = rx.read(&mut buf);
receive_frame(&mut event_loop.ctx.lock().unwrap(), eth_id, &mut buf[..len]);
}
diff --git a/bin/wlan/wlan-hw-sim/BUILD.gn b/bin/wlan/wlan-hw-sim/BUILD.gn
index 0ba1b0f..a3e8652 100644
--- a/bin/wlan/wlan-hw-sim/BUILD.gn
+++ b/bin/wlan/wlan-hw-sim/BUILD.gn
@@ -13,6 +13,7 @@
deps = [
"//garnet/lib/rust/ethernet",
+ "//garnet/lib/rust/fidl_zircon_ethernet_ext",
"//garnet/lib/rust/wlantap-client",
"//garnet/lib/wlan/fidl:fidl-rustc",
"//garnet/lib/wlan/fidl:wlantap-rustc",
diff --git a/bin/wlan/wlan-hw-sim/src/main.rs b/bin/wlan/wlan-hw-sim/src/main.rs
index f00d01b..be30d5e 100644
--- a/bin/wlan/wlan-hw-sim/src/main.rs
+++ b/bin/wlan/wlan-hw-sim/src/main.rs
@@ -342,7 +342,7 @@
use super::*;
use {
fidl_fuchsia_wlan_service as fidl_wlan_service,
- failure::format_err,
+ failure::{ensure, format_err},
fuchsia_app as app,
fuchsia_zircon as zx,
futures::{channel::mpsc, poll, select},
@@ -805,6 +805,7 @@
async fn send_and_receive<'a>(client: &'a mut ethernet::Client, buf: &'a Vec<u8>)
-> Result<(eth_frames::EthHeader, Vec<u8>), failure::Error> {
+ use fidl_zircon_ethernet_ext::EthernetQueueFlags;
let mut client_stream = client.get_stream();
client.send(&buf);
loop {
@@ -814,7 +815,8 @@
ethernet::Event::StatusChanged => {
await!(client.get_status()).expect("getting status");
},
- ethernet::Event::Receive(buffer) => {
+ ethernet::Event::Receive(buffer, flags) => {
+ ensure!(flags.intersects(EthernetQueueFlags::RX_OK), "RX_OK not set");
let mut eth_frame = vec![0u8; buffer.len()];
buffer.read(&mut eth_frame);
let mut cursor = io::Cursor::new(ð_frame);
diff --git a/examples/rust/eth-rs/BUILD.gn b/examples/rust/eth-rs/BUILD.gn
index 88d2df4..6c6c6e3 100644
--- a/examples/rust/eth-rs/BUILD.gn
+++ b/examples/rust/eth-rs/BUILD.gn
@@ -9,6 +9,7 @@
name = "eth_rs"
edition = "2018"
deps = [
+ "//garnet/lib/rust/fidl_zircon_ethernet_ext",
"//garnet/lib/rust/ethernet",
"//garnet/public/rust/fuchsia-async",
"//garnet/public/rust/fuchsia-zircon",
diff --git a/examples/rust/eth-rs/src/main.rs b/examples/rust/eth-rs/src/main.rs
index 3ca62f0..33e8662 100644
--- a/examples/rust/eth-rs/src/main.rs
+++ b/examples/rust/eth-rs/src/main.rs
@@ -5,6 +5,7 @@
#![feature(async_await, await_macro)]
use failure::{Error, ResultExt};
+use fidl_zircon_ethernet_ext::EthernetQueueFlags;
use fuchsia_async as fasync;
use fuchsia_zircon as zx;
use futures::prelude::*;
@@ -36,10 +37,12 @@
let mut events = client.get_stream();
while let Some(evt) = await!(events.try_next())? {
- if let ethernet::Event::Receive(rx) = evt {
+ if let ethernet::Event::Receive(rx, flags) = evt {
let mut buf = [0; 64];
let r = rx.read(&mut buf);
- println!("first {} bytes: {:02x?}", r, &buf[0..r]);
+ let is_tx_echo = flags.intersects(EthernetQueueFlags::TX_ECHO);
+ println!("{} first {} bytes:\n{:02x?}", if is_tx_echo {"TX_ECHO"} else {"RX "},
+ r, &buf[0..r]);
}
}
Ok(())
diff --git a/lib/rust/ethernet/src/lib.rs b/lib/rust/ethernet/src/lib.rs
index dd7eaaf..8a79ac7 100644
--- a/lib/rust/ethernet/src/lib.rs
+++ b/lib/rust/ethernet/src/lib.rs
@@ -171,7 +171,8 @@
}
/// Poll the Ethernet client to receive a packet from the Ethernet device.
- pub fn poll_complete_rx(&self, cx: &LocalWaker) -> Poll<Result<buffer::RxBuffer, zx::Status>> {
+ pub fn poll_complete_rx(&self, cx: &LocalWaker)
+ -> Poll<Result<(buffer::RxBuffer, EthernetQueueFlags), zx::Status>> {
self.inner.poll_complete_rx(cx)
}
}
@@ -191,7 +192,7 @@
/// The `get_status` method may be used to retrieve the current status.
StatusChanged,
/// A RxBuffer was received from the Ethernet device.
- Receive(buffer::RxBuffer),
+ Receive(buffer::RxBuffer, EthernetQueueFlags),
}
impl Stream for EventStream {
@@ -229,8 +230,8 @@
progress = true;
}
- if let Poll::Ready(buf) = self.inner.poll_complete_rx(lw)? {
- return Poll::Ready(Ok(Event::Receive(buf)));
+ if let Poll::Ready((buf, flags)) = self.inner.poll_complete_rx(lw)? {
+ return Poll::Ready(Ok(Event::Receive(buf, flags)));
}
if !progress {
@@ -338,12 +339,13 @@
}
/// Receive a buffer from the Ethernet device representing a packet from the network.
- fn poll_complete_rx(&self, lw: &LocalWaker) -> Poll<Result<buffer::RxBuffer, zx::Status>> {
+ fn poll_complete_rx(&self, lw: &LocalWaker)
+ -> Poll<Result<(buffer::RxBuffer, EthernetQueueFlags), zx::Status>> {
Poll::Ready(match try_ready!(self.rx_fifo.try_read(lw)) {
Some(entry) => {
let mut pool_guard = self.pool.lock().unwrap();
let buf = pool_guard.map_rx_buffer(entry.offset as usize, entry.length as usize);
- Ok(buf)
+ Ok((buf, EthernetQueueFlags::from_bits_truncate(entry.flags)))
}
None => Err(zx::Status::PEER_CLOSED),
})