Skip to content

Commit 57262b5

Browse files
DavidCozensclaude
andcommitted
feat: identify the device with an origin SD-ELEMENT
SolidSyslogOriginSd (RFC 5424 section 7.2) carrying software, swVersion and enterpriseId. The ip PARAM is left out: the address the collector sees is the one that reached it. Flash +11,972 B (+396 on the previous stage) RAM +7,136 B (+44) Log stack +448 B (unchanged) Service +736 B (unchanged) It lands after the store rather than before it. While a record went straight out, "who sent this" was implied by the connection it arrived on; once records can replay hours later that stops being true, and the record has to say so itself. enterpriseId 32473 is the number reserved for documentation by RFC 5612. A device shipping for real registers its own with IANA. It is defined in app/syslog/SyslogEnterprise.h rather than beside the element that carries it, because the number identifies the vendor and not the logger — anything else this product puts its own name on wants the same one, and one definition cannot drift from itself. The record is now 245 bytes, against the 256-byte cap this device set when its records were shorter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 8931a1e commit 57262b5

6 files changed

Lines changed: 65 additions & 24 deletions

File tree

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ It builds on a baseline that simulates the sort of device you might be adding th
1010
measures itself: see [docs/baseline.md](docs/baseline.md) for what the baseline is, how the
1111
figures are made, and how to run it.
1212

13-
## This stage — File store
13+
## This stage — Origin
1414

15-
Records spool to a block store on the volume the device already mounts — four blocks, one file
16-
each — instead of being held only in memory. The service task drains the ring into the store and
17-
sends from there, so a failed send costs a retry rather than the record. The CRC-16 written with
18-
each record catches corruption at rest, not tampering.
15+
The record carries an `origin` SD-ELEMENT naming the software, its version and the vendor's IANA
16+
enterprise number, so it identifies its sender instead of leaving the collector to infer that from
17+
the source address — which matters once the store replays records hours after the event. The `ip`
18+
PARAM is left out: the address the collector sees is still the one that reached it.
1919

2020
<!-- STAGE-COST:START (generated by scripts/gen-cost-table.py — do not edit by hand) -->
2121

22-
**Cost above baseline: Flash +11,576 B, RAM +7,092 B.**
22+
**Cost above baseline: Flash +11,972 B, RAM +7,136 B.**
2323

2424
<!-- STAGE-COST:END -->
2525

@@ -44,6 +44,7 @@ committed as [`run-report.md`](run-report.md), and rewritten by every stage.
4444
| TCP | records the network retransmits instead of dropping, and a send that fails when the collector is gone | +7,320 | +5,856 |
4545
| Time quality | a timestamp the collector knows how far to trust, and an uptime that tells a reboot from a counter wrap | +7,612 | +5,880 |
4646
| File store | records that survive a failed send, spooled to disk with a checksum at rest | +11,576 | +7,092 |
47+
| Origin | the device named in the record itself, not inferred from the source address | +11,972 | +7,136 |
4748

4849
*Deltas are bytes above the baseline, which is itself Flash 350,308 B, RAM 111,192 B.*
4950

app/syslog/Syslog.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
#include "SolidSyslogLwipRawResolver.h"
2525
#include "SolidSyslogLwipRawTcpStream.h"
2626
#include "SolidSyslogMetaSd.h"
27+
#include "SolidSyslogOriginSd.h"
2728
#include "SolidSyslogStdAtomicCounter.h"
2829
#include "SolidSyslogStreamSender.h"
2930
#include "SolidSyslogTimeQuality.h"
3031
#include "SolidSyslogTimeQualitySd.h"
32+
#include "SyslogEnterprise.h"
3133
#include "SyslogFields.h"
3234

3335
#include "lwip/tcpip.h"
@@ -53,11 +55,14 @@
5355
#define SYSLOG_STORE_PREFIX "syslog"
5456
#define SYSLOG_STORE_BLOCKS 4U
5557

58+
#define SYSLOG_SOFTWARE "solid-syslog-example"
59+
#define SYSLOG_SW_VERSION "0.1.0"
60+
5661
static struct SolidSyslog* s_logger = NULL;
5762
static uint8_t s_ring[SOLIDSYSLOG_CIRCULAR_BUFFER_RING_BYTES(SYSLOG_BUFFER_RECORDS)];
5863

5964
/* The logger reads these on every record, so they outlive Syslog_Start. */
60-
static struct SolidSyslogStructuredData* s_sd[2];
65+
static struct SolidSyslogStructuredData* s_sd[3];
6166

6267
/* One reading at boot, then free-running on the tick — enough to stamp a record,
6368
* not synchronisation. */
@@ -122,6 +127,15 @@ void Syslog_Start(void)
122127
s_sd[0] = SolidSyslogMetaSd_Create(&metaConfig);
123128
s_sd[1] = SolidSyslogTimeQualitySd_Create(SyslogTimeQuality);
124129

