Change default UDP port to 2121 and EtherType to 0x2121

Update the default UDP bind port from 4000 to 2121 (decimal) and the
default Ethernet EtherType from 0x88B5 to 0x2121 across all source
code, documentation, configuration templates, test fixtures, and
scripts. Remove references to "IEEE 802 experimental range" since
0x2121 is not in that range.
This commit is contained in:
Johnathan Corgan
2026-02-26 13:22:09 +00:00
parent e0fa69e0b9
commit daf1e629df
18 changed files with 67 additions and 67 deletions

View File

@@ -89,12 +89,12 @@ node: # node:
nsec: "nsec1aaa..." # nsec: "nsec1bbb..."
transports: # transports:
udp: # udp:
bind_addr: "0.0.0.0:4000" # bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121" # bind_addr: "0.0.0.0:2121"
peers: # peers:
- npub: "npub1bbb..." # - npub: "npub1aaa..."
addresses: # addresses:
- transport: udp # - transport: udp
addr: "10.0.0.2:4000" # addr: "10.0.0.1:4000"
addr: "10.0.0.2:2121" # addr: "10.0.0.1:2121"
```
The `nsec` field accepts bech32 (`nsec1...`) or hex-encoded secret keys.

View File

@@ -243,7 +243,7 @@ stale address mappings.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `transports.udp.bind_addr` | string | `"0.0.0.0:4000"` | UDP bind address and port |
| `transports.udp.bind_addr` | string | `"0.0.0.0:2121"` | UDP bind address and port |
| `transports.udp.mtu` | u16 | `1280` | Transport MTU |
| `transports.udp.recv_buf_size` | usize | `2097152` | UDP socket receive buffer size in bytes (2 MB). Linux kernel doubles the requested value internally. Host `net.core.rmem_max` must be >= this value. |
| `transports.udp.send_buf_size` | usize | `2097152` | UDP socket send buffer size in bytes (2 MB). Host `net.core.wmem_max` must be >= this value. |
@@ -256,7 +256,7 @@ Requires `CAP_NET_RAW` or running as root. Linux only.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `interface` | string | *(required)* | Network interface name (e.g., `"eth0"`, `"enp3s0"`) |
| `ethertype` | u16 | `0x88B5` | IEEE EtherType (802 experimental range) |
| `ethertype` | u16 | `0x2121` | EtherType |
| `mtu` | u16 | *(auto)* | Override MTU. Default: interface MTU minus 1 (for frame type prefix) |
| `recv_buf_size` | usize | `2097152` | Socket receive buffer size in bytes (2 MB) |
| `send_buf_size` | usize | `2097152` | Socket send buffer size in bytes (2 MB) |
@@ -320,7 +320,7 @@ dns:
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1472
peers:
@@ -328,7 +328,7 @@ peers:
alias: "node-b"
addresses:
- transport: udp
addr: "172.20.0.11:4000"
addr: "172.20.0.11:2121"
connect_policy: auto_connect
```
@@ -347,7 +347,7 @@ tun:
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1472
ethernet:
interface: "eth0"
@@ -361,7 +361,7 @@ peers:
alias: "internet-peer"
addresses:
- transport: udp
addr: "203.0.113.5:4000"
addr: "203.0.113.5:2121"
connect_policy: auto_connect
```
@@ -468,13 +468,13 @@ dns:
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1280
recv_buf_size: 2097152 # 2 MB (kernel doubles to 4 MB actual)
send_buf_size: 2097152 # 2 MB
# ethernet: # uncomment to enable (requires CAP_NET_RAW)
# interface: "eth0" # required: network interface name
# ethertype: 0x88B5 # IEEE 802 experimental EtherType
# ethertype: 0x2121 # default EtherType
# mtu: null # null = interface MTU - 1 (typically 1499)
# recv_buf_size: 2097152 # 2 MB
# send_buf_size: 2097152 # 2 MB
@@ -489,7 +489,7 @@ peers: # static peer list
# alias: "node-b"
# addresses:
# - transport: udp
# addr: "10.0.0.2:4000"
# addr: "10.0.0.2:2121"
# priority: 100
# connect_policy: auto_connect
# auto_reconnect: true # reconnect after link-dead removal

View File

@@ -239,7 +239,7 @@ sysctl net.core.rmem_max net.core.wmem_max
Actual buffer sizes are logged at startup:
```text
UDP transport started local_addr=0.0.0.0:4000 recv_buf=4194304 send_buf=4194304
UDP transport started local_addr=0.0.0.0:2121 recv_buf=4194304 send_buf=4194304
```
## Ethernet: The Local Network Transport
@@ -261,7 +261,7 @@ UDP (1500 vs 1472 MTU).
### Implementation
The Ethernet transport uses Linux AF_PACKET sockets in SOCK_DGRAM mode with
EtherType 0x88B5 (IEEE 802 experimental/local use range). SOCK_DGRAM mode
EtherType 0x2121. SOCK_DGRAM mode
lets the kernel handle Ethernet header construction and parsing — the
transport deals only with payloads and MAC addresses.
@@ -271,7 +271,7 @@ beacons and data to share the same EtherType and socket.
| Property | Value |
| -------- | ----- |
| EtherType | 0x88B5 (IEEE 802 experimental) |
| EtherType | 0x2121 |
| Socket type | AF_PACKET SOCK_DGRAM |
| Frame type prefix | 0x00 = data, 0x01 = beacon |
| Effective MTU | Interface MTU - 1 (typically 1499) |
@@ -450,7 +450,7 @@ transitions through `Starting` to `Up` (operational). `stop()` moves to
| --------- | ------ | ----- |
| UDP/IP | **Implemented** | Primary transport, async send/receive, configurable MTU |
| TCP/IP | Future direction | Requires stream framing, TCP-over-TCP concern |
| Ethernet | **Implemented** | AF_PACKET SOCK_DGRAM, EtherType 0x88B5, beacon discovery, Linux only |
| Ethernet | **Implemented** | AF_PACKET SOCK_DGRAM, EtherType 0x2121, beacon discovery, Linux only |
| WiFi | Future direction | Infrastructure mode = Ethernet driver |
| Tor | Future direction | High latency, .onion addressing |
| BLE | Future direction | ATT_MTU negotiation, per-link MTU |

View File

@@ -460,7 +460,7 @@ node:
let yaml = r#"
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1400
"#;
let config: Config = serde_yaml::from_str(yaml).unwrap();
@@ -469,7 +469,7 @@ transports:
let instances: Vec<_> = config.transports.udp.iter().collect();
assert_eq!(instances.len(), 1);
assert_eq!(instances[0].0, None); // Single instance has no name
assert_eq!(instances[0].1.bind_addr(), "0.0.0.0:4000");
assert_eq!(instances[0].1.bind_addr(), "0.0.0.0:2121");
assert_eq!(instances[0].1.mtu(), 1400);
}
@@ -479,9 +479,9 @@ transports:
transports:
udp:
main:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
backup:
bind_addr: "192.168.1.100:4001"
bind_addr: "192.168.1.100:2122"
mtu: 1280
"#;
let config: Config = serde_yaml::from_str(yaml).unwrap();
@@ -494,8 +494,8 @@ transports:
// Named instances have Some(name)
assert!(instances.contains_key(&Some("main")));
assert!(instances.contains_key(&Some("backup")));
assert_eq!(instances[&Some("main")].bind_addr(), "0.0.0.0:4000");
assert_eq!(instances[&Some("backup")].bind_addr(), "192.168.1.100:4001");
assert_eq!(instances[&Some("main")].bind_addr(), "0.0.0.0:2121");
assert_eq!(instances[&Some("backup")].bind_addr(), "192.168.1.100:2122");
assert_eq!(instances[&Some("backup")].mtu(), 1280);
}
@@ -513,7 +513,7 @@ transports: {}
fn test_transport_instances_iter() {
// Single instance - no name
let single = TransportInstances::Single(UdpConfig {
bind_addr: Some("0.0.0.0:4000".to_string()),
bind_addr: Some("0.0.0.0:2121".to_string()),
mtu: None,
..Default::default()
});
@@ -540,10 +540,10 @@ peers:
alias: "gateway"
addresses:
- transport: udp
addr: "192.168.1.1:4000"
addr: "192.168.1.1:2121"
priority: 1
- transport: tor
addr: "xyz.onion:4000"
addr: "xyz.onion:2121"
priority: 2
connect_policy: auto_connect
"#;
@@ -571,7 +571,7 @@ peers:
- npub: "npub1xyz"
addresses:
- transport: udp
addr: "10.0.0.1:4000"
addr: "10.0.0.1:2121"
"#;
let config: Config = serde_yaml::from_str(yaml).unwrap();
@@ -592,11 +592,11 @@ peers:
- npub: "npub1peer1"
addresses:
- transport: udp
addr: "10.0.0.1:4000"
addr: "10.0.0.1:2121"
- npub: "npub1peer2"
addresses:
- transport: udp
addr: "10.0.0.2:4000"
addr: "10.0.0.2:2121"
connect_policy: on_demand
"#;
let config: Config = serde_yaml::from_str(yaml).unwrap();
@@ -607,9 +607,9 @@ peers:
#[test]
fn test_peer_config_builder() {
let peer = PeerConfig::new("npub1test", "udp", "192.168.1.1:4000")
let peer = PeerConfig::new("npub1test", "udp", "192.168.1.1:2121")
.with_alias("test-peer")
.with_address(PeerAddress::with_priority("tor", "xyz.onion:4000", 50));
.with_address(PeerAddress::with_priority("tor", "xyz.onion:2121", 50));
assert_eq!(peer.npub, "npub1test");
assert_eq!(peer.alias, Some("test-peer".to_string()));

View File

@@ -35,8 +35,8 @@ pub struct PeerAddress {
/// Transport-specific address string.
///
/// Format depends on transport type:
/// - UDP: "host:port" (e.g., "192.168.1.1:4000")
/// - Tor: "onion_address:port" (e.g., "xyz...abc.onion:4000")
/// - UDP: "host:port" (e.g., "192.168.1.1:2121")
/// - Tor: "onion_address:port" (e.g., "xyz...abc.onion:2121")
/// - Ethernet: "interface/mac" (future)
pub addr: String,

View File

@@ -8,7 +8,7 @@ use std::collections::HashMap;
use serde::{Deserialize, Serialize};
/// Default UDP bind address.
const DEFAULT_UDP_BIND_ADDR: &str = "0.0.0.0:4000";
const DEFAULT_UDP_BIND_ADDR: &str = "0.0.0.0:2121";
/// Default UDP MTU (IPv6 minimum).
const DEFAULT_UDP_MTU: u16 = 1280;
@@ -23,7 +23,7 @@ const DEFAULT_UDP_SEND_BUF: usize = 2 * 1024 * 1024;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct UdpConfig {
/// Bind address (`bind_addr`). Defaults to "0.0.0.0:4000".
/// Bind address (`bind_addr`). Defaults to "0.0.0.0:2121".
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bind_addr: Option<String>,
@@ -68,7 +68,7 @@ impl UdpConfig {
/// ```yaml
/// transports:
/// udp:
/// bind_addr: "0.0.0.0:4000"
/// bind_addr: "0.0.0.0:2121"
/// ```
///
/// And multiple named instances:
@@ -76,9 +76,9 @@ impl UdpConfig {
/// transports:
/// udp:
/// main:
/// bind_addr: "0.0.0.0:4000"
/// bind_addr: "0.0.0.0:2121"
/// backup:
/// bind_addr: "192.168.1.100:4001"
/// bind_addr: "192.168.1.100:2122"
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
@@ -131,8 +131,8 @@ impl<T> Default for TransportInstances<T> {
}
}
/// Default Ethernet EtherType (IEEE 802 experimental).
const DEFAULT_ETHERNET_ETHERTYPE: u16 = 0x88B5;
/// Default Ethernet EtherType (FIPS default).
const DEFAULT_ETHERNET_ETHERTYPE: u16 = 0x2121;
/// Default Ethernet receive buffer size (2 MB).
const DEFAULT_ETHERNET_RECV_BUF: usize = 2 * 1024 * 1024;
@@ -156,7 +156,7 @@ pub struct EthernetConfig {
/// Network interface name (e.g., "eth0", "enp3s0"). Required.
pub interface: String,
/// Custom EtherType (default: 0x88B5).
/// Custom EtherType (default: 0x2121).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ethertype: Option<u16>,

View File

@@ -601,7 +601,7 @@ async fn test_stale_connection_cleanup() {
let transport_id = TransportId::new(1);
let peer_identity = make_peer_identity();
let remote_addr = TransportAddr::from_string("10.0.0.2:4000");
let remote_addr = TransportAddr::from_string("10.0.0.2:2121");
// Create outbound connection with a timestamp far in the past
let past_time_ms = 1000; // A very early timestamp
@@ -653,7 +653,7 @@ async fn test_failed_connection_cleanup() {
let transport_id = TransportId::new(1);
let peer_identity = make_peer_identity();
let remote_addr = TransportAddr::from_string("10.0.0.2:4000");
let remote_addr = TransportAddr::from_string("10.0.0.2:2121");
// Create a connection and mark it failed (simulating a send failure)
let now_ms = std::time::SystemTime::now()
@@ -699,7 +699,7 @@ async fn test_msg1_stored_for_resend() {
let transport_id = TransportId::new(1);
let peer_identity = make_peer_identity();
let remote_addr = TransportAddr::from_string("10.0.0.2:4000");
let remote_addr = TransportAddr::from_string("10.0.0.2:2121");
let now_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
@@ -733,7 +733,7 @@ async fn test_resend_scheduling() {
let transport_id = TransportId::new(1);
let peer_identity = make_peer_identity();
let remote_addr = TransportAddr::from_string("10.0.0.2:4000");
let remote_addr = TransportAddr::from_string("10.0.0.2:2121");
let now_ms = 100_000u64; // Use a fixed time for predictable testing
let link_id = node.allocate_link_id();
@@ -832,7 +832,7 @@ async fn test_duplicate_msg2_dropped() {
let packet = ReceivedPacket {
transport_id,
remote_addr: TransportAddr::from_string("10.0.0.2:4000"),
remote_addr: TransportAddr::from_string("10.0.0.2:2121"),
data: wire_msg2,
timestamp_ms: 1000,
};

View File

@@ -455,7 +455,7 @@ fn test_promote_cleans_up_pending_outbound_to_same_peer() {
let pending_index = node.index_allocator.allocate().unwrap();
pending_conn.set_our_index(pending_index);
pending_conn.set_transport_id(transport_id);
let pending_addr = TransportAddr::from_string("10.0.0.2:4000");
let pending_addr = TransportAddr::from_string("10.0.0.2:2121");
pending_conn.set_source_addr(pending_addr.clone());
let pending_link = Link::connectionless(
@@ -561,7 +561,7 @@ fn test_schedule_retry_creates_entry() {
config.peers.push(crate::config::PeerConfig::new(
peer_npub,
"udp",
"10.0.0.2:4000",
"10.0.0.2:2121",
));
let mut node = Node::new(config).unwrap();
@@ -589,7 +589,7 @@ fn test_schedule_retry_increments() {
config.peers.push(crate::config::PeerConfig::new(
peer_npub,
"udp",
"10.0.0.2:4000",
"10.0.0.2:2121",
));
let mut node = Node::new(config).unwrap();
@@ -618,7 +618,7 @@ fn test_schedule_retry_max_retries_exhausted() {
config.peers.push(crate::config::PeerConfig::new(
peer_npub,
"udp",
"10.0.0.2:4000",
"10.0.0.2:2121",
));
let mut node = Node::new(config).unwrap();
@@ -650,7 +650,7 @@ fn test_schedule_retry_disabled() {
config.peers.push(crate::config::PeerConfig::new(
peer_npub,
"udp",
"10.0.0.2:4000",
"10.0.0.2:2121",
));
let mut node = Node::new(config).unwrap();

View File

@@ -568,7 +568,7 @@ mod tests {
let addr = TransportAddr::from_bytes(&[0xaa, 0xbb, 0xcc]);
assert!(parse_mac_addr(&addr).is_err());
let addr = TransportAddr::from_string("192.168.1.1:4000");
let addr = TransportAddr::from_string("192.168.1.1:2121");
assert!(parse_mac_addr(&addr).is_err());
}

View File

@@ -997,9 +997,9 @@ mod tests {
#[test]
fn test_transport_addr_string() {
let addr = TransportAddr::from_string("192.168.1.1:4000");
assert_eq!(format!("{}", addr), "192.168.1.1:4000");
assert_eq!(addr.as_str(), Some("192.168.1.1:4000"));
let addr = TransportAddr::from_string("192.168.1.1:2121");
assert_eq!(format!("{}", addr), "192.168.1.1:2121");
assert_eq!(addr.as_str(), Some("192.168.1.1:2121"));
}
#[test]
@@ -1152,7 +1152,7 @@ mod tests {
fn test_discovered_peer() {
let peer = DiscoveredPeer::new(
TransportId::new(1),
TransportAddr::from_string("192.168.1.1:4000"),
TransportAddr::from_string("192.168.1.1:2121"),
);
assert_eq!(peer.transport_id, TransportId::new(1));
@@ -1175,7 +1175,7 @@ mod tests {
fn test_received_packet() {
let packet = ReceivedPacket::new(
TransportId::new(1),
TransportAddr::from_string("192.168.1.1:4000"),
TransportAddr::from_string("192.168.1.1:2121"),
vec![1, 2, 3, 4],
);
@@ -1314,7 +1314,7 @@ mod tests {
#[test]
fn test_link_mtu_default_falls_back_to_mtu() {
let transport = MockTransport::new(1280);
let addr = TransportAddr::from_string("192.168.1.1:4000");
let addr = TransportAddr::from_string("192.168.1.1:2121");
// Default link_mtu() should return the transport-wide mtu()
assert_eq!(transport.link_mtu(&addr), 1280);
@@ -1327,7 +1327,7 @@ mod tests {
#[test]
fn test_link_mtu_per_link_override() {
let addr_a = TransportAddr::from_string("192.168.1.1:4000");
let addr_a = TransportAddr::from_string("192.168.1.1:2121");
let addr_b = TransportAddr::from_string("10.0.0.1:5000");
let addr_unknown = TransportAddr::from_string("172.16.0.1:6000");
@@ -1356,7 +1356,7 @@ mod tests {
let transport = UdpTransport::new(TransportId::new(1), None, config, tx);
let handle = TransportHandle::Udp(transport);
let addr = TransportAddr::from_string("192.168.1.1:4000");
let addr = TransportAddr::from_string("192.168.1.1:2121");
// TransportHandle::link_mtu() should delegate and return the same
// as TransportHandle::mtu() for UDP (no per-link overrides)

View File

@@ -544,9 +544,9 @@ mod tests {
#[test]
fn test_parse_socket_addr() {
let addr = TransportAddr::from_string("192.168.1.1:4000");
let addr = TransportAddr::from_string("192.168.1.1:2121");
let result = parse_socket_addr(&addr).unwrap();
assert_eq!(result.to_string(), "192.168.1.1:4000");
assert_eq!(result.to_string(), "192.168.1.1:2121");
let invalid = TransportAddr::from_string("not_an_address");
assert!(parse_socket_addr(&invalid).is_err());

View File

@@ -17,7 +17,7 @@ dns:
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1472
# recv_buf_size: 2097152 # 2 MB (default)
# send_buf_size: 2097152 # 2 MB (default)

View File

@@ -49,7 +49,7 @@ def generate_peers_block(
lines.append(f' alias: "{peer_id}"')
lines.append(f" addresses:")
lines.append(f" - transport: udp")
lines.append(f' addr: "{peer.docker_ip}:4000"')
lines.append(f' addr: "{peer.docker_ip}:2121"')
lines.append(f" connect_policy: auto_connect")
return "\n".join(lines)

View File

@@ -306,7 +306,7 @@ removing rules first.
- **Capabilities**: `CAP_NET_ADMIN` (for TUN device creation)
- **Devices**: `/dev/net/tun` mapped into each container
- **DNS**: FIPS built-in resolver on `127.0.0.1:53`
- **Transport**: UDP on port 4000, MTU 1472
- **Transport**: UDP on port 2121, MTU 1472
- **TUN**: `fips0` interface, MTU 1280
Each node resolves `<npub>.fips` DNS names to FIPS IPv6 addresses via its

View File

@@ -17,7 +17,7 @@ dns:
transports:
udp:
bind_addr: "0.0.0.0:4000"
bind_addr: "0.0.0.0:2121"
mtu: 1472
# recv_buf_size: 2097152 # 2 MB (default)
# send_buf_size: 2097152 # 2 MB (default)

View File

@@ -101,7 +101,7 @@
<rect x="30" y="260" width="640" height="120" class="legend-box"/>
<line x1="50" y1="282" x2="90" y2="282" stroke="#506090" stroke-width="2"/>
<text x="100" y="286" class="legend">Direct UDP peer link (port 4000, auto_connect)</text>
<text x="100" y="286" class="legend">Direct UDP peer link (port 2121, auto_connect)</text>
<line x1="50" y1="304" x2="90" y2="304" stroke="#d0a040" stroke-width="1.2"
stroke-dasharray="5 3" marker-end="url(#arrow)"/>

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -117,7 +117,7 @@
<rect x="40" y="410" width="620" height="130" class="legend-box"/>
<line x1="60" y1="435" x2="100" y2="435" stroke="#404860" stroke-width="1.5"/>
<text x="110" y="439" class="legend">UDP peer link (port 4000, auto_connect)</text>
<text x="110" y="439" class="legend">UDP peer link (port 2121, auto_connect)</text>
<line x1="55" y1="457" x2="100" y2="457" stroke="#60a0e0" stroke-width="2"/>
<path d="M 90 454 L 100 457 L 90 460 z" fill="#60a0e0"/>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -89,7 +89,7 @@ generate_peer_block() {
alias: "node-$peer_id"
addresses:
- transport: udp
addr: "$peer_ip:4000"
addr: "$peer_ip:2121"
connect_policy: auto_connect
EOF
}