Crate catnip

source ·
Expand description

A no-std, panic-never, heapless, minimally-featured UDP/IP stack for bare-metal. Intended for fixed-time data acquisition and controls on LAN.

This crate currently relies on the nightly channel, and as a result, may break regularly until the required features stabilize.

Makes use of const generic expressions to provide flexibility in, and guaranteed correctness of, lengths of headers and data segments without an allocator.

This library is under active development; major functionality is yet to be implemented and I’m sure some bugs are yet to be found.

use catnip::*;

// Some made-up data with two 32-bit words' worth of bytes and some arbitrary addresses
let data: ByteArray<8> = ByteArray([0, 1, 2, 3, 4, 5, 6, 7]);

// Build frame
let mut frame = EthernetFrame::<IpV4Frame<UdpFrame<ByteArray<8>>>> {
    header: EthernetHeader {
        dst_macaddr: MacAddr::BROADCAST,
        src_macaddr: MacAddr::new([0x02, 0xAF, 0xFF, 0x1A, 0xE5, 0x3C]),
        ethertype: EtherType::IpV4,
    data: IpV4Frame::<UdpFrame<ByteArray<8>>> {
        header: IpV4Header {
            version_and_header_length: VersionAndHeaderLength::new().with_version(4).with_header_length((IpV4Header::BYTE_LEN / 4) as u8),
            dscp: DSCP::Standard,
            total_length: IpV4Frame::<UdpFrame<ByteArray<8>>>::BYTE_LEN as u16,
            identification: 0,
            fragmentation: Fragmentation::default(),
            time_to_live: 10,
            protocol: Protocol::Udp,
            checksum: 0,
            src_ipaddr: IpV4Addr::new([10, 0, 0, 120]),
            dst_ipaddr: IpV4Addr::new([10, 0, 0, 121]),
        data: UdpFrame::<ByteArray<8>> {
            header: UdpHeader {
                src_port: 8123,
                dst_port: 8125,
                length: UdpFrame::<ByteArray<8>>::BYTE_LEN as u16,
                checksum: 0,
            data: data,
    checksum: 0_u32,

// Calculate IP and UDP checksums = calc_udp_checksum(&; = calc_ip_checksum(&;

// Reduce to bytes
let bytes = frame.to_be_bytes();

// Parse from bytes
let frame_parsed = EthernetFrame::<IpV4Frame<UdpFrame<ByteArray<8>>>>::read_bytes(&bytes);
assert_eq!(frame_parsed, frame);




  • Derive To/From with an added “Unknown” variant catch-all for converting from numerical values that do not match a valid variant in order to avoid either panicking or cumbersome error handling.


  • Newtype for [u8; N] in order to be able to implement traits.



  • A data structure that can be packed into or unpacked from raw bytes.
  • A type that can be packed into or unpacked from fixed-size bytes, but the method is unknown yet.
  • Just like core::fmt::Debug
  • Just like core::fmt::Display
  • A collection of methods that are required / used to format a message into a stream.


Type Definitions

  • IPV4 address as bytes
  • Standard 6-byte MAC address. Split 24/24 format, Block ID | Device ID . Locally-administered addresses are [0x02, …], [0x06, …], [0x0A, …], [0x0E, …]

Derive Macros