summaryrefslogtreecommitdiff
path: root/cmake/config/lib/ssm.cmake
blob: aa9c4f75414a2fa296426da56eba7c140ae13052 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# Secure Shared Memory (SSM) pool configuration for Ouroboros This file defines the allocation
# parameters for the secure shared memory pool allocator

# Shared memory pool naming configuration
set(SSM_PREFIX "ouroboros" CACHE STRING
    "Prefix for secure shared memory pools")

# Pool naming (internal)
set(SSM_GSPP_NAME "/${SSM_PREFIX}.gspp" CACHE INTERNAL
    "Name for the Global Shared Packet Pool")
set(SSM_PUP_NAME_FMT "/${SSM_PREFIX}.pup.%d" CACHE INTERNAL
    "Format string for Per-User Pool names (uid as argument)")

# Packet buffer configuration
set(SSM_POOL_NAME "/${SHM_PREFIX}.pool" CACHE INTERNAL
    "Name for the main POSIX shared memory pool")
set(SSM_PK_BUFF_HEADSPACE 256 CACHE STRING
    "Bytes of headspace to reserve for future headers")
set(SSM_PK_BUFF_TAILSPACE 32 CACHE STRING
    "Bytes of tailspace to reserve for future tails")
set(SSM_RBUFF_SIZE 1024 CACHE STRING
    "Number of slots in a flow's rbuff ring; must be a power of 2")
set(SSM_RBUFF_TXQ_DELAY 10 CACHE STRING
    "Queueing delay a flow's tx ring may hold (ms); 0 is unlimited")
set(SSM_RBUFF_TXQ_PRIO_MUL 2 CACHE STRING
    "Retransmissions get this multiple of the tx occupancy limit")
set(SSM_RBUFF_TXQ_PRIO_DIV 16 CACHE STRING
    "Ring fraction (1/N) new data leaves to retransmissions")
set(SSM_RBUFF_PREFIX "/${SHM_PREFIX}.rbuff." CACHE INTERNAL
    "Prefix for rbuff POSIX shared memory filenames")
set(SSM_FLOW_SET_PREFIX "/${SHM_PREFIX}.set." CACHE INTERNAL
    "Prefix for the POSIX shared memory flow set")

# Number of shards per size class for reducing contention
set(SSM_POOL_SHARDS 4 CACHE STRING
    "Number of allocator shards per size class")
set(SSM_POOL_RECLAIM_AGE_S 60 CACHE STRING
    "Minimum age in seconds before a block is presumed stale and reclaimed")

# Global Shared Packet Pool (GSPP) - for privileged processes Shared by all processes in 'ouroboros'
# group (~60 MB total)
set(SSM_GSPP_256_BLOCKS 1024 CACHE STRING
    "GSPP: Number of 256B blocks")
set(SSM_GSPP_512_BLOCKS 2048 CACHE STRING
    "GSPP: Number of 512B blocks")
set(SSM_GSPP_1K_BLOCKS 512 CACHE STRING
    "GSPP: Number of 1KB blocks")
set(SSM_GSPP_2K_BLOCKS 384 CACHE STRING
    "GSPP: Number of 2KB blocks")
set(SSM_GSPP_4K_BLOCKS 256 CACHE STRING
    "GSPP: Number of 4KB blocks")
set(SSM_GSPP_16K_BLOCKS 128 CACHE STRING
    "GSPP: Number of 16KB blocks")
set(SSM_GSPP_64K_BLOCKS 64 CACHE STRING
    "GSPP: Number of 64KB blocks")
set(SSM_GSPP_256K_BLOCKS 32 CACHE STRING
    "GSPP: Number of 256KB blocks")
set(SSM_GSPP_1M_BLOCKS 16 CACHE STRING
    "GSPP: Number of 1MB blocks")

# Per-User Pool (PUP) - for unprivileged applications Each unprivileged app gets its own smaller
# pool (~7.5 MB total)
set(SSM_PUP_256_BLOCKS 512 CACHE STRING
    "PUP: Number of 256B blocks")
set(SSM_PUP_512_BLOCKS 512 CACHE STRING
    "PUP: Number of 512B blocks")
set(SSM_PUP_1K_BLOCKS 512 CACHE STRING
    "PUP: Number of 1KB blocks")
set(SSM_PUP_2K_BLOCKS 512 CACHE STRING
    "PUP: Number of 2KB blocks")
set(SSM_PUP_4K_BLOCKS 32 CACHE STRING
    "PUP: Number of 4KB blocks")
set(SSM_PUP_16K_BLOCKS 16 CACHE STRING
    "PUP: Number of 16KB blocks")
set(SSM_PUP_64K_BLOCKS 8 CACHE STRING
    "PUP: Number of 64KB blocks")
