Skip to main content

CCSDS Ethernet client

This project provides typed, in-process command exchange with a directly attached CCSDS Ethernet endpoint. The Rust crate owns the full typed session contract. The optional Python package exposes strict configuration, byte-level frame helpers, and the Linux raw transport for test orchestrators. It has no daemon, service, RPC API, sender CLI, plugin system, recording layer, automatic retry, or UDP/raw fallback.

It is available under the MIT License.

Contract

RawEthernetConfig and its endpoints are immutable after strict construction. The config requires schema version 2, caller-supplied concrete unicast IPv4 or IPv6 endpoints, nonzero UDP ports, unicast nonzero MAC addresses, matching IP address families, distinct host/board identity, a valid Linux interface name, and a nonzero packet-ring capacity. The crate never infers, discovers, selects, rewrites, or learns peer addresses.

A mission crate implements Codec with its own typed Command, Acknowledgement, Telemetry, and opaque Correlation. Session::open (Linux) or Session::from_transport starts receive before any command can be sent. exchange_once accepts an absolute monotonic deadline and performs one send only. An already-expired deadline is DeadlineExpiredBeforeSend; a receive failure after send is DeliveryOutcomeUnknown. Matching busy or rejected acknowledgements remain successful typed decode results for the codec/caller to interpret. next_telemetry returns telemetry observed while an exchange waited for its matching acknowledgement. close is idempotent.

The Linux transport is cfg-gated and uses an interface-bound AF_PACKET raw socket. Live use requires Linux and CAP_NET_RAW; granting that capability and selecting an interface are deployment responsibilities. Frame/config/ring/ session tests use MemoryTransport; default checks never open a NIC or require root.

Rust example

Run the hardware-free example to send one typed command through Session, receive a correlated acknowledgement, and read telemetry that reports an incremented command counter:

cargo run --example dummy_ccsds
command packet:   11 20 c0 29 00 02 01 00 29
telemetry packet: 01 21 c0 00 00 02 02 00 2a
ack packet:       01 22 c0 00 00 02 03 00 29
acknowledged command counter: 41
telemetry command counter:    42

These are complete Space Packets that follow CCSDS 133.0-B-2, with the mandatory six-octet primary header. The example uses version 0, no secondary header, and unsegmented packets. APID 0x120 carries the dummy telecommand. APID 0x121 carries the dummy telemetry, and APID 0x122 carries the dummy acknowledgement. The packet data length is 0x0002, which means three data octets because CCSDS encodes this field as the number of data octets minus one.

The application data is intentionally small and mission-specific:

command data:   01 00 29  # increment command, counter 41
telemetry data: 02 00 2a  # counter report, counter 42

The application-level command counter is not the primary-header packet sequence count. The command uses sequence count 41 for illustration. The telemetry APID has its own sequence count, starting at zero.

The example implements Codec in the consuming program and uses MemoryTransport to supply dummy board packets:

let transport = MemoryTransport::with_incoming([
    incoming_frame(telemetry_packet, board),
    incoming_frame(acknowledgement_packet, board),
]);
let mut session = Session::from_transport(DummyCodec, transport, board)?;

let deadline = Instant::now() + Duration::from_secs(1);
let acknowledgement = session.exchange_once(&command, deadline)?;
let telemetry = session.next_telemetry(deadline)?;

See examples/dummy_ccsds.rs for the complete packet encoder, decoder, typed codec, exchange, and exact-byte tests. The APIDs and application data are examples only; a consuming mission crate owns those definitions.

Python package

Install ccsds-ethernet-client from PyPI on Python 3.11 or newer. Published wheels target Linux x86-64 and AArch64. The source distribution supports other Linux targets with a Rust toolchain. Frame helpers also build on other platforms, but RawEthernetClient rejects live use outside Linux.

from ccsds_ethernet_client import RawEthernetClient, RawEthernetConfig

config = RawEthernetConfig(
    interface_name="eth0",
    host_mac="02:00:00:00:00:01",
    host_ip="169.254.209.1",
    host_udp_port=49152,
    board_mac="02:00:00:00:00:7a",
    board_ip="169.254.209.0",
    board_udp_port=24576,
    ring_capacity=64,
)

with RawEthernetClient(config) as client:
    client.send(b"\x10\x01")
    datagram = client.receive(timeout_seconds=0.5)
    print(datagram.payload, datagram.sender_ip)

