Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions applications/awkernel_shell/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ edition = "2021"
blisp = "0.4"
log = "0.4"
byteorder = { version = "1.0", default-features = false }
num-bigint = { version = "0.4", default-features = false }
Comment thread
ytakano marked this conversation as resolved.
num-traits = { version = "0.2", default-features = false }

[dependencies.awkernel_async_lib]
path = "../../awkernel_async_lib"
Expand Down
19 changes: 19 additions & 0 deletions applications/awkernel_shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use awkernel_async_lib::{
use awkernel_lib::{console, sync::mutex::MCSNode, IS_STD};
use blisp::{embedded, runtime::FFI};
use core::time::Duration;
use num_bigint::BigInt;
use num_traits::ToPrimitive;

const SERVICE_NAME: &str = "[Awkernel] shell";

Expand Down Expand Up @@ -48,6 +50,7 @@ async fn console_handler() -> TaskResult {
Box::new(TaskFfi),
Box::new(InterruptFfi),
Box::new(IfconfigFfi),
Box::new(NetdumpFfi),
Box::new(RebootFfi),
Box::new(ShutdownFfi),
];
Expand Down Expand Up @@ -169,6 +172,9 @@ const CODE: &str = "(export factorial (n) (Pure (-> (Int) Int))
(export ifconfig () (IO (-> () []))
(ifconfig_ffi))

(export netdump (interface_id) (IO (-> (Int) []))
(netdump_ffi interface_id))

(export reboot () (IO (-> () []))
(reboot_ffi))

Expand All @@ -192,6 +198,7 @@ fn help_ffi() {
lines.push_str("(task) ; print tasks\r\n");
lines.push_str("(interrupt) ; print interrupt information\r\n");
lines.push_str("(ifconfig) ; print network interfaces\r\n");
lines.push_str("(netdump if); dump device registers\r\n");
lines.push_str("(reboot) ; reboot x86_64 systems\r\n");
lines.push_str("(shutdown) ; power off x86_64 systems\r\n");

Expand Down Expand Up @@ -247,6 +254,18 @@ fn ifconfig_ffi() {
}
}

#[embedded]
fn netdump_ffi(interface_id: BigInt) {
let Some(interface_id) = interface_id.to_u64() else {
console::print("netdump failed: interface_id must fit in u64\r\n");
return;
};

if let Err(e) = awkernel_lib::net::debug_dump_interface(interface_id) {
console::print(&format!("netdump failed: {e}\r\n"));
}
}

#[embedded]
fn reboot_ffi() {
#[cfg(all(target_arch = "x86_64", target_os = "none"))]
Expand Down
9 changes: 7 additions & 2 deletions awkernel_drivers/src/pcie/intel/igc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@ impl NetDevice for Igc {
.or(Err(net_device::NetDevError::DeviceError))
}

fn debug_dump(&self) {
let msg = self.inner.read().dump();
log::debug!("igc: dump:\r\n{msg}");
}

fn add_multicast_addr(&self, addr: &[u8; 6]) -> Result<(), net_device::NetDevError> {
let mut inner = self.inner.write();
inner.multicast_addrs.add_addr(*addr);
Expand Down Expand Up @@ -702,7 +707,7 @@ impl IgcInner {
}
}

fn dump(&self) {
fn dump(&self) -> alloc::string::String {
let mut msg = alloc::string::String::new();

msg = format!("BDF: {}\r\n", self.info.get_bdf());
Expand Down Expand Up @@ -802,7 +807,7 @@ impl IgcInner {
msg = format!("{msg}TDBAL{i}: {tdbal:#08x}\r\n");
}

log::debug!("igc: dump:\r\n{msg}");
msg
}

#[inline(always)]
Expand Down
22 changes: 22 additions & 0 deletions awkernel_lib/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,28 @@ pub fn get_interface(interface_id: u64) -> Result<IfStatus, NetManagerError> {
Ok(if_status)
}

/// Emit debug state for the interface identified by `interface_id` via `log::debug!`.
///
/// Returns [`NetManagerError::InvalidInterfaceID`] if no interface with that ID exists.
/// The NET_MANAGER read lock is held only to look up and clone the device reference;
/// the device dump runs outside that lock.
pub fn debug_dump_interface(interface_id: u64) -> Result<(), NetManagerError> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new public API has no doc comment, while other pub fns in this module (get_interface, up, down, tick_interface, ...) document behavior and error conditions. A caller cannot tell where the dump is emitted (the IGC implementation uses log::debug!, but that is not part of the contract), what error variants can be returned, or whether it is safe to invoke during active TX/RX.

Please add a /// comment specifying the output channel, the returned errors (today only InvalidInterfaceID), and any timing constraints.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a doc comment as follows.

/// Emit debug state for the interface identified by `interface_id` via `log::debug!`.
///
/// Returns [`NetManagerError::InvalidInterfaceID`] if no interface with that ID exists.
/// The NET_MANAGER read lock is held only to look up and clone the device reference;
/// the device dump runs outside that lock.

let net_device = {
let net_manager = NET_MANAGER.read();

let if_net = net_manager
.interfaces
.get(&interface_id)
.ok_or(NetManagerError::InvalidInterfaceID)?;

if_net.net_device.clone()
};

net_device.debug_dump();

Ok(())
}

pub fn get_all_interface() -> Vec<IfStatus> {
let net_manager = NET_MANAGER.read();

Expand Down
5 changes: 5 additions & 0 deletions awkernel_lib/src/net/net_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ pub trait NetDevice {
Ok(())
}

/// Dump device-specific debug state on demand.
fn debug_dump(&self) {
log::warn!("debug_dump not implemented for this device");
}

fn add_multicast_addr(&self, addr: &[u8; 6]) -> Result<(), NetDevError>;
fn remove_multicast_addr(&self, addr: &[u8; 6]) -> Result<(), NetDevError>;
}
Expand Down
Loading