mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-10-02 15:15:05 +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" = []
|
||||
|
||||
# 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]]
|
||||
name = "packet2pcap"
|
||||
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"] }
|
||||
```
|
||||
|
||||
## Feature flags
|
||||
|
||||
### Feature `std`
|
||||
|
||||
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.
|
||||
|
||||
### 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.
|
||||
|
||||
@ -208,6 +210,73 @@ Enable [IPv4] and [IPv6] respectively.
|
||||
[IPv4]: https://tools.ietf.org/rfc/rfc791.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
|
||||
|
||||
_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 crate::config::{REASSEMBLY_BUFFER_COUNT, REASSEMBLY_BUFFER_SIZE};
|
||||
use crate::storage::Assembler;
|
||||
use crate::time::{Duration, Instant};
|
||||
|
||||
// TODO: make configurable.
|
||||
const BUFFER_SIZE: usize = 1500;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
type Buffer = alloc::vec::Vec<u8>;
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
type Buffer = [u8; BUFFER_SIZE];
|
||||
|
||||
const PACKET_ASSEMBLER_COUNT: usize = 4;
|
||||
type Buffer = [u8; REASSEMBLY_BUFFER_SIZE];
|
||||
|
||||
/// Problem when assembling: something was out of bounds.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
@ -44,14 +40,14 @@ pub struct PacketAssembler<K> {
|
||||
|
||||
impl<K> PacketAssembler<K> {
|
||||
/// Create a new empty buffer for fragments.
|
||||
pub fn new() -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
key: None,
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
buffer: Buffer::new(),
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
buffer: [0u8; BUFFER_SIZE],
|
||||
buffer: [0u8; REASSEMBLY_BUFFER_SIZE],
|
||||
|
||||
assembler: Assembler::new(),
|
||||
total_size: None,
|
||||
@ -172,20 +168,16 @@ impl<K> PacketAssembler<K> {
|
||||
/// Set holding multiple [`PacketAssembler`].
|
||||
#[derive(Debug)]
|
||||
pub struct PacketAssemblerSet<K: Eq + Copy> {
|
||||
assemblers: [PacketAssembler<K>; PACKET_ASSEMBLER_COUNT],
|
||||
assemblers: [PacketAssembler<K>; REASSEMBLY_BUFFER_COUNT],
|
||||
}
|
||||
|
||||
impl<K: Eq + Copy> PacketAssemblerSet<K> {
|
||||
const NEW_PA: PacketAssembler<K> = PacketAssembler::new();
|
||||
|
||||
/// Create a new set of packet assemblers.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
// TODO: support any PACKET_ASSEMBLER_COUNT
|
||||
assemblers: [
|
||||
PacketAssembler::new(),
|
||||
PacketAssembler::new(),
|
||||
PacketAssembler::new(),
|
||||
PacketAssembler::new(),
|
||||
],
|
||||
assemblers: [Self::NEW_PA; REASSEMBLY_BUFFER_COUNT],
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,10 +283,9 @@ mod tests {
|
||||
#[test]
|
||||
fn packet_assembler_set_full() {
|
||||
let mut set = PacketAssemblerSet::new();
|
||||
set.get(&Key { id: 0 }, Instant::ZERO).unwrap();
|
||||
set.get(&Key { id: 1 }, Instant::ZERO).unwrap();
|
||||
set.get(&Key { id: 2 }, Instant::ZERO).unwrap();
|
||||
set.get(&Key { id: 3 }, Instant::ZERO).unwrap();
|
||||
for i in 0..REASSEMBLY_BUFFER_COUNT {
|
||||
set.get(&Key { id: i }, Instant::ZERO).unwrap();
|
||||
}
|
||||
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"))]
|
||||
use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
|
||||
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::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
|
||||
use crate::rand::Rand;
|
||||
@ -36,13 +40,6 @@ use crate::socket::*;
|
||||
use crate::time::{Duration, Instant};
|
||||
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")]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -248,15 +245,16 @@ pub struct InterfaceInner {
|
||||
#[cfg(feature = "proto-ipv4-fragmentation")]
|
||||
ipv4_id: u16,
|
||||
#[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")]
|
||||
tag: u16,
|
||||
ip_addrs: Vec<IpCidr, MAX_IP_ADDR_COUNT>,
|
||||
ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
any_ip: bool,
|
||||
routes: Routes,
|
||||
#[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
|
||||
#[cfg(feature = "proto-igmp")]
|
||||
igmp_report_state: IgmpReportState,
|
||||
@ -642,7 +640,7 @@ impl Interface {
|
||||
///
|
||||
/// # Panics
|
||||
/// 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);
|
||||
InterfaceInner::flush_cache(&mut self.inner);
|
||||
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
||||
@ -690,7 +688,7 @@ impl Interface {
|
||||
#[cfg(feature = "proto-sixlowpan")]
|
||||
pub fn sixlowpan_address_context(
|
||||
&self,
|
||||
) -> &Vec<SixlowpanAddressContext, SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||
) -> &Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||
&self.inner.sixlowpan_address_context
|
||||
}
|
||||
|
||||
@ -698,7 +696,7 @@ impl Interface {
|
||||
#[cfg(feature = "proto-sixlowpan")]
|
||||
pub fn sixlowpan_address_context_mut(
|
||||
&mut self,
|
||||
) -> &mut Vec<SixlowpanAddressContext, SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||
) -> &mut Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT> {
|
||||
&mut self.inner.sixlowpan_address_context
|
||||
}
|
||||
|
||||
|
@ -1012,7 +1012,7 @@ fn test_icmpv4_socket() {
|
||||
#[cfg(feature = "proto-ipv6")]
|
||||
fn test_solicited_node_addrs() {
|
||||
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
|
||||
.push(IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64))
|
||||
.unwrap();
|
||||
|
@ -3,14 +3,10 @@
|
||||
|
||||
use heapless::LinearMap;
|
||||
|
||||
use crate::config::IFACE_NEIGHBOR_CACHE_COUNT;
|
||||
use crate::time::{Duration, Instant};
|
||||
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 neighbor mapping translates from a protocol address to a hardware address,
|
||||
@ -48,7 +44,7 @@ impl Answer {
|
||||
/// A neighbor cache backed by a map.
|
||||
#[derive(Debug)]
|
||||
pub struct Cache {
|
||||
storage: LinearMap<IpAddress, Neighbor, NEIGHBOR_CACHE_SIZE>,
|
||||
storage: LinearMap<IpAddress, Neighbor, IFACE_NEIGHBOR_CACHE_COUNT>,
|
||||
silent_until: Instant,
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
use crate::time::Instant;
|
||||
use heapless::Vec;
|
||||
|
||||
use crate::config::IFACE_MAX_ROUTE_COUNT;
|
||||
use crate::time::Instant;
|
||||
use crate::wire::{IpAddress, IpCidr};
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
use crate::wire::{Ipv4Address, Ipv4Cidr};
|
||||
#[cfg(feature = "proto-ipv6")]
|
||||
use crate::wire::{Ipv6Address, Ipv6Cidr};
|
||||
|
||||
pub const MAX_ROUTE_COUNT: usize = 4;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct RouteTableFull;
|
||||
@ -58,7 +57,7 @@ impl Route {
|
||||
/// A routing table.
|
||||
#[derive(Debug)]
|
||||
pub struct Routes {
|
||||
storage: Vec<Route, MAX_ROUTE_COUNT>,
|
||||
storage: Vec<Route, IFACE_MAX_ROUTE_COUNT>,
|
||||
}
|
||||
|
||||
impl Routes {
|
||||
@ -70,7 +69,7 @@ impl Routes {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
23
src/lib.rs
23
src/lib.rs
@ -129,6 +129,29 @@ mod macros;
|
||||
mod parsers;
|
||||
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(
|
||||
feature = "medium-ethernet",
|
||||
feature = "medium-ip",
|
||||
|
@ -4,6 +4,7 @@ use core::task::Waker;
|
||||
use heapless::Vec;
|
||||
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::time::{Duration, Instant};
|
||||
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")]
|
||||
use super::WakerRegistration;
|
||||
|
||||
pub const MAX_ADDRESS_COUNT: usize = 4;
|
||||
pub const MAX_SERVER_COUNT: usize = 4;
|
||||
|
||||
const DNS_PORT: u16 = 53;
|
||||
const MDNS_DNS_PORT: u16 = 5353;
|
||||
const MAX_NAME_LEN: usize = 255;
|
||||
const RETRANSMIT_DELAY: Duration = Duration::from_millis(1_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
|
||||
@ -79,7 +76,7 @@ enum State {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PendingQuery {
|
||||
name: Vec<u8, MAX_NAME_LEN>,
|
||||
name: Vec<u8, DNS_MAX_NAME_SIZE>,
|
||||
type_: Type,
|
||||
|
||||
port: u16, // UDP port (src for request, dst for response)
|
||||
@ -102,7 +99,7 @@ pub enum MulticastDns {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CompletedQuery {
|
||||
addresses: Vec<IpAddress, MAX_ADDRESS_COUNT>,
|
||||
addresses: Vec<IpAddress, DNS_MAX_RESULT_COUNT>,
|
||||
}
|
||||
|
||||
/// A handle to an in-progress DNS query.
|
||||
@ -115,7 +112,7 @@ pub struct QueryHandle(usize);
|
||||
/// packet buffers.
|
||||
#[derive(Debug)]
|
||||
pub struct Socket<'a> {
|
||||
servers: Vec<IpAddress, MAX_SERVER_COUNT>,
|
||||
servers: Vec<IpAddress, DNS_MAX_SERVER_COUNT>,
|
||||
queries: ManagedSlice<'a, Option<DnsQuery>>,
|
||||
|
||||
/// 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];
|
||||
}
|
||||
|
||||
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;
|
||||
#[cfg(feature = "socket-mdns")]
|
||||
@ -292,7 +289,7 @@ impl<'a> Socket<'a> {
|
||||
pub fn get_query_result(
|
||||
&mut self,
|
||||
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 q = slot.as_mut().unwrap();
|
||||
match &mut q.state {
|
||||
|
@ -1,5 +1,7 @@
|
||||
use core::fmt;
|
||||
|
||||
use crate::config::ASSEMBLER_MAX_SEGMENT_COUNT;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct TooManyHolesError;
|
||||
|
||||
@ -27,7 +29,7 @@ impl fmt::Display for Contig {
|
||||
}
|
||||
|
||||
impl Contig {
|
||||
fn empty() -> Contig {
|
||||
const fn empty() -> Contig {
|
||||
Contig {
|
||||
hole_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.
|
||||
///
|
||||
/// Currently, up to a hardcoded limit of 4 or 32 holes can be tracked in the buffer.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct Assembler {
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
contigs: [Contig; CONTIG_COUNT],
|
||||
#[cfg(feature = "alloc")]
|
||||
contigs: Box<[Contig; CONTIG_COUNT]>,
|
||||
contigs: [Contig; ASSEMBLER_MAX_SEGMENT_COUNT],
|
||||
}
|
||||
|
||||
impl fmt::Display for Assembler {
|
||||
@ -106,12 +97,11 @@ impl fmt::Display for Assembler {
|
||||
|
||||
impl Assembler {
|
||||
/// Create a new buffer assembler.
|
||||
pub fn new() -> Assembler {
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
let contigs = [Contig::empty(); CONTIG_COUNT];
|
||||
#[cfg(feature = "alloc")]
|
||||
let contigs = Box::new([Contig::empty(); CONTIG_COUNT]);
|
||||
Assembler { contigs }
|
||||
pub const fn new() -> Assembler {
|
||||
const EMPTY: Contig = Contig::empty();
|
||||
Assembler {
|
||||
contigs: [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
@ -355,10 +345,9 @@ mod test {
|
||||
|
||||
impl From<Vec<(usize, usize)>> for Assembler {
|
||||
fn from(vec: Vec<(usize, usize)>) -> Assembler {
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
let mut contigs = [Contig::empty(); CONTIG_COUNT];
|
||||
#[cfg(feature = "alloc")]
|
||||
let mut contigs = Box::new([Contig::empty(); CONTIG_COUNT]);
|
||||
const EMPTY: Contig = Contig::empty();
|
||||
|
||||
let mut contigs = [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT];
|
||||
for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
|
||||
contigs[i] = Contig {
|
||||
hole_size,
|
||||
@ -468,7 +457,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_rejected_add_keeps_state() {
|
||||
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(()));
|
||||
}
|
||||
// Maximum of allowed holes is reached
|
||||
@ -499,12 +488,12 @@ mod test {
|
||||
|
||||
#[test]
|
||||
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);
|
||||
let mut assr = Assembler::from(vec);
|
||||
assert_eq!(assr.remove_front(), 2);
|
||||
let mut vec = vec![(1, 1); CONTIG_COUNT];
|
||||
vec[CONTIG_COUNT - 1] = (0, 0);
|
||||
let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
|
||||
vec[ASSEMBLER_MAX_SEGMENT_COUNT - 1] = (0, 0);
|
||||
let exp_assr = Assembler::from(vec);
|
||||
assert_eq!(assr, exp_assr);
|
||||
}
|
||||
@ -648,7 +637,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_add_then_remove_front_at_front_full() {
|
||||
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(()));
|
||||
}
|
||||
// Maximum of allowed holes is reached
|
||||
@ -660,7 +649,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_add_then_remove_front_at_front_full_offset_0() {
|
||||
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_then_remove_front(0, 3), Ok(3));
|
||||
@ -708,7 +697,7 @@ mod test {
|
||||
}
|
||||
|
||||
// Compare.
|
||||
let wanted_res = if contigs.len() > CONTIG_COUNT {
|
||||
let wanted_res = if contigs.len() > ASSEMBLER_MAX_SEGMENT_COUNT {
|
||||
Err(TooManyHolesError)
|
||||
} else {
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user