Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add defmt logging support #455

Merged
merged 3 commits into from
Apr 1, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
features:
# These feature sets cannot run tests, so we only check they build.
- medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
- defmt medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async

steps:
- uses: actions/checkout@v2
Expand Down
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ byteorder = { version = "1.0", default-features = false }
log = { version = "0.4.4", default-features = false, optional = true }
libc = { version = "0.2.18", optional = true }
bitflags = { version = "1.0", default-features = false }
defmt = { version = "0.2.0", optional = true }

[dev-dependencies]
env_logger = "0.5"
Expand All @@ -46,6 +47,13 @@ verbose = []
"socket-tcp" = ["socket"]
"socket-icmp" = ["socket"]
"async" = []

defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []

Comment on lines +50 to +56
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, what's the point of these, are they needed by defmt?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the defmt macros only emit code if the corresponding log level (or lower) is enabled. The end-user is supposed to depend on smoltcp with defmt, defmt-debug features to see up to debug level, for example. This is so log level is configurable per-crate.

Copy link
Contributor

Choose a reason for hiding this comment

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

But don't you need to forward the features then? I'm confused about how this would work as-is in this PR.

default = [
"std", "log", # needed for `cargo test --no-default-features --features default` :/
"medium-ethernet", "medium-ip",
Expand Down
2 changes: 2 additions & 0 deletions examples/loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod mock {
use core::cell::Cell;

#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Clock(Cell<Instant>);

impl Clock {
Expand All @@ -46,6 +47,7 @@ mod mock {

// should be AtomicU64 but that's unstable
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Clock(Arc<AtomicUsize>);

impl Clock {
Expand Down
1 change: 1 addition & 0 deletions fuzz/fuzz_targets/tcp_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod mock {

// should be AtomicU64 but that's unstable
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Clock(Arc<AtomicUsize>);

impl Clock {
Expand Down
4 changes: 4 additions & 0 deletions src/dhcp/clientv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ const PARAMETER_REQUEST_LIST: &[u8] = &[

/// IPv4 configuration data returned by `client.poll()`
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Config {
pub address: Option<Ipv4Cidr>,
pub router: Option<Ipv4Address>,
pub dns_servers: [Option<Ipv4Address>; 3],
}

#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct RequestState {
retry: u16,
endpoint_ip: Ipv4Address,
Expand All @@ -37,12 +39,14 @@ struct RequestState {
}

#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct RenewState {
endpoint_ip: Ipv4Address,
server_identifier: Ipv4Address,
}

#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum ClientState {
/// Discovering the DHCP server
Discovering,
Expand Down
4 changes: 4 additions & 0 deletions src/iface/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ let iface = InterfaceBuilder::new(device)
}

#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg(feature = "medium-ethernet")]
enum EthernetPacket<'a> {
#[cfg(feature = "proto-ipv4")]
Expand All @@ -251,6 +252,7 @@ enum EthernetPacket<'a> {
}

#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub(crate) enum IpPacket<'a> {
#[cfg(feature = "proto-ipv4")]
Icmpv4((Ipv4Repr, Icmpv4Repr<'a>)),
Expand Down Expand Up @@ -591,6 +593,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
Medium::Ethernet => {
inner.process_ethernet(sockets, timestamp, &frame).map_err(|err| {
net_debug!("cannot process ingress packet: {}", err);
#[cfg(not(feature = "defmt"))]
net_debug!("packet dump follows:\n{}",
PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &frame));
err
Expand Down Expand Up @@ -1844,6 +1847,7 @@ mod test {
}

#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct MockTxToken;

impl TxToken for MockTxToken {
Expand Down
2 changes: 2 additions & 0 deletions src/iface/neighbor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ use crate::time::{Duration, Instant};
/// A neighbor mapping translates from a protocol address to a hardware address,
/// and contains the timestamp past which the mapping should be discarded.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Neighbor {
hardware_addr: EthernetAddress,
expires_at: Instant,
}

/// An answer to a neighbor cache lookup.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub(crate) enum Answer {
/// The neighbor address is in the cache and not expired.
Found(EthernetAddress),
Expand Down
1 change: 1 addition & 0 deletions src/iface/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::wire::{Ipv6Address, Ipv6Cidr};

/// A prefix of addresses that should be routed via a router
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Route {
pub via_router: IpAddress,
/// `None` means "forever".
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ compile_error!("You must enable at least one of the following features: proto-ip
))]
compile_error!("If you enable the socket feature, you must enable at least one of the following features: socket-raw, socket-udp, socket-tcp, socket-icmp");

#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You must enable at most one of the following features: defmt, log");

use core::fmt;

#[macro_use]
Expand All @@ -116,6 +119,7 @@ pub mod dhcp;
/// The error type for the networking stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
/// An operation cannot proceed because a buffer is empty or full.
Exhausted,
Expand Down
9 changes: 8 additions & 1 deletion src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ macro_rules! net_log {
(debug, $($arg:expr),*) => { log::debug!($($arg),*); };
}

#[cfg(not(feature = "log"))]
#[cfg(feature = "defmt")]
macro_rules! net_log {
(trace, $($arg:expr),*) => { defmt::trace!($($arg),*); };
(debug, $($arg:expr),*) => { defmt::debug!($($arg),*); };
}

#[cfg(not(any(feature = "log", feature = "defmt")))]
#[macro_use]
macro_rules! net_log {
($level:ident, $($arg:expr),*) => { $( let _ = $arg; )* }
Expand All @@ -30,6 +36,7 @@ macro_rules! enum_with_unknown {
}
) => {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
$( #[$enum_attr] )*
pub enum $name {
$(
Expand Down
2 changes: 2 additions & 0 deletions src/phy/fault_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn xorshift32(state: &mut u32) -> u32 {
const MTU: usize = 1536;

#[derive(Debug, Default, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct Config {
corrupt_pct: u8,
drop_pct: u8,
Expand All @@ -30,6 +31,7 @@ struct Config {
}

#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct State {
rng_seed: u32,
refilled_at: Instant,
Expand Down
1 change: 1 addition & 0 deletions src/phy/fuzz_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub trait Fuzzer {
/// smoltcp, and is not for production use.
#[allow(unused)]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
inner: D,
fuzz_tx: FTx,
Expand Down
4 changes: 4 additions & 0 deletions src/phy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub use self::tuntap_interface::TunTapInterface;

/// A description of checksum behavior for a particular protocol.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Checksum {
/// Verify checksum when receiving and compute checksum when sending.
Both,
Expand Down Expand Up @@ -156,6 +157,7 @@ impl Checksum {

/// A description of checksum behavior for every supported protocol.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct ChecksumCapabilities {
pub ipv4: Checksum,
Expand Down Expand Up @@ -188,6 +190,7 @@ impl ChecksumCapabilities {
/// Higher-level protocols may achieve higher throughput or lower latency if they consider
/// the bandwidth or packet size limitations.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct DeviceCapabilities {
/// Medium of the device.
Expand Down Expand Up @@ -229,6 +232,7 @@ pub struct DeviceCapabilities {

/// Type of medium of a device.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Medium {
/// Ethernet medium. Devices of this type send and receive Ethernet frames,
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
Expand Down
2 changes: 2 additions & 0 deletions src/phy/pcap_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ enum_with_unknown! {

/// Packet capture mode.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PcapMode {
/// Capture both received and transmitted packets.
Both,
Expand Down Expand Up @@ -118,6 +119,7 @@ impl<T: Write> PcapSink for RefCell<T> {
/// [libpcap]: https://wiki.wireshark.org/Development/LibpcapFileFormat
/// [sink]: trait.PcapSink.html
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PcapWriter<D, S>
where D: for<'a> Device<'a>,
S: PcapSink + Clone,
Expand Down
1 change: 1 addition & 0 deletions src/socket/icmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr};
///
/// [IcmpSocket::bind]: struct.IcmpSocket.html#method.bind
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Endpoint {
Unspecified,
Ident(u16),
Expand Down
2 changes: 2 additions & 0 deletions src/socket/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::time::{Duration, Instant};
/// This enum tracks whether the socket should be polled based on the neighbor it is
/// going to send packets to.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum NeighborState {
/// Socket can be polled immediately.
Active,
Expand All @@ -29,6 +30,7 @@ impl Default for NeighborState {
/// This includes things that only external (to the socket, that is) code
/// is interested in, but which are more conveniently stored inside the socket itself.
#[derive(Debug, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Meta {
/// Handle of this socket within its enclosing `SocketSet`.
/// Mainly useful for debug output.
Expand Down
1 change: 1 addition & 0 deletions src/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub(crate) use self::ref_::Session as SocketSession;

/// Gives an indication on the next time the socket should be polled.
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub(crate) enum PollAt {
/// The socket needs to be polled immidiately.
Now,
Expand Down
1 change: 1 addition & 0 deletions src/socket/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct Item<'a> {

/// A handle, identifying a socket in a set.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Handle(usize);

impl fmt::Display for Handle {
Expand Down
2 changes: 2 additions & 0 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub type SocketBuffer<'a> = RingBuffer<'a, u8>;
///
/// [RFC 793]: https://tools.ietf.org/html/rfc793
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum State {
Closed,
Listen,
Expand Down Expand Up @@ -147,6 +148,7 @@ impl RttEstimator {
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum Timer {
Idle {
keep_alive_at: Option<Instant>,
Expand Down
2 changes: 2 additions & 0 deletions src/storage/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub struct TooManyHolesError;

/// A contiguous chunk of absent data, followed by a contiguous chunk of present data.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct Contig {
hole_size: usize,
data_size: usize
Expand Down Expand Up @@ -80,6 +81,7 @@ const CONTIG_COUNT: usize = 4;
/// Currently, up to a hardcoded limit of 4 or 32 holes can be tracked in the buffer.
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq, Eq, Clone))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Assembler {
#[cfg(not(any(feature = "std", feature = "alloc")))]
contigs: [Contig; CONTIG_COUNT],
Expand Down
1 change: 1 addition & 0 deletions src/storage/packet_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::storage::RingBuffer;

/// Size and header of a packet.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PacketMetadata<H> {
size: usize,
header: Option<H>
Expand Down
2 changes: 2 additions & 0 deletions src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use core::{ops, fmt};
/// * A value less than `0` indicates a time before the starting
/// point.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Instant {
pub millis: i64,
}
Expand Down Expand Up @@ -135,6 +136,7 @@ impl ops::Sub<Instant> for Instant {

/// A relative amount of time.
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Duration {
pub millis: u64,
}
Expand Down
2 changes: 2 additions & 0 deletions src/wire/arp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum_with_unknown! {

/// A read/write wrapper around an Address Resolution Protocol packet buffer.
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Packet<T: AsRef<[u8]>> {
buffer: T
}
Expand Down Expand Up @@ -253,6 +254,7 @@ use crate::wire::{EthernetAddress, Ipv4Address};

/// A high-level representation of an Address Resolution Protocol packet.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Repr {
/// An Ethernet and IPv4 Address Resolution Protocol packet.
Expand Down
3 changes: 3 additions & 0 deletions src/wire/dhcpv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl MessageType {

/// A representation of a single DHCP option.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum DhcpOption<'a> {
EndOfList,
Pad,
Expand Down Expand Up @@ -200,6 +201,7 @@ impl<'a> DhcpOption<'a> {

/// A read/write wrapper around a Dynamic Host Configuration Protocol packet buffer.
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Packet<T: AsRef<[u8]>> {
buffer: T
}
Expand Down Expand Up @@ -624,6 +626,7 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
///
/// The `options` field has a variable length.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Repr<'a> {
/// This field is also known as `op` in the RFC. It indicates the type of DHCP message this
/// packet represents.
Expand Down
Loading