130+
/* No ip: the address the collector sees is the one that reached it, until a
131+
* relay makes that untrue. */
132+
struct SolidSyslogOriginSdConfig originConfig = {
133+
.Software = SYSLOG_SOFTWARE,
134+
.SwVersion = SYSLOG_SW_VERSION,
135+
.EnterpriseId = SYSLOG_ENTERPRISE_ID,
136+
};
137+
s_sd[2] = SolidSyslogOriginSd_Create(&originConfig);
138+
125139
/* Oldest discarded when the ceiling is reached: a device that cannot reach its
126140
* collector should keep the newest evidence, not stop logging. */
127141
struct SolidSyslogBlockStoreConfig storeConfig = {

app/syslog/SyslogEnterprise.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* This product's IANA Private Enterprise Number. It identifies the vendor, not
2+
* the logger, so it lives on its own rather than beside any one element that
3+
* carries it.
4+
*
5+
* 32473 is reserved for documentation (RFC 5612). Register your own at
6+
* https://www.iana.org/assignments/enterprise-numbers/ */
7+
#ifndef APP_SYSLOG_ENTERPRISE_H
8+
#define APP_SYSLOG_ENTERPRISE_H
9+
10+
#define SYSLOG_ENTERPRISE_ID "32473"
11+
12+
#endif /* APP_SYSLOG_ENTERPRISE_H */

measurements/origin.csv

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# origin figures (bytes) — captured by scripts/run.sh (CAPTURE=1).
2+
# The device reads measurements/Baseline.csv as its frozen baseline and reports current-minus-Baseline.
3+
flash_text,361640
4+
flash_data,640
5+
static_bss,117688
6+
heap_used,4440
7+
mbedtls_peak,21336
8+
mbedtls_free,11432
9+
lwip_mem_free,7576
10+
lwip_pbufs_free,13
11+
stack_log,568
12+
stack_service,788
13+
stack_harness,2848

measurements/stages.tsv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ buffered Buffered logging that returns immediately, with the send moved off the
2121
tcp TCP records the network retransmits instead of dropping, and a send that fails when the collector is gone
2222
time-quality Time quality a timestamp the collector knows how far to trust, and an uptime that tells a reboot from a counter wrap
2323
file-store File store records that survive a failed send, spooled to disk with a checksum at rest
24+
origin Origin the device named in the record itself, not inferred from the source address

run-report.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# solid-syslog-example — run (file-store)
1+
# solid-syslog-example — run (origin)
22

33
## Device (self-measured)
44

@@ -10,14 +10,14 @@
1010
[device] first record logged: yes
1111
[report] --- SolidSyslog cost above baseline (simulated existing application) ---
1212
[report] key,current,baseline,used_above_baseline
13-
[report] flash_text,361252,349992,11260
14-
[report] flash_data,632,316,316
15-
[report] static_bss,117652,110876,6776
13+
[report] flash_text,361640,349992,11648
14+
[report] flash_data,640,316,324
15+
[report] static_bss,117688,110876,6812
1616
[report] heap_used,4440,4440,0
17-
[report] mbedtls_peak,21276,21332,-56
18-
[report] mbedtls_free,11492,11436,56
17+
[report] mbedtls_peak,21336,21332,4
18+
[report] mbedtls_free,11432,11436,-4
1919
[report] lwip_mem_free,7576,7576,0
20-
[report] lwip_pbufs_free,14,14,0
20+
[report] lwip_pbufs_free,13,14,-1
2121
[report] stack_log,568,120,448
2222
[report] stack_service,788,52,736
2323
[report] stack_harness,2848,2840,8
@@ -29,7 +29,7 @@
2929

3030
```text
3131
text data bss dec hex filename
32-
361244 640 117652 479536 75130 /w/build/baseline-cross/baseline.elf
32+
361632 648 117688 479968 752e0 /w/build/baseline-cross/baseline.elf
3333
```
3434

3535
## Listeners (proved before the device ran)
@@ -47,21 +47,21 @@
4747
## Collector (syslog-ng) received
4848

4949
```text
50-
wire <134>1 2026-07-29T08:06:15.410000Z 10.0.2.15 solid-syslog-example - BOOT [meta sequenceId="1" sysUpTime="241"][timeQuality tzKnown="1" isSynced="0"] device started
51-
parsed PRIORITY=134 TIMESTAMP=2026-07-29T08:06:15+00:00 HOSTNAME=10.0.2.15 APP_NAME=solid-syslog-example PROCID= MSGID=BOOT STRUCTURED_DATA=[meta sequenceId="1" sysUpTime="241"][timeQuality tzKnown="1" isSynced="0"] MSG=device started
50+
wire <134>1 2026-07-29T08:21:38.360000Z 10.0.2.15 solid-syslog-example - BOOT [meta sequenceId="1" sysUpTime="236"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] device started
51+
parsed PRIORITY=134 TIMESTAMP=2026-07-29T08:21:38+00:00 HOSTNAME=10.0.2.15 APP_NAME=solid-syslog-example PROCID= MSGID=BOOT STRUCTURED_DATA=[meta sequenceId="1" sysUpTime="236"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] MSG=device started
5252
```
5353

54-
## Self-check (vs measurements/file-store.csv)
54+
## Self-check (vs measurements/origin.csv)
5555

5656
```text
57-
OK flash_text: 361252 (expected 361252, Δ0)
58-
OK flash_data: 632 (expected 632, Δ0)
59-
OK static_bss: 117652 (expected 117652, Δ0)
57+
OK flash_text: 361640 (expected 361640, Δ0)
58+
OK flash_data: 640 (expected 640, Δ0)
59+
OK static_bss: 117688 (expected 117688, Δ0)
6060
OK heap_used: 4440 (expected 4440, Δ0)
61-
OK mbedtls_peak: 21276 (expected 21276, Δ0)
62-
OK mbedtls_free: 11492 (expected 11492, Δ0)
61+
OK mbedtls_peak: 21336 (expected 21336, Δ0)
62+
OK mbedtls_free: 11432 (expected 11432, Δ0)
6363
OK lwip_mem_free: 7576 (expected 7576, Δ0)
64-
OK lwip_pbufs_free: 14 (expected 14, Δ0)
64+
OK lwip_pbufs_free: 13 (expected 13, Δ0)
6565
OK stack_log: 568 (expected 568, Δ0)
6666
OK stack_service: 788 (expected 788, Δ0)
6767
OK stack_harness: 2848 (expected 2848, Δ0)

0 commit comments

Comments
 (0)