receive raises TimeoutError when its relative monotonic timeout expires. Configuration failures raise ConfigError. Frame construction and parsing failures raise FrameError. Both are ValueError subclasses. Other live transport failures raise TransportError. The package does not encode commands, correlate acknowledgements, retry, or interpret telemetry. The test orchestrator owns those policies.

TransportStatistics reports transport observations only. Detailed frame classification counters describe what the receive path observed; they do not decide whether a consumer should accept, reject, persist, or invalidate an exchange, recording, test run, or safety case. Unsupported EtherTypes continue to contribute to ignored_non_ipv4_frames and also receive a factual detailed counter. Endpoint mismatches contribute to foreign_frames. Parse and integrity failures contribute to invalid_frames and, when the reason is recognized, the matching detailed failure counter.

Ignored frame payload bytes are not retained. Consumers own serialization, recording schemas, mission interpretation, and safety policy.

For concurrent Python orchestration, ThreadedRawEthernetClient(config) owns the native client on a single thread. It provides send, receive, statistics, cancel_receive, and close. Use a context manager to join the owner thread. Receive and send queues are bounded; dropped_datagrams reports receive overflow. It does not interpret packets or retry sends. The original RawEthernetClient requires serialized access. See recovery contracts for request identity, checksum policy, diagnostics, and recovery semantics.

Checks

just check

Use just python-test to run only the extension build and hardware-free Python contract tests.

Use just linux-test for isolated Linux packet-socket tests. See performance evidence for the virtual-link baseline and the measurements required before throughput optimizations.

Use just benchmark for configurable root-free workloads, or just linux-benchmark for the packet transport in a disposable veth fixture. Both emit JSON Lines. See the benchmark contract for traffic, fault injection, measurement scope, and later peer-adapter requirements.

Maintenance

Future agent and maintainer workflow guidance lives in docs/agent-operating-loop.md. Use it to keep changes aligned with the crate's transport-only boundary and executable test contracts.

Scope boundary

Mission APIDs, secondary headers, request-ID allocation, acknowledgement status policy, retries, recording schemas, logic, decisions, intent, and safety policy belong to consuming systems.

This crate defines transport and exchange mechanics only; it does not define subsystem intent or safety policy. Generic file recording is not part of this crate. Schema version 2 uses a standard 1500-byte Ethernet MTU. IPv4 UDP payloads are limited to 1472 bytes (1500 minus the 20-byte IPv4 and 8-byte UDP headers). IPv6 UDP payloads are limited to 1452 bytes (1500 minus the 40-byte IPv6 and 8-byte UDP headers). Use RawEthernetConfig::maximum_udp_payload_bytes() for the configured family.

See docs/release.md for the local release process. See docs/agent-operating-loop.md for the agent-facing transport boundary.

Metadata

Release files for ccsds-ethernet-client 0.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ccsds-ethernet-client 0.3.3
File Size Uploaded
ccsds_ethernet_client-0.3.3.tar.gz 79.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for ccsds-ethernet-client 0.3.3
File Interpreter ABI Platform
ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details

Total release size: 710.6 kB

Release files / ccsds_ethernet_client-0.3.3.tar.gz

Download URL ccsds_ethernet_client-0.3.3.tar.gz
Size 79.8 kB
Tags Source
SHA-256 checksum
How to use checksums
344795bbac2714f9259a03e9fc85e1ac68740593ab4607f5163ac182ffd56395
BLAKE2b-256 checksum
How to use checksums
65d5579a8292bea6181d99a1111eebdb09e6e296805194be46430934c781cfeb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release files / ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_x86_64.whl
Size 317.4 kB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
94e59bcf61bd97f94a99bb7398302c3602a35ce6e3712a0bf7938cbfa1ee8a02
BLAKE2b-256 checksum
How to use checksums
2d7ce930aa835f23e9b6727497a02252367c53494bae1344c4c0c475457075b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release files / ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL ccsds_ethernet_client-0.3.3-cp311-abi3-manylinux_2_28_aarch64.whl
Size 313.4 kB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
7b4fc6883a94e6b0403997276ff59dbfad67a7f737f7e7f4e3a012236f2de50a
BLAKE2b-256 checksum
How to use checksums
502233add03721ae5649d4738ace452412abb52733c330868423470c7749aa52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.3 This release

3 release files

0.3.2

3 release files

0.3.1

3 release files

0.3.0

3 release files

0.2.2

3 release files

0.2.1

3 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page