mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-10-02 23:25:20 +00:00
Add compile-time configuration options for counts and buffer sizes.
This commit is contained in:
parent
a656ab0c08
commit
b047cbeade
135
Cargo.toml
135
Cargo.toml
@ -80,6 +80,141 @@ default = [
|
|||||||
|
|
||||||
"_proto-fragmentation" = []
|
"_proto-fragmentation" = []
|
||||||
|
|
||||||
|
# BEGIN AUTOGENERATED CONFIG FEATURES
|
||||||
|
# Generated by gen_config.py. DO NOT EDIT.
|
||||||
|
iface-max-addr-count-1 = []
|
||||||
|
iface-max-addr-count-2 = [] # Default
|
||||||
|
iface-max-addr-count-3 = []
|
||||||
|
iface-max-addr-count-4 = []
|
||||||
|
iface-max-addr-count-5 = []
|
||||||
|
iface-max-addr-count-6 = []
|
||||||
|
iface-max-addr-count-7 = []
|
||||||
|
iface-max-addr-count-8 = []
|
||||||
|
|
||||||
|
iface-max-multicast-group-count-1 = []
|
||||||
|
iface-max-multicast-group-count-2 = []
|
||||||
|
iface-max-multicast-group-count-3 = []
|
||||||
|
iface-max-multicast-group-count-4 = [] # Default
|
||||||
|
iface-max-multicast-group-count-5 = []
|
||||||
|
iface-max-multicast-group-count-6 = []
|
||||||
|
iface-max-multicast-group-count-7 = []
|
||||||
|
iface-max-multicast-group-count-8 = []
|
||||||
|
iface-max-multicast-group-count-16 = []
|
||||||
|
iface-max-multicast-group-count-32 = []
|
||||||
|
iface-max-multicast-group-count-64 = []
|
||||||
|
iface-max-multicast-group-count-128 = []
|
||||||
|
iface-max-multicast-group-count-256 = []
|
||||||
|
iface-max-multicast-group-count-512 = []
|
||||||
|
iface-max-multicast-group-count-1024 = []
|
||||||
|
|
||||||
|
iface-max-sixlowpan-address-context-count-1 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-2 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-3 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-4 = [] # Default
|
||||||
|
iface-max-sixlowpan-address-context-count-5 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-6 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-7 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-8 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-16 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-32 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-64 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-128 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-256 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-512 = []
|
||||||
|
iface-max-sixlowpan-address-context-count-1024 = []
|
||||||
|
|
||||||
|
iface-neighbor-cache-count-1 = []
|
||||||
|
iface-neighbor-cache-count-2 = []
|
||||||
|
iface-neighbor-cache-count-3 = []
|
||||||
|
iface-neighbor-cache-count-4 = [] # Default
|
||||||
|
iface-neighbor-cache-count-5 = []
|
||||||
|
iface-neighbor-cache-count-6 = []
|
||||||
|
iface-neighbor-cache-count-7 = []
|
||||||
|
iface-neighbor-cache-count-8 = []
|
||||||
|
iface-neighbor-cache-count-16 = []
|
||||||
|
iface-neighbor-cache-count-32 = []
|
||||||
|
iface-neighbor-cache-count-64 = []
|
||||||
|
iface-neighbor-cache-count-128 = []
|
||||||
|
iface-neighbor-cache-count-256 = []
|
||||||
|
iface-neighbor-cache-count-512 = []
|
||||||
|
iface-neighbor-cache-count-1024 = []
|
||||||
|
|
||||||
|
iface-max-route-count-1 = []
|
||||||
|
iface-max-route-count-2 = [] # Default
|
||||||
|
iface-max-route-count-3 = []
|
||||||
|
iface-max-route-count-4 = []
|
||||||
|
iface-max-route-count-5 = []
|
||||||
|
iface-max-route-count-6 = []
|
||||||
|
iface-max-route-count-7 = []
|
||||||
|
iface-max-route-count-8 = []
|
||||||
|
iface-max-route-count-16 = []
|
||||||
|
iface-max-route-count-32 = []
|
||||||
|
iface-max-route-count-64 = []
|
||||||
|
iface-max-route-count-128 = []
|
||||||
|
iface-max-route-count-256 = []
|
||||||
|
iface-max-route-count-512 = []
|
||||||
|
iface-max-route-count-1024 = []
|
||||||
|
|
||||||
|
fragmentation-buffer-size-256 = []
|
||||||
|
fragmentation-buffer-size-512 = []
|
||||||
|
fragmentation-buffer-size-1024 = []
|
||||||
|
fragmentation-buffer-size-1500 = [] # Default
|
||||||
|
fragmentation-buffer-size-2048 = []
|
||||||
|
fragmentation-buffer-size-4096 = []
|
||||||
|
fragmentation-buffer-size-8192 = []
|
||||||
|
fragmentation-buffer-size-16384 = []
|
||||||
|
fragmentation-buffer-size-32768 = []
|
||||||
|
fragmentation-buffer-size-65536 = []
|
||||||
|
|
||||||
|
assembler-max-segment-count-1 = []
|
||||||
|
assembler-max-segment-count-2 = []
|
||||||
|
assembler-max-segment-count-3 = []
|
||||||
|
assembler-max-segment-count-4 = [] # Default
|
||||||
|
assembler-max-segment-count-8 = []
|
||||||
|
assembler-max-segment-count-16 = []
|
||||||
|
assembler-max-segment-count-32 = []
|
||||||
|
|
||||||
|
reassembly-buffer-size-256 = []
|
||||||
|
reassembly-buffer-size-512 = []
|
||||||
|
reassembly-buffer-size-1024 = []
|
||||||
|
reassembly-buffer-size-1500 = [] # Default
|
||||||
|
reassembly-buffer-size-2048 = []
|
||||||
|
reassembly-buffer-size-4096 = []
|
||||||
|
reassembly-buffer-size-8192 = []
|
||||||
|
reassembly-buffer-size-16384 = []
|
||||||
|
reassembly-buffer-size-32768 = []
|
||||||
|
reassembly-buffer-size-65536 = []
|
||||||
|
|
||||||
|
reassembly-buffer-count-1 = [] # Default
|
||||||
|
reassembly-buffer-count-2 = []
|
||||||
|
reassembly-buffer-count-3 = []
|
||||||
|
reassembly-buffer-count-4 = []
|
||||||
|
reassembly-buffer-count-8 = []
|
||||||
|
reassembly-buffer-count-16 = []
|
||||||
|
reassembly-buffer-count-32 = []
|
||||||
|
|
||||||
|
dns-max-result-count-1 = [] # Default
|
||||||
|
dns-max-result-count-2 = []
|
||||||
|
dns-max-result-count-3 = []
|
||||||
|
dns-max-result-count-4 = []
|
||||||
|
dns-max-result-count-8 = []
|
||||||
|
dns-max-result-count-16 = []
|
||||||
|
dns-max-result-count-32 = []
|
||||||
|
|
||||||
|
dns-max-server-count-1 = [] # Default
|
||||||
|
dns-max-server-count-2 = []
|
||||||
|
dns-max-server-count-3 = []
|
||||||
|
dns-max-server-count-4 = []
|
||||||
|
dns-max-server-count-8 = []
|
||||||
|
dns-max-server-count-16 = []
|
||||||
|
dns-max-server-count-32 = []
|
||||||
|
|
||||||
|
dns-max-name-size-64 = []
|
||||||
|
dns-max-name-size-128 = []
|
||||||
|
dns-max-name-size-255 = [] # Default
|
||||||
|
|
||||||
|
# END AUTOGENERATED CONFIG FEATURES
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "packet2pcap"
|
name = "packet2pcap"
|
||||||
path = "utils/packet2pcap.rs"
|
path = "utils/packet2pcap.rs"
|
||||||
|
71
README.md
71
README.md
@ -147,6 +147,8 @@ You probably want to disable default features and configure them one by one:
|
|||||||
smoltcp = { version = "0.8.0", default-features = false, features = ["log"] }
|
smoltcp = { version = "0.8.0", default-features = false, features = ["log"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Feature flags
|
||||||
|
|
||||||
### Feature `std`
|
### Feature `std`
|
||||||
|
|
||||||
The `std` feature enables use of objects and slices owned by the networking stack through a
|
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
|
|||||||
|
|
||||||
These features are enabled by default.
|
These features are enabled by default.
|
||||||
|
|
||||||
### Features `socket-raw`, `socket-udp`, `socket-tcp`, `socket-icmp`, `socket-dhcpv4`
|
### Features `socket-raw`, `socket-udp`, `socket-tcp`, `socket-icmp`, `socket-dhcpv4`, `socket-dns`
|
||||||
|
|
||||||
Enable the corresponding socket type.
|
Enable the corresponding socket type.
|
||||||
|
|
||||||
@ -208,6 +210,73 @@ Enable [IPv4] and [IPv6] respectively.
|
|||||||
[IPv4]: https://tools.ietf.org/rfc/rfc791.txt
|
[IPv4]: https://tools.ietf.org/rfc/rfc791.txt
|
||||||
[IPv6]: https://tools.ietf.org/rfc/rfc8200.txt
|
[IPv6]: https://tools.ietf.org/rfc/rfc8200.txt
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
_smoltcp_ has some configuration settings that are set at compile time, affecting sizes
|
||||||
|
and counts of buffers.
|
||||||
|
|
||||||
|
They can be set in two ways:
|
||||||
|
|
||||||
|
- Via Cargo features: enable a feature like `<name>-<value>`. `name` must be in lowercase and
|
||||||
|
use dashes instead of underscores. For example. `iface-max-addr-count-3`. Only a selection of values
|
||||||
|
is available, check `Cargo.toml` for the list.
|
||||||
|
- Via environment variables at build time: set the variable named `SMOLTCP_<value>`. For example
|
||||||
|
`SMOLTCP_IFACE_MAX_ADDR_COUNT=3 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`.
|
||||||
|
Any value can be set, unlike with Cargo features.
|
||||||
|
|
||||||
|
Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting
|
||||||
|
with different values, compilation fails.
|
||||||
|
|
||||||
|
### IFACE_MAX_ADDR_COUNT
|
||||||
|
|
||||||
|
Max amount of IP addresses that can be assigned to one interface (counting both IPv4 and IPv6 addresses). Default: 2.
|
||||||
|
|
||||||
|
### IFACE_MAX_MULTICAST_GROUP_COUNT
|
||||||
|
|
||||||
|
Max amount of multicast groups that can be joined by one interface. Default: 4.
|
||||||
|
|
||||||
|
### IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT
|
||||||
|
|
||||||
|
Max amount of 6LoWPAN address contexts that can be assigned to one interface. Default: 4.
|
||||||
|
|
||||||
|
### IFACE_NEIGHBOR_CACHE_COUNT
|
||||||
|
|
||||||
|
Amount of "IP address -> hardware address" entries the neighbor cache (also known as the "ARP cache" or the "ARP table") holds. Default: 4.
|
||||||
|
|
||||||
|
### IFACE_MAX_ROUTE_COUNT
|
||||||
|
|
||||||
|
Max amount of routes that can be added to one interface. Includes the default route. Includes both IPv4 and IPv6. Default: 2.
|
||||||
|
|
||||||
|
### FRAGMENTATION_BUFFER_SIZE
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### ASSEMBLER_MAX_SEGMENT_COUNT
|
||||||
|
|
||||||
|
Maximum number of non-contiguous segments the assembler can hold. Used for both packet reassembly and TCP stream reassembly. Default: 4.
|
||||||
|
|
||||||
|
### REASSEMBLY_BUFFER_SIZE
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### REASSEMBLY_BUFFER_COUNT
|
||||||
|
|
||||||
|
Number of reassembly buffers, i.e how many different incoming packets can be reassembled at the same time. Default: 1.
|
||||||
|
|
||||||
|
### DNS_MAX_RESULT_COUNT
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### DNS_MAX_SERVER_COUNT
|
||||||
|
|
||||||
|
Maximum amount of DNS servers that can be configured in one DNS socket. Default: 1.
|
||||||
|
|
||||||
|
### DNS_MAX_NAME_SIZE
|
||||||
|
|
||||||
|
Maximum length of DNS names that can be queried. Default: 255.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Hosted usage examples
|
## Hosted usage examples
|
||||||
|
|
||||||
_smoltcp_, being a freestanding networking stack, needs to be able to transmit and receive
|
_smoltcp_, being a freestanding networking stack, needs to be able to transmit and receive
|
||||||
|
101
build.rs
Normal file
101
build.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::{env, fs};
|
||||||
|
|
||||||
|
static CONFIGS: &[(&str, usize)] = &[
|
||||||
|
// BEGIN AUTOGENERATED CONFIG FEATURES
|
||||||
|
// Generated by gen_config.py. DO NOT EDIT.
|
||||||
|
("IFACE_MAX_ADDR_COUNT", 2),
|
||||||
|
("IFACE_MAX_MULTICAST_GROUP_COUNT", 4),
|
||||||
|
("IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT", 4),
|
||||||
|
("IFACE_NEIGHBOR_CACHE_COUNT", 4),
|
||||||
|
("IFACE_MAX_ROUTE_COUNT", 2),
|
||||||
|
("FRAGMENTATION_BUFFER_SIZE", 1500),
|
||||||
|
("ASSEMBLER_MAX_SEGMENT_COUNT", 4),
|
||||||
|
("REASSEMBLY_BUFFER_SIZE", 1500),
|
||||||
|
("REASSEMBLY_BUFFER_COUNT", 1),
|
||||||
|
("DNS_MAX_RESULT_COUNT", 1),
|
||||||
|
("DNS_MAX_SERVER_COUNT", 1),
|
||||||
|
("DNS_MAX_NAME_SIZE", 255),
|
||||||
|
// END AUTOGENERATED CONFIG FEATURES
|
||||||
|
];
|
||||||
|
|
||||||
|
struct ConfigState {
|
||||||
|
value: usize,
|
||||||
|
seen_feature: bool,
|
||||||
|
seen_env: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// only rebuild if build.rs changed. Otherwise Cargo will rebuild if any
|
||||||
|
// other file changed.
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
// Rebuild if config envvar changed.
|
||||||
|
for (name, _) in CONFIGS {
|
||||||
|
println!("cargo:rerun-if-env-changed=SMOLTCP_{name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut configs = HashMap::new();
|
||||||
|
for (name, default) in CONFIGS {
|
||||||
|
configs.insert(
|
||||||
|
*name,
|
||||||
|
ConfigState {
|
||||||
|
value: *default,
|
||||||
|
seen_env: false,
|
||||||
|
seen_feature: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var, value) in env::vars() {
|
||||||
|
if let Some(name) = var.strip_prefix("SMOLTCP_") {
|
||||||
|
let Some(cfg) = configs.get_mut(name) else {
|
||||||
|
panic!("Unknown env var {name}")
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(value) = value.parse::<usize>() else {
|
||||||
|
panic!("Invalid value for env var {name}: {value}")
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg.value = value;
|
||||||
|
cfg.seen_env = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") {
|
||||||
|
if let Some(i) = feature.rfind('_') {
|
||||||
|
let name = &feature[..i];
|
||||||
|
let value = &feature[i + 1..];
|
||||||
|
if let Some(cfg) = configs.get_mut(name) {
|
||||||
|
let Ok(value) = value.parse::<usize>() else {
|
||||||
|
panic!("Invalid value for feature {name}: {value}")
|
||||||
|
};
|
||||||
|
|
||||||
|
// envvars take priority.
|
||||||
|
if !cfg.seen_env {
|
||||||
|
if cfg.seen_feature {
|
||||||
|
panic!(
|
||||||
|
"multiple values set for feature {}: {} and {}",
|
||||||
|
name, cfg.value, value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.value = value;
|
||||||
|
cfg.seen_feature = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut data = String::new();
|
||||||
|
|
||||||
|
for (name, cfg) in &configs {
|
||||||
|
writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
let out_file = out_dir.join("config.rs").to_string_lossy().to_string();
|
||||||
|
fs::write(out_file, data).unwrap();
|
||||||
|
}
|
83
gen_config.py
Normal file
83
gen_config.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
abspath = os.path.abspath(__file__)
|
||||||
|
dname = os.path.dirname(abspath)
|
||||||
|
os.chdir(dname)
|
||||||
|
|
||||||
|
features = []
|
||||||
|
|
||||||
|
|
||||||
|
def feature(name, default, min, max, pow2=None):
|
||||||
|
vals = set()
|
||||||
|
val = min
|
||||||
|
while val <= max:
|
||||||
|
vals.add(val)
|
||||||
|
if pow2 == True or (isinstance(pow2, int) and val >= pow2):
|
||||||
|
val *= 2
|
||||||
|
else:
|
||||||
|
val += 1
|
||||||
|
vals.add(default)
|
||||||
|
|
||||||
|
features.append(
|
||||||
|
{
|
||||||
|
"name": name,
|
||||||
|
"default": default,
|
||||||
|
"vals": sorted(list(vals)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
feature("iface_max_addr_count", default=2, min=1, max=8)
|
||||||
|
feature("iface_max_multicast_group_count", default=4, min=1, max=1024, pow2=8)
|
||||||
|
feature("iface_max_sixlowpan_address_context_count", default=4, min=1, max=1024, pow2=8)
|
||||||
|
feature("iface_neighbor_cache_count", default=4, min=1, max=1024, pow2=8)
|
||||||
|
feature("iface_max_route_count", default=2, min=1, max=1024, pow2=8)
|
||||||
|
feature("fragmentation_buffer_size", default=1500, min=256, max=65536, pow2=True)
|
||||||
|
feature("assembler_max_segment_count", default=4, min=1, max=32, pow2=4)
|
||||||
|
feature("reassembly_buffer_size", default=1500, min=256, max=65536, pow2=True)
|
||||||
|
feature("reassembly_buffer_count", default=1, min=1, max=32, pow2=4)
|
||||||
|
feature("dns_max_result_count", default=1, min=1, max=32, pow2=4)
|
||||||
|
feature("dns_max_server_count", default=1, min=1, max=32, pow2=4)
|
||||||
|
feature("dns_max_name_size", default=255, min=64, max=255, pow2=True)
|
||||||
|
|
||||||
|
# ========= Update Cargo.toml
|
||||||
|
|
||||||
|
things = ""
|
||||||
|
for f in features:
|
||||||
|
name = f["name"].replace("_", "-")
|
||||||
|
for val in f["vals"]:
|
||||||
|
things += f"{name}-{val} = []"
|
||||||
|
if val == f["default"]:
|
||||||
|
things += " # Default"
|
||||||
|
things += "\n"
|
||||||
|
things += "\n"
|
||||||
|
|
||||||
|
SEPARATOR_START = "# BEGIN AUTOGENERATED CONFIG FEATURES\n"
|
||||||
|
SEPARATOR_END = "# END AUTOGENERATED CONFIG FEATURES\n"
|
||||||
|
HELP = "# Generated by gen_config.py. DO NOT EDIT.\n"
|
||||||
|
with open("Cargo.toml", "r") as f:
|
||||||
|
data = f.read()
|
||||||
|
before, data = data.split(SEPARATOR_START, maxsplit=1)
|
||||||
|
_, after = data.split(SEPARATOR_END, maxsplit=1)
|
||||||
|
data = before + SEPARATOR_START + HELP + things + SEPARATOR_END + after
|
||||||
|
with open("Cargo.toml", "w") as f:
|
||||||
|
f.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
# ========= Update build.rs
|
||||||
|
|
||||||
|
things = ""
|
||||||
|
for f in features:
|
||||||
|
name = f["name"].upper()
|
||||||
|
things += f' ("{name}", {f["default"]}),\n'
|
||||||
|
|
||||||
|
SEPARATOR_START = "// BEGIN AUTOGENERATED CONFIG FEATURES\n"
|
||||||
|
SEPARATOR_END = "// END AUTOGENERATED CONFIG FEATURES\n"
|
||||||
|
HELP = " // Generated by gen_config.py. DO NOT EDIT.\n"
|
||||||
|
with open("build.rs", "r") as f:
|
||||||
|
data = f.read()
|
||||||
|
before, data = data.split(SEPARATOR_START, maxsplit=1)
|
||||||
|
_, after = data.split(SEPARATOR_END, maxsplit=1)
|
||||||
|
data = before + SEPARATOR_START + HELP + things + " " + SEPARATOR_END + after
|
||||||
|
with open("build.rs", "w") as f:
|
||||||
|
f.write(data)
|
@ -4,18 +4,14 @@ use core::fmt;
|
|||||||
|
|
||||||
use managed::{ManagedMap, ManagedSlice};
|
use managed::{ManagedMap, ManagedSlice};
|
||||||
|
|
||||||
|
use crate::config::{REASSEMBLY_BUFFER_COUNT, REASSEMBLY_BUFFER_SIZE};
|
||||||
use crate::storage::Assembler;
|
use crate::storage::Assembler;
|
||||||
use crate::time::{Duration, Instant};
|
use crate::time::{Duration, Instant};
|
||||||
|
|
||||||
// TODO: make configurable.
|
|
||||||
const BUFFER_SIZE: usize = 1500;
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
type Buffer = alloc::vec::Vec<u8>;
|
type Buffer = alloc::vec::Vec<u8>;
|
||||||
#[cfg(not(feature = "alloc"))]
|
#[cfg(not(feature = "alloc"))]
|
||||||
type Buffer = [u8; BUFFER_SIZE];
|
type Buffer = [u8; REASSEMBLY_BUFFER_SIZE];
|
||||||
|
|
||||||
const PACKET_ASSEMBLER_COUNT: usize = 4;
|
|
||||||
|
|
||||||
/// Problem when assembling: something was out of bounds.
|
/// Problem when assembling: something was out of bounds.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
@ -44,14 +40,14 @@ pub struct PacketAssembler<K> {
|
|||||||
|
|
||||||
impl<K> PacketAssembler<K> {
|
impl<K> PacketAssembler<K> {
|
||||||
/// Create a new empty buffer for fragments.
|
/// Create a new empty buffer for fragments.
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
key: None,
|
key: None,
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
buffer: Buffer::new(),
|
buffer: Buffer::new(),
|
||||||
#[cfg(not(feature = "alloc"))]
|
#[cfg(not(feature = "alloc"))]
|
||||||
buffer: [0u8; BUFFER_SIZE],
|
buffer: [0u8; REASSEMBLY_BUFFER_SIZE],
|
||||||
|
|
||||||
assembler: Assembler::new(),
|
assembler: Assembler::new(),
|
||||||
total_size: None,
|
total_size: None,
|
||||||
@ -172,20 +168,16 @@ impl<K> PacketAssembler<K> {
|
|||||||
/// Set holding multiple [`PacketAssembler`].
|
/// Set holding multiple [`PacketAssembler`].
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PacketAssemblerSet<K: Eq + Copy> {
|
pub struct PacketAssemblerSet<K: Eq + Copy> {
|
||||||
assemblers: [PacketAssembler<K>; PACKET_ASSEMBLER_COUNT],
|
assemblers: [PacketAssembler<K>; REASSEMBLY_BUFFER_COUNT],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Eq + Copy> PacketAssemblerSet<K> {
|
impl<K: Eq + Copy> PacketAssemblerSet<K> {
|
||||||
|
const NEW_PA: PacketAssembler<K> = PacketAssembler::new();
|
||||||
|
|
||||||
/// Create a new set of packet assemblers.
|
/// Create a new set of packet assemblers.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
// TODO: support any PACKET_ASSEMBLER_COUNT
|
assemblers: [Self::NEW_PA; REASSEMBLY_BUFFER_COUNT],
|
||||||
assemblers: [
|
|
||||||
PacketAssembler::new(),
|
|
||||||
PacketAssembler::new(),
|
|
||||||
PacketAssembler::new(),
|
|
||||||
PacketAssembler::new(),
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,10 +283,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn packet_assembler_set_full() {
|
fn packet_assembler_set_full() {
|
||||||
let mut set = PacketAssemblerSet::new();
|
let mut set = PacketAssemblerSet::new();
|
||||||
set.get(&Key { id: 0 }, Instant::ZERO).unwrap();
|
for i in 0..REASSEMBLY_BUFFER_COUNT {
|
||||||
set.get(&Key { id: 1 }, Instant::ZERO).unwrap();
|
set.get(&Key { id: i }, Instant::ZERO).unwrap();
|
||||||
set.get(&Key { id: 2 }, Instant::ZERO).unwrap();
|
}
|
||||||
set.get(&Key { id: 3 }, Instant::ZERO).unwrap();
|
|
||||||
assert!(set.get(&Key { id: 4 }, Instant::ZERO).is_err());
|
assert!(set.get(&Key { id: 4 }, Instant::ZERO).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,10 @@ use super::fragmentation::PacketAssemblerSet;
|
|||||||
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
|
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
|
||||||
use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
|
use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
|
||||||
use super::socket_set::SocketSet;
|
use super::socket_set::SocketSet;
|
||||||
|
use crate::config::{
|
||||||
|
FRAGMENTATION_BUFFER_SIZE, IFACE_MAX_ADDR_COUNT, IFACE_MAX_MULTICAST_GROUP_COUNT,
|
||||||
|
IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT,
|
||||||
|
};
|
||||||
use crate::iface::Routes;
|
use crate::iface::Routes;
|
||||||
use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
|
use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
|
||||||
use crate::rand::Rand;
|
use crate::rand::Rand;
|
||||||
@ -36,13 +40,6 @@ use crate::socket::*;
|
|||||||
use crate::time::{Duration, Instant};
|
use crate::time::{Duration, Instant};
|
||||||
use crate::wire::*;
|
use crate::wire::*;
|
||||||
|
|
||||||
const MAX_IP_ADDR_COUNT: usize = 5;
|
|
||||||
#[cfg(feature = "proto-igmp")]
|
|
||||||
const MAX_IPV4_MULTICAST_GROUPS: usize = 4;
|
|
||||||
const FRAGMENTATION_BUFFER_SIZE: usize = 1500;
|
|
||||||
#[cfg(feature = "proto-sixlowpan")]
|
|
||||||
const SIXLOWPAN_ADDRESS_CONTEXT_COUNT: usize = 4;
|
|
||||||
|
|
||||||
#[cfg(feature = "_proto-fragmentation")]
|
#[cfg(feature = "_proto-fragmentation")]
|
||||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -248,15 +245,16 @@ pub struct InterfaceInner {
|
|||||||
#[cfg(feature = "proto-ipv4-fragmentation")]
|
#[cfg(feature = "proto-ipv4-fragmentation")]
|
||||||
ipv4_id: u16,
|
ipv4_id: u16,
|
||||||
#[cfg(feature = "proto-sixlowpan")]
|
#[cfg(feature = "proto-sixlowpan")]
|
||||||
sixlowpan_address_context: Vec<SixlowpanAddressContext, SIXLOWPAN_ADDRESS_CONTEXT_COUNT>,
|
sixlowpan_address_context:
|
||||||
|
Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT>,
|
||||||
#[cfg(feature = "proto-sixlowpan-fragmentation")]
|
#[cfg(feature = "proto-sixlowpan-fragmentation")]
|
||||||
tag: u16,
|
tag: u16,
|
||||||
ip_addrs: Vec<IpCidr, MAX_IP_ADDR_COUNT>,
|
ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
any_ip: bool,
|
any_ip: bool,
|
||||||
routes: Routes,
|
routes: Routes,
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
ipv4_multicast_groups: LinearMap<Ipv4Address, (), MAX_IPV4_MULTICAST_GROUPS>,
|
ipv4_multicast_groups: LinearMap<Ipv4Address, (), IFACE_MAX_MULTICAST_GROUP_COUNT>,
|
||||||
/// When to report for (all or) the next multicast group membership via IGMP
|
/// When to report for (all or) the next multicast group membership via IGMP
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
igmp_report_state: IgmpReportState,
|
igmp_report_state: IgmpReportState,
|
||||||
@ -642,7 +640,7 @@ impl Interface {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// This function panics if any of the addresses are not unicast.
|
/// This function panics if any of the addresses are not unicast.
|
||||||
pub fn update_ip_addrs<F: FnOnce(&mut Vec<IpCidr, MAX_IP_ADDR_COUNT>)>(&mut self, f: F) {
|
pub fn update_ip_addrs<F: FnOnce(&mut Vec<IpCidr, IFACE_MAX_ADDR_COUNT>)>(&mut self, f: F) {
|
||||||
f(&mut self.inner.ip_addrs);
|
f(&mut self.inner.ip_addrs);
|
||||||
InterfaceInner::flush_cache(&mut self.inner);
|
InterfaceInner::flush_cache(&mut self.inner);
|
||||||
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
||||||
@ -690,7 +688,7 @@ impl Interface {
|
|||||||
#[cfg(feature = "proto-sixlowpan")]
|
#[cfg(feature = "proto-sixlowpan")]
|
||||||
pub fn sixlowpan_address_context(
|
pub fn sixlowpan_address_context(
|
||||||
&self,
|
&self,
|
||||||
) -> &Vec<SixlowpanAddressContext, SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
) -> &Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||||
&self.inner.sixlowpan_address_context
|
&self.inner.sixlowpan_address_context
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,7 +696,7 @@ impl Interface {
|
|||||||
#[cfg(feature = "proto-sixlowpan")]
|
#[cfg(feature = "proto-sixlowpan")]
|
||||||
pub fn sixlowpan_address_context_mut(
|
pub fn sixlowpan_address_context_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> &mut Vec<SixlowpanAddressContext, SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
) -> &mut Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||||
&mut self.inner.sixlowpan_address_context
|
&mut self.inner.sixlowpan_address_context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,7 +1012,7 @@ fn test_icmpv4_socket() {
|
|||||||
#[cfg(feature = "proto-ipv6")]
|
#[cfg(feature = "proto-ipv6")]
|
||||||
fn test_solicited_node_addrs() {
|
fn test_solicited_node_addrs() {
|
||||||
let (mut iface, _, _device) = create(MEDIUM);
|
let (mut iface, _, _device) = create(MEDIUM);
|
||||||
let mut new_addrs = heapless::Vec::<IpCidr, MAX_IP_ADDR_COUNT>::new();
|
let mut new_addrs = heapless::Vec::<IpCidr, IFACE_MAX_ADDR_COUNT>::new();
|
||||||
new_addrs
|
new_addrs
|
||||||
.push(IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64))
|
.push(IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3,14 +3,10 @@
|
|||||||
|
|
||||||
use heapless::LinearMap;
|
use heapless::LinearMap;
|
||||||
|
|
||||||
|
use crate::config::IFACE_NEIGHBOR_CACHE_COUNT;
|
||||||
use crate::time::{Duration, Instant};
|
use crate::time::{Duration, Instant};
|
||||||
use crate::wire::{HardwareAddress, IpAddress};
|
use crate::wire::{HardwareAddress, IpAddress};
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
pub const NEIGHBOR_CACHE_SIZE: usize = 16;
|
|
||||||
#[cfg(test)]
|
|
||||||
pub const NEIGHBOR_CACHE_SIZE: usize = 3;
|
|
||||||
|
|
||||||
/// A cached neighbor.
|
/// A cached neighbor.
|
||||||
///
|
///
|
||||||
/// A neighbor mapping translates from a protocol address to a hardware address,
|
/// A neighbor mapping translates from a protocol address to a hardware address,
|
||||||
@ -48,7 +44,7 @@ impl Answer {
|
|||||||
/// A neighbor cache backed by a map.
|
/// A neighbor cache backed by a map.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
storage: LinearMap<IpAddress, Neighbor, NEIGHBOR_CACHE_SIZE>,
|
storage: LinearMap<IpAddress, Neighbor, IFACE_NEIGHBOR_CACHE_COUNT>,
|
||||||
silent_until: Instant,
|
silent_until: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
use crate::time::Instant;
|
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
|
|
||||||
|
use crate::config::IFACE_MAX_ROUTE_COUNT;
|
||||||
|
use crate::time::Instant;
|
||||||
use crate::wire::{IpAddress, IpCidr};
|
use crate::wire::{IpAddress, IpCidr};
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
use crate::wire::{Ipv4Address, Ipv4Cidr};
|
use crate::wire::{Ipv4Address, Ipv4Cidr};
|
||||||
#[cfg(feature = "proto-ipv6")]
|
#[cfg(feature = "proto-ipv6")]
|
||||||
use crate::wire::{Ipv6Address, Ipv6Cidr};
|
use crate::wire::{Ipv6Address, Ipv6Cidr};
|
||||||
|
|
||||||
pub const MAX_ROUTE_COUNT: usize = 4;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct RouteTableFull;
|
pub struct RouteTableFull;
|
||||||
@ -58,7 +57,7 @@ impl Route {
|
|||||||
/// A routing table.
|
/// A routing table.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Routes {
|
pub struct Routes {
|
||||||
storage: Vec<Route, MAX_ROUTE_COUNT>,
|
storage: Vec<Route, IFACE_MAX_ROUTE_COUNT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Routes {
|
impl Routes {
|
||||||
@ -70,7 +69,7 @@ impl Routes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the routes of this node.
|
/// Update the routes of this node.
|
||||||
pub fn update<F: FnOnce(&mut Vec<Route, MAX_ROUTE_COUNT>)>(&mut self, f: F) {
|
pub fn update<F: FnOnce(&mut Vec<Route, IFACE_MAX_ROUTE_COUNT>)>(&mut self, f: F) {
|
||||||
f(&mut self.storage);
|
f(&mut self.storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
src/lib.rs
23
src/lib.rs
@ -129,6 +129,29 @@ mod macros;
|
|||||||
mod parsers;
|
mod parsers;
|
||||||
mod rand;
|
mod rand;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod config {
|
||||||
|
#![allow(unused)]
|
||||||
|
pub const ASSEMBLER_MAX_SEGMENT_COUNT: usize = 4;
|
||||||
|
pub const DNS_MAX_NAME_SIZE: usize = 255;
|
||||||
|
pub const DNS_MAX_RESULT_COUNT: usize = 1;
|
||||||
|
pub const DNS_MAX_SERVER_COUNT: usize = 1;
|
||||||
|
pub const FRAGMENTATION_BUFFER_SIZE: usize = 1500;
|
||||||
|
pub const IFACE_MAX_ADDR_COUNT: usize = 8;
|
||||||
|
pub const IFACE_MAX_MULTICAST_GROUP_COUNT: usize = 4;
|
||||||
|
pub const IFACE_MAX_ROUTE_COUNT: usize = 4;
|
||||||
|
pub const IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT: usize = 4;
|
||||||
|
pub const IFACE_NEIGHBOR_CACHE_COUNT: usize = 3;
|
||||||
|
pub const REASSEMBLY_BUFFER_COUNT: usize = 4;
|
||||||
|
pub const REASSEMBLY_BUFFER_SIZE: usize = 1500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
mod config {
|
||||||
|
#![allow(unused)]
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/config.rs"));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "medium-ethernet",
|
feature = "medium-ethernet",
|
||||||
feature = "medium-ip",
|
feature = "medium-ip",
|
||||||
|
@ -4,6 +4,7 @@ use core::task::Waker;
|
|||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
use managed::ManagedSlice;
|
use managed::ManagedSlice;
|
||||||
|
|
||||||
|
use crate::config::{DNS_MAX_NAME_SIZE, DNS_MAX_RESULT_COUNT, DNS_MAX_SERVER_COUNT};
|
||||||
use crate::socket::{Context, PollAt};
|
use crate::socket::{Context, PollAt};
|
||||||
use crate::time::{Duration, Instant};
|
use crate::time::{Duration, Instant};
|
||||||
use crate::wire::dns::{Flags, Opcode, Packet, Question, Rcode, Record, RecordData, Repr, Type};
|
use crate::wire::dns::{Flags, Opcode, Packet, Question, Rcode, Record, RecordData, Repr, Type};
|
||||||
@ -12,12 +13,8 @@ use crate::wire::{self, IpAddress, IpProtocol, IpRepr, UdpRepr};
|
|||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
use super::WakerRegistration;
|
use super::WakerRegistration;
|
||||||
|
|
||||||
pub const MAX_ADDRESS_COUNT: usize = 4;
|
|
||||||
pub const MAX_SERVER_COUNT: usize = 4;
|
|
||||||
|
|
||||||
const DNS_PORT: u16 = 53;
|
const DNS_PORT: u16 = 53;
|
||||||
const MDNS_DNS_PORT: u16 = 5353;
|
const MDNS_DNS_PORT: u16 = 5353;
|
||||||
const MAX_NAME_LEN: usize = 255;
|
|
||||||
const RETRANSMIT_DELAY: Duration = Duration::from_millis(1_000);
|
const RETRANSMIT_DELAY: Duration = Duration::from_millis(1_000);
|
||||||
const MAX_RETRANSMIT_DELAY: Duration = Duration::from_millis(10_000);
|
const MAX_RETRANSMIT_DELAY: Duration = Duration::from_millis(10_000);
|
||||||
const RETRANSMIT_TIMEOUT: Duration = Duration::from_millis(10_000); // Should generally be 2-10 secs
|
const RETRANSMIT_TIMEOUT: Duration = Duration::from_millis(10_000); // Should generally be 2-10 secs
|
||||||
@ -79,7 +76,7 @@ enum State {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PendingQuery {
|
struct PendingQuery {
|
||||||
name: Vec<u8, MAX_NAME_LEN>,
|
name: Vec<u8, DNS_MAX_NAME_SIZE>,
|
||||||
type_: Type,
|
type_: Type,
|
||||||
|
|
||||||
port: u16, // UDP port (src for request, dst for response)
|
port: u16, // UDP port (src for request, dst for response)
|
||||||
@ -102,7 +99,7 @@ pub enum MulticastDns {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CompletedQuery {
|
struct CompletedQuery {
|
||||||
addresses: Vec<IpAddress, MAX_ADDRESS_COUNT>,
|
addresses: Vec<IpAddress, DNS_MAX_RESULT_COUNT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A handle to an in-progress DNS query.
|
/// A handle to an in-progress DNS query.
|
||||||
@ -115,7 +112,7 @@ pub struct QueryHandle(usize);
|
|||||||
/// packet buffers.
|
/// packet buffers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Socket<'a> {
|
pub struct Socket<'a> {
|
||||||
servers: Vec<IpAddress, MAX_SERVER_COUNT>,
|
servers: Vec<IpAddress, DNS_MAX_SERVER_COUNT>,
|
||||||
queries: ManagedSlice<'a, Option<DnsQuery>>,
|
queries: ManagedSlice<'a, Option<DnsQuery>>,
|
||||||
|
|
||||||
/// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
/// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
||||||
@ -216,7 +213,7 @@ impl<'a> Socket<'a> {
|
|||||||
name = &name[..name.len() - 1];
|
name = &name[..name.len() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut raw_name: Vec<u8, MAX_NAME_LEN> = Vec::new();
|
let mut raw_name: Vec<u8, DNS_MAX_NAME_SIZE> = Vec::new();
|
||||||
|
|
||||||
let mut mdns = MulticastDns::Disabled;
|
let mut mdns = MulticastDns::Disabled;
|
||||||
#[cfg(feature = "socket-mdns")]
|
#[cfg(feature = "socket-mdns")]
|
||||||
@ -292,7 +289,7 @@ impl<'a> Socket<'a> {
|
|||||||
pub fn get_query_result(
|
pub fn get_query_result(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: QueryHandle,
|
handle: QueryHandle,
|
||||||
) -> Result<Vec<IpAddress, MAX_ADDRESS_COUNT>, GetQueryResultError> {
|
) -> Result<Vec<IpAddress, DNS_MAX_RESULT_COUNT>, GetQueryResultError> {
|
||||||
let slot = &mut self.queries[handle.0];
|
let slot = &mut self.queries[handle.0];
|
||||||
let q = slot.as_mut().unwrap();
|
let q = slot.as_mut().unwrap();
|
||||||
match &mut q.state {
|
match &mut q.state {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
|
use crate::config::ASSEMBLER_MAX_SEGMENT_COUNT;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct TooManyHolesError;
|
pub struct TooManyHolesError;
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ impl fmt::Display for Contig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Contig {
|
impl Contig {
|
||||||
fn empty() -> Contig {
|
const fn empty() -> Contig {
|
||||||
Contig {
|
Contig {
|
||||||
hole_size: 0,
|
hole_size: 0,
|
||||||
data_size: 0,
|
data_size: 0,
|
||||||
@ -66,24 +68,13 @@ impl Contig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
const CONTIG_COUNT: usize = 32;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "alloc"))]
|
|
||||||
const CONTIG_COUNT: usize = 4;
|
|
||||||
|
|
||||||
/// A buffer (re)assembler.
|
/// A buffer (re)assembler.
|
||||||
///
|
///
|
||||||
/// Currently, up to a hardcoded limit of 4 or 32 holes can be tracked in the buffer.
|
/// Currently, up to a hardcoded limit of 4 or 32 holes can be tracked in the buffer.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct Assembler {
|
pub struct Assembler {
|
||||||
#[cfg(not(feature = "alloc"))]
|
contigs: [Contig; ASSEMBLER_MAX_SEGMENT_COUNT],
|
||||||
contigs: [Contig; CONTIG_COUNT],
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
contigs: Box<[Contig; CONTIG_COUNT]>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Assembler {
|
impl fmt::Display for Assembler {
|
||||||
@ -106,12 +97,11 @@ impl fmt::Display for Assembler {
|
|||||||
|
|
||||||
impl Assembler {
|
impl Assembler {
|
||||||
/// Create a new buffer assembler.
|
/// Create a new buffer assembler.
|
||||||
pub fn new() -> Assembler {
|
pub const fn new() -> Assembler {
|
||||||
#[cfg(not(feature = "alloc"))]
|
const EMPTY: Contig = Contig::empty();
|
||||||
let contigs = [Contig::empty(); CONTIG_COUNT];
|
Assembler {
|
||||||
#[cfg(feature = "alloc")]
|
contigs: [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT],
|
||||||
let contigs = Box::new([Contig::empty(); CONTIG_COUNT]);
|
}
|
||||||
Assembler { contigs }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
@ -355,10 +345,9 @@ mod test {
|
|||||||
|
|
||||||
impl From<Vec<(usize, usize)>> for Assembler {
|
impl From<Vec<(usize, usize)>> for Assembler {
|
||||||
fn from(vec: Vec<(usize, usize)>) -> Assembler {
|
fn from(vec: Vec<(usize, usize)>) -> Assembler {
|
||||||
#[cfg(not(feature = "alloc"))]
|
const EMPTY: Contig = Contig::empty();
|
||||||
let mut contigs = [Contig::empty(); CONTIG_COUNT];
|
|
||||||
#[cfg(feature = "alloc")]
|
let mut contigs = [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT];
|
||||||
let mut contigs = Box::new([Contig::empty(); CONTIG_COUNT]);
|
|
||||||
for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
|
for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
|
||||||
contigs[i] = Contig {
|
contigs[i] = Contig {
|
||||||
hole_size,
|
hole_size,
|
||||||
@ -468,7 +457,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rejected_add_keeps_state() {
|
fn test_rejected_add_keeps_state() {
|
||||||
let mut assr = Assembler::new();
|
let mut assr = Assembler::new();
|
||||||
for c in 1..=CONTIG_COUNT {
|
for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
|
||||||
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
||||||
}
|
}
|
||||||
// Maximum of allowed holes is reached
|
// Maximum of allowed holes is reached
|
||||||
@ -499,12 +488,12 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_boundary_case_remove_front() {
|
fn test_boundary_case_remove_front() {
|
||||||
let mut vec = vec![(1, 1); CONTIG_COUNT];
|
let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
|
||||||
vec[0] = (0, 2);
|
vec[0] = (0, 2);
|
||||||
let mut assr = Assembler::from(vec);
|
let mut assr = Assembler::from(vec);
|
||||||
assert_eq!(assr.remove_front(), 2);
|
assert_eq!(assr.remove_front(), 2);
|
||||||
let mut vec = vec![(1, 1); CONTIG_COUNT];
|
let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
|
||||||
vec[CONTIG_COUNT - 1] = (0, 0);
|
vec[ASSEMBLER_MAX_SEGMENT_COUNT - 1] = (0, 0);
|
||||||
let exp_assr = Assembler::from(vec);
|
let exp_assr = Assembler::from(vec);
|
||||||
assert_eq!(assr, exp_assr);
|
assert_eq!(assr, exp_assr);
|
||||||
}
|
}
|
||||||
@ -648,7 +637,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_add_then_remove_front_at_front_full() {
|
fn test_add_then_remove_front_at_front_full() {
|
||||||
let mut assr = Assembler::new();
|
let mut assr = Assembler::new();
|
||||||
for c in 1..=CONTIG_COUNT {
|
for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
|
||||||
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
||||||
}
|
}
|
||||||
// Maximum of allowed holes is reached
|
// Maximum of allowed holes is reached
|
||||||
@ -660,7 +649,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_add_then_remove_front_at_front_full_offset_0() {
|
fn test_add_then_remove_front_at_front_full_offset_0() {
|
||||||
let mut assr = Assembler::new();
|
let mut assr = Assembler::new();
|
||||||
for c in 1..=CONTIG_COUNT {
|
for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
|
||||||
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
assert_eq!(assr.add(c * 10, 3), Ok(()));
|
||||||
}
|
}
|
||||||
assert_eq!(assr.add_then_remove_front(0, 3), Ok(3));
|
assert_eq!(assr.add_then_remove_front(0, 3), Ok(3));
|
||||||
@ -708,7 +697,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare.
|
// Compare.
|
||||||
let wanted_res = if contigs.len() > CONTIG_COUNT {
|
let wanted_res = if contigs.len() > ASSEMBLER_MAX_SEGMENT_COUNT {
|
||||||
Err(TooManyHolesError)
|
Err(TooManyHolesError)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user