Example mirage-eio unikernels
0

Configure Feed

Select the types of activity you want to include in your feed.

unikernels / bin / space / tm-downlink
1 folder 7 files
README.md

tm-downlink unikernel#

A CCSDS telemetry downlink receiver as a Solo5 unikernel: the ground station's ingest end. Transfer frames arrive on the RF link, and what comes out the other side is telemetry in a database.

tm-downlink unikernel demo

The whole stack is declared, not written:

Ccsds.Space_packet.packets      (* reassemble space packets (CCSDS 133.0-B) *)
  (Ccsds.Tm.link                (* decode TM transfer frames (CCSDS 132.0-B) *)
     (Net_device.frame "rf"))   (* one frame in, one frame out              *)

Reassembly is not decorative here. A space packet may share a transfer frame with other packets and may span two frames, so the frame carrying a packet's first byte is rarely the one that completes it. The packets device hands the body whole packets, in order; the idle packets a spacecraft pads a frame with (APID 2047) arrive like any other and are dropped.

Net_device.frame is the carrier every CCSDS link sits on: a channel where one receive is one whole frame, with no byte-stream framing of its own. Under a Solo5 tender that is the netif the tender binds, and transfer frames go out untouched.

On the host, a net device otherwise runs through the slirp gateway -- an Ethernet/IPv4 NAT bridge, which parses what it is given and drops a CCSDS transfer frame as malformed Ethernet. So the native backend binds a frame device to a UDP socket instead:

dune exec -- unikernel-tm-downlink --frame rf=LOCAL_PORT:REMOTE_PORT

One datagram is one frame. That is also how ground systems really move TM between elements, so it is not only a test affordance -- and it is what lets the same unikernel run on the host, under a cram test, against the spacecraft on the other end of the link.

Run on the host (native dev backend)#

dune exec -- unikernel-tm-downlink \
  --frame rf=5000:5001 --packets 3
dune exec -- unikernel-tm-downlink-spacecraft \
  --port 5000 --from 5001

The receiver stores its packets, closes the database and exits. What lands on the block device is an ordinary SQLite database, so the host reads the pass back with its own sqlite3:

notafs_extract disk tm.db tm.db
sqlite3 -header -box tm.db "SELECT apid, seq, value, bytes FROM telemetry;"

A pass is a load-then-close workload, so the database runs in journal_mode: Journal``: the new pages go straight into the database file and the journal is deleted, leaving a complete SQLite file on the block device the moment the pass ends.

Build and run under Solo5#

mrg up
mrg build -t solo5 unikernels/bin/space/tm-downlink
mrg run --disk disk.img unikernels/bin/space/tm-downlink

Under the tender the rf device is a real netif, and the frames on it are the spacecraft's.