set(SSM_PUP_256K_BLOCKS 2 CACHE STRING
    "PUP: Number of 256KB blocks")
set(SSM_PUP_1M_BLOCKS 0 CACHE STRING
    "PUP: Number of 1MB blocks")

# Zero classes too small for spb header + HEADSPACE + TAILSPACE + 1 B.
math(EXPR _SSM_MIN_USEFUL_CLASS
    "32 + ${SSM_PK_BUFF_HEADSPACE} + ${SSM_PK_BUFF_TAILSPACE}")
foreach(_pair "256:256" "512:512" "1K:1024" "2K:2048")
    string(REPLACE ":" ";" _p "${_pair}")
    list(GET _p 0 _suffix)
    list(GET _p 1 _size)
    if(_size LESS _SSM_MIN_USEFUL_CLASS)
        set(SSM_GSPP_${_suffix}_BLOCKS 0)
        set(SSM_PUP_${_suffix}_BLOCKS 0)
    endif()
endforeach()
unset(_SSM_MIN_USEFUL_CLASS)
unset(_p)
unset(_suffix)
unset(_size)

# SSM pool size calculations
include(utils/HumanReadable)

math(EXPR SSM_GSPP_TOTAL_SIZE
    "(1 << 8) * ${SSM_GSPP_256_BLOCKS} + \
     (1 << 9) * ${SSM_GSPP_512_BLOCKS} + \
     (1 << 10) * ${SSM_GSPP_1K_BLOCKS} + \
     (1 << 11) * ${SSM_GSPP_2K_BLOCKS} + \
     (1 << 12) * ${SSM_GSPP_4K_BLOCKS} + \
     (1 << 14) * ${SSM_GSPP_16K_BLOCKS} + \
     (1 << 16) * ${SSM_GSPP_64K_BLOCKS} + \
     (1 << 18) * ${SSM_GSPP_256K_BLOCKS} + \
     (1 << 20) * ${SSM_GSPP_1M_BLOCKS}")

set(SSM_GSPP_TOTAL_SIZE ${SSM_GSPP_TOTAL_SIZE} CACHE INTERNAL
    "GSPP total size in bytes")

math(EXPR SSM_PUP_TOTAL_SIZE
    "(1 << 8) * ${SSM_PUP_256_BLOCKS} + \
     (1 << 9) * ${SSM_PUP_512_BLOCKS} + \
     (1 << 10) * ${SSM_PUP_1K_BLOCKS} + \
     (1 << 11) * ${SSM_PUP_2K_BLOCKS} + \
     (1 << 12) * ${SSM_PUP_4K_BLOCKS} + \
     (1 << 14) * ${SSM_PUP_16K_BLOCKS} + \
     (1 << 16) * ${SSM_PUP_64K_BLOCKS} + \
     (1 << 18) * ${SSM_PUP_256K_BLOCKS} + \
     (1 << 20) * ${SSM_PUP_1M_BLOCKS}")

set(SSM_PUP_TOTAL_SIZE ${SSM_PUP_TOTAL_SIZE} CACHE INTERNAL
    "PUP total size in bytes")

set(SSM_POOL_TOTAL_SIZE ${SSM_GSPP_TOTAL_SIZE} CACHE INTERNAL
    "Total shared memory pool size in bytes")

format_bytes_human_readable(${SSM_GSPP_TOTAL_SIZE} SSM_GSPP_SIZE_DISPLAY)
format_bytes_human_readable(${SSM_PUP_TOTAL_SIZE} SSM_PUP_SIZE_DISPLAY)

message(STATUS "Secure Shared Memory Pool Configuration:")
message(STATUS "  Pool prefix: ${SSM_PREFIX}")
message(STATUS "  Size classes: "
    "256B, 512B, 1KiB, 2KiB, 4KiB, 16KiB, 64KiB, 256KiB, 1MiB")
message(STATUS "  Max allocation: 1 MB")
message(STATUS "  Shards per class: ${SSM_POOL_SHARDS}")
message(STATUS "  GSPP (privileged): ${SSM_GSPP_SIZE_DISPLAY} "
    "(${SSM_GSPP_TOTAL_SIZE} bytes)")
message(STATUS "    Blocks: ${SSM_GSPP_256_BLOCKS}, ${SSM_GSPP_512_BLOCKS}, "
    "${SSM_GSPP_1K_BLOCKS}, ${SSM_GSPP_2K_BLOCKS}, ${SSM_GSPP_4K_BLOCKS}, "
    "${SSM_GSPP_16K_BLOCKS}, ${SSM_GSPP_64K_BLOCKS}, ${SSM_GSPP_256K_BLOCKS}, "
    "${SSM_GSPP_1M_BLOCKS}")
