SpaceOS wire protocol codecs for host-guest communication
1open Wire
2
3let magic = 0x53504F53
4
5type t = {
6 magic : int;
7 format_version : int;
8 reserved : int;
9 tenant_id : int;
10 total_blocks : int;
11 dp_start : int;
12 dp_size : int;
13 epoch : int64;
14 uuid : string;
15 crc32 : int;
16}
17
18let codec =
19 let open Codec in
20 record "Superblock"
21 (fun
22 magic
23 format_version
24 reserved
25 tenant_id
26 total_blocks
27 dp_start
28 dp_size
29 epoch
30 uuid
31 crc32
32 ->
33 {
34 magic;
35 format_version;
36 reserved;
37 tenant_id;
38 total_blocks;
39 dp_start;
40 dp_size;
41 epoch;
42 uuid;
43 crc32;
44 })
45 |+ field "magic" uint32be (fun t -> t.magic)
46 |+ field "format_version" uint8 (fun t -> t.format_version)
47 |+ field "reserved" uint8 (fun t -> t.reserved)
48 |+ field "tenant_id" uint16be (fun t -> t.tenant_id)
49 |+ field "total_blocks" uint32be (fun t -> t.total_blocks)
50 |+ field "dp_start" uint32be (fun t -> t.dp_start)
51 |+ field "dp_size" uint32be (fun t -> t.dp_size)
52 |+ field "epoch" uint64be (fun t -> t.epoch)
53 |+ field "uuid" (byte_array ~size:(int 16)) (fun t -> t.uuid)
54 |+ field "crc32" uint32be (fun t -> t.crc32)
55 |> seal
56
57let crc32c data =
58 let v =
59 Checkseum.Crc32c.digest_string data 0 (String.length data)
60 Checkseum.Crc32c.default
61 in
62 Optint.to_unsigned_int v
63
64let compute_crc t =
65 (* CRC covers bytes 0-47 (everything before the CRC field) *)
66 let wire_size = Codec.wire_size codec in
67 let buf = Bytes.create wire_size in
68 Codec.encode codec t buf 0;
69 (* CRC covers first 48 bytes (wire_size - 4) *)
70 let crc_len = wire_size - 4 in
71 crc32c (Bytes.sub_string buf 0 crc_len)
72
73let v ~tenant_id ~total_blocks ~dp_start ~dp_size ~epoch ~uuid =
74 let t =
75 {
76 magic;
77 format_version = 0x01;
78 reserved = 0;
79 tenant_id;
80 total_blocks;
81 dp_start;
82 dp_size;
83 epoch;
84 uuid;
85 crc32 = 0;
86 }
87 in
88 { t with crc32 = compute_crc t }
89
90let check_magic t = t.magic = magic
91
92let check_crc t =
93 let expected = compute_crc { t with crc32 = 0 } in
94 t.crc32 = expected
95
96let pp ppf t =
97 Fmt.pf ppf
98 "@[<h>superblock(magic=0x%08x ver=%d tenant=%d blocks=%d dp=%d+%d \
99 crc=0x%08x)@]"
100 t.magic t.format_version t.tenant_id t.total_blocks t.dp_start t.dp_size
101 t.crc32
102
103let equal a b =
104 a.magic = b.magic
105 && a.format_version = b.format_version
106 && a.tenant_id = b.tenant_id
107 && a.total_blocks = b.total_blocks
108 && a.dp_start = b.dp_start && a.dp_size = b.dp_size
109 && Int64.equal a.epoch b.epoch
110 && String.equal a.uuid b.uuid && a.crc32 = b.crc32