Skip to content

Commit b047cbe

Browse files
committed
Add compile-time configuration options for counts and buffer sizes.
1 parent a656ab0 commit b047cbe

File tree

12 files changed

+466
-85
lines changed

12 files changed

+466
-85
lines changed

Cargo.toml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,141 @@ default = [
8080

8181
"_proto-fragmentation" = []
8282

83+
# BEGIN AUTOGENERATED CONFIG FEATURES
84+
# Generated by gen_config.py. DO NOT EDIT.
85+
iface-max-addr-count-1 = []
86+
iface-max-addr-count-2 = [] # Default
87+
iface-max-addr-count-3 = []
88+
iface-max-addr-count-4 = []
89+
iface-max-addr-count-5 = []
90+
iface-max-addr-count-6 = []
91+
iface-max-addr-count-7 = []
92+
iface-max-addr-count-8 = []
93+
94+
iface-max-multicast-group-count-1 = []
95+
iface-max-multicast-group-count-2 = []
96+
iface-max-multicast-group-count-3 = []
97+
iface-max-multicast-group-count-4 = [] # Default
98+
iface-max-multicast-group-count-5 = []
99+
iface-max-multicast-group-count-6 = []
100+
iface-max-multicast-group-count-7 = []
101+
iface-max-multicast-group-count-8 = []
102+
iface-max-multicast-group-count-16 = []
103+
iface-max-multicast-group-count-32 = []
104+
iface-max-multicast-group-count-64 = []
105+
iface-max-multicast-group-count-128 = []
106+
iface-max-multicast-group-count-256 = []
107+
iface-max-multicast-group-count-512 = []
108+
iface-max-multicast-group-count-1024 = []
109+
110+
iface-max-sixlowpan-address-context-count-1 = []
111+
iface-max-sixlowpan-address-context-count-2 = []
112+
iface-max-sixlowpan-address-context-count-3 = []
113+
iface-max-sixlowpan-address-context-count-4 = [] # Default
114+
iface-max-sixlowpan-address-context-count-5 = []
115+
iface-max-sixlowpan-address-context-count-6 = []
116+
iface-max-sixlowpan-address-context-count-7 = []
117+
iface-max-sixlowpan-address-context-count-8 = []
118+
iface-max-sixlowpan-address-context-count-16 = []
119+
iface-max-sixlowpan-address-context-count-32 = []
120+
iface-max-sixlowpan-address-context-count-64 = []
121+
iface-max-sixlowpan-address-context-count-128 = []
122+
iface-max-sixlowpan-address-context-count-256 = []
123+
iface-max-sixlowpan-address-context-count-512 = []
124+
iface-max-sixlowpan-address-context-count-1024 = []
125+
126+
iface-neighbor-cache-count-1 = []
127+
iface-neighbor-cache-count-2 = []
128+
iface-neighbor-cache-count-3 = []
129+
iface-neighbor-cache-count-4 = [] # Default
130+
iface-neighbor-cache-count-5 = []
131+
iface-neighbor-cache-count-6 = []
132+
iface-neighbor-cache-count-7 = []
133+
iface-neighbor-cache-count-8 = []
134+
iface-neighbor-cache-count-16 = []
135+
iface-neighbor-cache-count-32 = []
136+
iface-neighbor-cache-count-64 = []
137+
iface-neighbor-cache-count-128 = []
138+
iface-neighbor-cache-count-256 = []
139+
iface-neighbor-cache-count-512 = []
140+
iface-neighbor-cache-count-1024 = []
141+
142+
iface-max-route-count-1 = []
143+
iface-max-route-count-2 = [] # Default
144+
iface-max-route-count-3 = []
145+
iface-max-route-count-4 = []
146+
iface-max-route-count-5 = []
147+
iface-max-route-count-6 = []
148+
iface-max-route-count-7 = []
149+
iface-max-route-count-8 = []
150+
iface-max-route-count-16 = []
151+
iface-max-route-count-32 = []
152+
iface-max-route-count-64 = []
153+
iface-max-route-count-128 = []
154+
iface-max-route-count-256 = []
155+
iface-max-route-count-512 = []
156+
iface-max-route-count-1024 = []
157+
158+
fragmentation-buffer-size-256 = []
159+
fragmentation-buffer-size-512 = []
160+
fragmentation-buffer-size-1024 = []
161+
fragmentation-buffer-size-1500 = [] # Default
162+
fragmentation-buffer-size-2048 = []
163+
fragmentation-buffer-size-4096 = []
164+
fragmentation-buffer-size-8192 = []
165+
fragmentation-buffer-size-16384 = []
166+
fragmentation-buffer-size-32768 = []
167+
fragmentation-buffer-size-65536 = []
168+
169+
assembler-max-segment-count-1 = []
170+
assembler-max-segment-count-2 = []
171+
assembler-max-segment-count-3 = []
172+
assembler-max-segment-count-4 = [] # Default
173+
assembler-max-segment-count-8 = []
174+
assembler-max-segment-count-16 = []
175+
assembler-max-segment-count-32 = []
176+
177+
reassembly-buffer-size-256 = []
178+
reassembly-buffer-size-512 = []
179+
reassembly-buffer-size-1024 = []
180+
reassembly-buffer-size-1500 = [] # Default
181+
reassembly-buffer-size-2048 = []
182+
reassembly-buffer-size-4096 = []
183+
reassembly-buffer-size-8192 = []
184+
reassembly-buffer-size-16384 = []
185+
reassembly-buffer-size-32768 = []
186+
reassembly-buffer-size-65536 = []
187+
188+
reassembly-buffer-count-1 = [] # Default
189+
reassembly-buffer-count-2 = []
190+
reassembly-buffer-count-3 = []
191+
reassembly-buffer-count-4 = []
192+
reassembly-buffer-count-8 = []
193+
reassembly-buffer-count-16 = []
194+
reassembly-buffer-count-32 = []
195+
196+
dns-max-result-count-1 = [] # Default
197+
dns-max-result-count-2 = []
198+
dns-max-result-count-3 = []
199+
dns-max-result-count-4 = []
200+
dns-max-result-count-8 = []
201+
dns-max-result-count-16 = []
202+
dns-max-result-count-32 = []
203+
204+
dns-max-server-count-1 = [] # Default
205+
dns-max-server-count-2 = []
206+
dns-max-server-count-3 = []
207+
dns-max-server-count-4 = []
208+
dns-max-server-count-8 = []
209+
dns-max-server-count-16 = []
210+
dns-max-server-count-32 = []
211+
212+
dns-max-name-size-64 = []
213+
dns-max-name-size-128 = []
214+
dns-max-name-size-255 = [] # Default
215+
216+
# END AUTOGENERATED CONFIG FEATURES
217+
83218
[[example]]
84219
name = "packet2pcap"
85220
path = "utils/packet2pcap.rs"

README.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ You probably want to disable default features and configure them one by one:
147147
smoltcp = { version = "0.8.0", default-features = false, features = ["log"] }
148148
```
149149

150+
## Feature flags
151+
150152
### Feature `std`
151153

152154
The `std` feature enables use of objects and slices owned by the networking stack through a
@@ -195,7 +197,7 @@ Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TunTapInterface`, respective
195197

196198
These features are enabled by default.
197199

198-
### Features `socket-raw`, `socket-udp`, `socket-tcp`, `socket-icmp`, `socket-dhcpv4`
200+
### Features `socket-raw`, `socket-udp`, `socket-tcp`, `socket-icmp`, `socket-dhcpv4`, `socket-dns`
199201

200202
Enable the corresponding socket type.
201203

@@ -208,6 +210,73 @@ Enable [IPv4] and [IPv6] respectively.
208210
[IPv4]: https://tools.ietf.org/rfc/rfc791.txt
209211
[IPv6]: https://tools.ietf.org/rfc/rfc8200.txt
210212

213+
## Configuration
214+
215+
_smoltcp_ has some configuration settings that are set at compile time, affecting sizes
216+
and counts of buffers.
217+
218+
They can be set in two ways:
219+
220+
- Via Cargo features: enable a feature like `<name>-<value>`. `name` must be in lowercase and
221+
use dashes instead of underscores. For example. `iface-max-addr-count-3`. Only a selection of values
222+
is available, check `Cargo.toml` for the list.
223+
- Via environment variables at build time: set the variable named `SMOLTCP_<value>`. For example
224+
`SMOLTCP_IFACE_MAX_ADDR_COUNT=3 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`.
225+
Any value can be set, unlike with Cargo features.
226+
227+
Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting
228+
with different values, compilation fails.
229+
230+
### IFACE_MAX_ADDR_COUNT
231+
232+
Max amount of IP addresses that can be assigned to one interface (counting both IPv4 and IPv6 addresses). Default: 2.
233+
234+
### IFACE_MAX_MULTICAST_GROUP_COUNT
235+
236+
Max amount of multicast groups that can be joined by one interface. Default: 4.
237+
238+
### IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT
239+
240+
Max amount of 6LoWPAN address contexts that can be assigned to one interface. Default: 4.
241+
242+
### IFACE_NEIGHBOR_CACHE_COUNT
243+
244+
Amount of "IP address -> hardware address" entries the neighbor cache (also known as the "ARP cache" or the "ARP table") holds. Default: 4.
245+
246+
### IFACE_MAX_ROUTE_COUNT
247+
248+
Max amount of routes that can be added to one interface. Includes the default route. Includes both IPv4 and IPv6. Default: 2.
249+
250+
### FRAGMENTATION_BUFFER_SIZE
251+
252+
Size of the buffer used for fragmenting outgoing packets larger than the MTU. Packets larger than this setting will be dropped instead of fragmented. Default: 1500.
253+
254+
### ASSEMBLER_MAX_SEGMENT_COUNT
255+
256+
Maximum number of non-contiguous segments the assembler can hold. Used for both packet reassembly and TCP stream reassembly. Default: 4.
257+
258+
### REASSEMBLY_BUFFER_SIZE
259+
260+
Size of the buffer used for reassembling (de-fragmenting) incoming packets. If the reassembled packet is larger than this setting, it will be dropped instead of reassembled. Default: 1500.
261+
262+
### REASSEMBLY_BUFFER_COUNT
263+
264+
Number of reassembly buffers, i.e how many different incoming packets can be reassembled at the same time. Default: 1.
265+
266+
### DNS_MAX_RESULT_COUNT
267+
268+
Maximum amount of address results for a given DNS query that will be kept. For example, if this is set to 2 and the queried name has 4 `A` records, only the first 2 will be returned. Default: 1.
269+
270+
### DNS_MAX_SERVER_COUNT
271+
272+
Maximum amount of DNS servers that can be configured in one DNS socket. Default: 1.
273+
274+
### DNS_MAX_NAME_SIZE
275+
276+
Maximum length of DNS names that can be queried. Default: 255.
277+
278+
279+
211280
## Hosted usage examples
212281

213282
_smoltcp_, being a freestanding networking stack, needs to be able to transmit and receive

build.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use std::collections::HashMap;
2+
use std::fmt::Write;
3+
use std::path::PathBuf;
4+
use std::{env, fs};
5+
6+
static CONFIGS: &[(&str, usize)] = &[
7+
// BEGIN AUTOGENERATED CONFIG FEATURES
8+
// Generated by gen_config.py. DO NOT EDIT.
9+
("IFACE_MAX_ADDR_COUNT", 2),
10+
("IFACE_MAX_MULTICAST_GROUP_COUNT", 4),
11+
("IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT", 4),
12+
("IFACE_NEIGHBOR_CACHE_COUNT", 4),
13+
("IFACE_MAX_ROUTE_COUNT", 2),
14+
("FRAGMENTATION_BUFFER_SIZE", 1500),
15+
("ASSEMBLER_MAX_SEGMENT_COUNT", 4),
16+
("REASSEMBLY_BUFFER_SIZE", 1500),
17+
("REASSEMBLY_BUFFER_COUNT", 1),
18+
("DNS_MAX_RESULT_COUNT", 1),
19+
("DNS_MAX_SERVER_COUNT", 1),
20+
("DNS_MAX_NAME_SIZE", 255),
21+
// END AUTOGENERATED CONFIG FEATURES
22+
];
23+
24+
struct ConfigState {
25+
value: usize,
26+
seen_feature: bool,
27+
seen_env: bool,
28+
}
29+
30+
fn main() {
31+
// only rebuild if build.rs changed. Otherwise Cargo will rebuild if any
32+
// other file changed.
33+
println!("cargo:rerun-if-changed=build.rs");
34+
35+
// Rebuild if config envvar changed.
36+
for (name, _) in CONFIGS {
37+
println!("cargo:rerun-if-env-changed=SMOLTCP_{name}");
38+
}
39+
40+
let mut configs = HashMap::new();
41+
for (name, default) in CONFIGS {
42+
configs.insert(
43+
*name,
44+
ConfigState {
45+
value: *default,
46+
seen_env: false,
47+
seen_feature: false,
48+
},
49+
);
50+
}
51+
52+
for (var, value) in env::vars() {
53+
if let Some(name) = var.strip_prefix("SMOLTCP_") {
54+
let Some(cfg) = configs.get_mut(name) else {
55+
panic!("Unknown env var {name}")
56+
};
57+
58+
let Ok(value) = value.parse::<usize>() else {
59+
panic!("Invalid value for env var {name}: {value}")
60+
};
61+
62+
cfg.value = value;
63+
cfg.seen_env = true;
64+
}
65+
66+
if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") {
67+
if let Some(i) = feature.rfind('_') {
68+
let name = &feature[..i];
69+
let value = &feature[i + 1..];
70+
if let Some(cfg) = configs.get_mut(name) {
71+
let Ok(value) = value.parse::<usize>() else {
72+
panic!("Invalid value for feature {name}: {value}")
73+
};
74+
75+
// envvars take priority.
76+
if !cfg.seen_env {
77+
if cfg.seen_feature {
78+
panic!(
79+
"multiple values set for feature {}: {} and {}",
80+
name, cfg.value, value
81+
);
82+
}
83+
84+
cfg.value = value;
85+
cfg.seen_feature = true;
86+
}
87+
}
88+
}
89+
}
90+
}
91+
92+
let mut data = String::new();
93+
94+
for (name, cfg) in &configs {
95+
writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap();
96+
}
97+
98+
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
99+
let out_file = out_dir.join("config.rs").to_string_lossy().to_string();
100+
fs::write(out_file, data).unwrap();
101+
}

0 commit comments

Comments
 (0)