message(STATUS "  PUP (unprivileged): ${SSM_PUP_SIZE_DISPLAY} "
    "(${SSM_PUP_TOTAL_SIZE} bytes)")
message(STATUS "    Blocks: ${SSM_PUP_256_BLOCKS}, ${SSM_PUP_512_BLOCKS}, "
    "${SSM_PUP_1K_BLOCKS}, ${SSM_PUP_2K_BLOCKS}, ${SSM_PUP_4K_BLOCKS}, "
    "${SSM_PUP_16K_BLOCKS}, ${SSM_PUP_64K_BLOCKS}, ${SSM_PUP_256K_BLOCKS}, "
    "${SSM_PUP_1M_BLOCKS}")

math(EXPR SSM_RBUFF_TXQ_RESERVE
    "${SSM_RBUFF_SIZE} / ${SSM_RBUFF_TXQ_PRIO_DIV}")

set(SSM_RBUFF_TXQ_RESERVE ${SSM_RBUFF_TXQ_RESERVE} CACHE INTERNAL
    "Top-of-ring slots new data may not use")

math(EXPR SSM_RBUFF_TXQ_DATA_MAX
    "${SSM_RBUFF_SIZE} - 1 - ${SSM_RBUFF_TXQ_RESERVE}")

# The limiter asserts its target fits SSM_RBUFF_TXQ_MAX_DELAY (1 s).
if(SSM_RBUFF_TXQ_DELAY LESS 0 OR SSM_RBUFF_TXQ_DELAY GREATER 1000)
    message(FATAL_ERROR
        "SSM_RBUFF_TXQ_DELAY (${SSM_RBUFF_TXQ_DELAY}) must be in "
        "[0, 1000] ms; a longer target trips the limiter's own bound.")
endif()

# What the reserve leaves new data must still clear the 4-slot floor.
if(SSM_RBUFF_TXQ_DATA_MAX LESS 4)
    message(FATAL_ERROR
        "SSM_RBUFF_TXQ_PRIO_DIV (${SSM_RBUFF_TXQ_PRIO_DIV}) leaves new "
        "data ${SSM_RBUFF_TXQ_DATA_MAX} of ${SSM_RBUFF_SIZE} slots, "
        "below the 4-slot floor: every write would be refused.")
endif()

# Both bounds keep the retransmission headroom above zero: the divisor
# reserves it at saturation, the multiplier below it.
if(SSM_RBUFF_TXQ_PRIO_DIV LESS 2 OR SSM_RBUFF_TXQ_RESERVE LESS 1)
    message(FATAL_ERROR
        "SSM_RBUFF_TXQ_PRIO_DIV (${SSM_RBUFF_TXQ_PRIO_DIV}) must be in "
        "[2, SSM_RBUFF_SIZE (${SSM_RBUFF_SIZE})]: it reserves "
        "${SSM_RBUFF_TXQ_RESERVE} of ${SSM_RBUFF_SIZE} slots for "
        "retransmissions.")
endif()

if(SSM_RBUFF_TXQ_PRIO_MUL LESS 2)
    message(FATAL_ERROR
        "SSM_RBUFF_TXQ_PRIO_MUL (${SSM_RBUFF_TXQ_PRIO_MUL}) must be >= 2: "
        "at 1 a retransmission gets the ceiling new data already has.")
endif()

# FRCT reorder queue must fit in every enabled size class. If RQ_SIZE >= any backing pool, the
# receiver advertises a window the pool cannot back; np1_flow_write fails under load and a single
# dropped fragment wedges the flow. Auto-zeroed classes are skipped.
foreach(_class 256 512 1K 2K)
    if(SSM_PUP_${_class}_BLOCKS GREATER 0
       AND NOT FRCT_REORDER_QUEUE_SIZE LESS SSM_PUP_${_class}_BLOCKS)
        message(FATAL_ERROR
            "FRCT_REORDER_QUEUE_SIZE (${FRCT_REORDER_QUEUE_SIZE}) must be "
            "< SSM_PUP_${_class}_BLOCKS (${SSM_PUP_${_class}_BLOCKS}): "
            "the FC window cannot exceed the pool that backs OOO stashing.")
    endif()
    if(SSM_GSPP_${_class}_BLOCKS GREATER 0
       AND NOT FRCT_REORDER_QUEUE_SIZE LESS SSM_GSPP_${_class}_BLOCKS)
        message(FATAL_ERROR
            "FRCT_REORDER_QUEUE_SIZE (${FRCT_REORDER_QUEUE_SIZE}) must be "
            "< SSM_GSPP_${_class}_BLOCKS (${SSM_GSPP_${_class}_BLOCKS}).")
    endif()
endforeach()