Files
fanyang 09cd15725e perf(udp): add GSO batch send via quinn-udp for UDP tunnel
Replace per-packet socket.send_to() with batch drain + GSO sendmsg
in forward_from_ring_to_udp. Uses quinn-udp's UdpSocketState to
leverage UDP_SEGMENT (GSO) when the kernel supports it.

Architecture:
  1. Await first packet from RingStream
  2. Non-blocking drain up to 8 more packets (noop_waker poll_next)
  3. If all same size + GSO supported: concatenate + single sendmsg
     with UDP_SEGMENT → kernel splits into N UDP datagrams
  4. Otherwise: fallback to per-packet send

Feature gated behind 'udp-gso' (enabled in default features).
Falls back to per-packet send on older kernels (no GSO support).

Benchmark (localhost, no hotpath):
  Before GSO: 1,066K pps
  After GSO:  1,070K pps (noise — localhost has no NIC driver overhead)

GSO will have larger impact on real WAN interfaces where syscall
overhead dominates. Implementation is correct and ready for that.

All 208 peers tests pass. 6 netns tests fail (require root, unchanged).
2026-06-29 03:24:55 +08:00

423 lines
10 KiB
TOML

[package]
name = "easytier"
description = "A full meshed p2p VPN, connecting all your devices in one network with one command."
homepage = "https://github.com/EasyTier/EasyTier"
repository = "https://github.com/EasyTier/EasyTier"
version = "2.6.4"
edition.workspace = true
rust-version.workspace = true
authors = ["kkrainbow"]
keywords = ["vpn", "p2p", "network", "easytier"]
categories = ["network-programming", "command-line-utilities"]
license-file = "LICENSE"
readme = "README.md"
build = "build/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "easytier-core"
path = "src/easytier-core.rs"
test = false
[[bin]]
name = "easytier-cli"
path = "src/easytier-cli.rs"
[lib]
name = "easytier"
path = "src/lib.rs"
[dependencies]
git-version = "0.3.9"
tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = { version = "0.3", features = [
"env-filter",
"local-time",
"time",
] }
derivative = "2.2.0"
derive_more = { version = "2.1.1", features = ["full"] }
console-subscriber = { version = "0.4.1", optional = true }
indoc = "2.0.7"
regex = "1.8"
paste = "1.0"
thiserror = "1.0"
auto_impl = "1.1.0"
crossbeam = "0.8.4"
arc-swap = "1.7"
time = "0.3"
toml = "0.8.12"
chrono = { version = "0.4.37", features = ["serde"] }
guarden = "0.2"
hotpath = { version = "0.18", default-features = false, optional = true }
quanta = "0.12"
delegate = "0.13.5"
itertools = "0.14.0"
strum = { version = "0.27.2", features = ["derive"] }
gethostname = "0.5.0"
futures = { version = "0.3", features = ["bilock", "unstable"] }
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1"
tokio-util = { version = "0.7.9", features = ["codec", "net", "io", "rt"] }
async-stream = "0.3.5"
async-trait = "0.1.74"
dashmap = "6.0"
moka = { version = "0.12", features = ["future"] }
timedmap = "=1.0.1"
# for full-path zero-copy
zerocopy = { version = "0.7.32", features = ["derive", "simd"] }
bytes = "1.5.0"
pin-project-lite = "0.2.13"
atomic_refcell = "0.1.13"
quinn = { version = "0.11.8", optional = true, features = ["ring"] }
quinn-proto = { version = "0.11.12", optional = true }
quinn-udp = { version = "0.5", optional = true }
seahash = { version = "4.1.0", optional = true }
rustls = { version = "0.23.0", features = [
"ring", "tls12"
], default-features = false, optional = true }
rcgen = { version = "0.12.1", optional = true }
# for websocket
tokio-websockets = { version = "0.13.2", git = "https://github.com/EasyTier/tokio-websockets", optional = true, features = [
"rustls-webpki-roots",
"client",
"server",
"fastrand",
"ring",
] }
http = { version = "1", default-features = false, features = [
"std",
], optional = true }
forwarded-header-value = { version = "0.1.1", optional = true }
tokio-rustls = { version = "0.26", default-features = false, optional = true }
# for tap device
tun = { package = "tun-easytier", git = "https://github.com/EasyTier/rust-tun", features = [
"async",
], optional = true }
# for net ns
nix = { version = "0.29.0", features = [
"sched",
"socket",
"ioctl",
"net",
"fs",
] }
uuid = { version = "1.5.0", features = [
"v4",
"fast-rng",
"macro-diagnostics",
"serde",
] }
# for ring tunnel
once_cell = "1.18.0"
# for rpc
prost = "0.14.3"
prost-reflect = { version = "0.16.4", default-features = false, features = ["derive", "serde"] }
prost-wkt-types = "0.7.1"
pbjson = "0.9.0"
anyhow = "1.0"
ariadne = "0.5"
url = { version = "2.5", features = ["serde"] }
percent-encoding = "2.3.1"
idna = "1.0"
# for tun packet
byteorder = "1.5.0"
# for proxy
cidr = { version = "0.3.1", features = ["serde"] }
socket2 = { version = "0.5.10", features = ["all"] }
prefix-trie = { version = "0.7.0", features = ["cidr"] }
# for hole punching
stun_codec = "0.3.4"
bytecodec = "0.4.15"
rand = "0.8.5"
serde = { version = "1.0", features = ["derive"] }
pnet = { version = "0.35.0", features = ["serde"] }
serde_json = "1"
clap = { version = "4.5.30", features = [
"string",
"unicode",
"derive",
"wrap_help",
"env",
] }
clap_complete = { version = "4.5.55" }
clap_complete_nushell = { version = "4.5.10" }
async-recursion = "1.0.5"
network-interface = "2.0"
# for ospf route
petgraph = "0.8.1"
ordered_hash_map = "0.5.0"
# for wireguard
boringtun = { package = "boringtun-easytier", version = "0.6.1", optional = true }
# for encryption
ring = { version = "0.17", optional = true }
bitflags = "2.5"
aes-gcm = { version = "0.10.3", optional = true }
openssl = { version = "0.10", optional = true, features = ["vendored"] }
snow = "0.10.0"
x25519-dalek = { version = "2.0", features = ["static_secrets"] }
# for cli
tabled = "0.16"
humansize = "2.1.3"
terminal_size = "0.4"
unicode-width = "0.1"
base64 = "0.22"
mimalloc = { version = "*", optional = true }
# mips
atomic-shim = "0.2.0"
smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "0a926767a68bc88d5512afefa7529c5ecdade4ea", optional = true, default-features = false, features = [
"std",
"medium-ip",
"proto-ipv4",
"proto-ipv6",
"proto-ipv4-fragmentation",
"fragmentation-buffer-size-8192",
"assembler-max-segment-count-16",
"reassembly-buffer-size-8192",
"reassembly-buffer-count-16",
"socket-tcp",
"socket-udp",
# "socket-tcp-cubic",
"async",
] }
parking_lot = { version = "0.12.0" }
wildmatch = "2.3.4"
rust-i18n = "3"
sys-locale = "0.3"
ringbuf = "0.4.5"
async-ringbuf = "0.3.1"
service-manager = { git = "https://github.com/EasyTier/service-manager-rs.git", branch = "main" }
zstd = { version = "0.13", optional = true }
kcp-sys = { git = "https://github.com/EasyTier/kcp-sys", rev = "d7427c22d764deb1860a7d37acc446ed5033464c", optional = true }
# for http connector
http_req = { git = "https://github.com/EasyTier/http_req.git", default-features = false, features = [
"rust-tls",
] }
# for dns connector
hickory-resolver = "0.25.2"
hickory-proto = "0.25.2"
# for magic dns
hickory-client = { version = "0.25.2", optional = true }
hickory-server = { version = "0.25.2", features = [
"resolver",
], optional = true }
bon = "3.9.1"
derive_builder = "0.20.2"
humantime-serde = "1.1.1"
multimap = "0.10.1"
version-compare = "0.2.0"
hmac = "0.12.1"
sha2 = "0.10.8"
shellexpand = "3.1.1"
# for fake tcp
flume = { version = "0.12", optional = true }
igd-next = { version = "0.17.0", features = ["aio_tokio"] }
natpmp = "0.5.0"
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd"))'.dependencies]
machine-uid = "0.5.3"
[target.'cfg(any(target_os = "linux"))'.dependencies]
netlink-sys = "0.8.7"
netlink-packet-route = "0.21.0"
netlink-packet-core = { version = "0.7.0" }
netlink-packet-utils = "0.5.2"
# for magic dns
resolv-conf = "0.7.3"
dbus = { version = "0.9.7", features = ["vendored"] }
which = "7.0.3"
[target.'cfg(all(windows, any(target_arch = "x86_64", target_arch = "x86")))'.dependencies]
windivert = { git = "https://github.com/EasyTier/windivert-rust.git", rev = "adcc56d1550f7b5377ec2b3429f413ee24a77375", features = [
"static",
] }
[target.'cfg(windows)'.dependencies]
windows = { version = "0.62.2", features = [
"Win32_Foundation",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
"Win32_NetworkManagement_WindowsFirewall",
"Win32_Networking",
"Win32_System_Com",
"Win32_System_Diagnostics",
"Win32_System_Diagnostics_Debug",
"Win32_System_Ole",
"Win32_System_Variant",
"Win32_Networking_WinSock",
"Win32_System_IO",
] }
encoding = "0.2"
winreg = "0.52"
windows-service = "0.7.0"
winapi = { version = "0.3.9", features = ["impl-default"] }
[target.'cfg(not(windows))'.dependencies]
jemallocator = { package = "tikv-jemallocator", version = "0.6.0", optional = true, features = [
"unprefixed_malloc_on_supported_platforms",
] }
jemalloc-ctl = { package = "tikv-jemalloc-ctl", version = "0.6.0", optional = true, features = [
"use_std",
] }
[target.'cfg(not(target_os = "macos"))'.dependencies]
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.6.0", features = [
"background_threads_runtime_support",
"background_threads",
], optional = true }
[target.'cfg(target_os = "macos")'.dependencies]
jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.6.0", features = [
], optional = true }
[build-dependencies]
cfg_aliases = "0.2.1"
indoc = "2.0"
globwalk = "0.8.1"
regex = "1"
prost-build = "0.14.3"
prost-reflect-build = "0.16.0"
pbjson-build = "0.9.0"
proc-macro2 = "1"
quote = "1"
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
"win7",
] }
[target.'cfg(windows)'.build-dependencies]
reqwest = { version = "0.12.12", features = ["blocking"] }
zip = "4.0.0"
[dev-dependencies]
serial_test = "3.0.0"
rstest = "0.25.0"
futures-util = "0.3.31"
maplit = "1.0.2"
tempfile = "3.22.0"
ctor = "0.8.0"
[target.'cfg(target_os = "linux")'.dev-dependencies]
defguard_wireguard_rs = "0.4.2"
tokio-socks = "0.5.2"
[features]
default = [
"wireguard",
"websocket",
"smoltcp",
"tun",
"socks5",
"kcp",
"quic",
"faketcp",
"magic-dns",
"zstd",
"udp-gso",
]
full = [
"websocket",
"wireguard",
"aes-gcm",
"openssl-crypto", # need openssl-dev libs
"smoltcp",
"tun",
"socks5",
"kcp",
"quic",
"faketcp",
"magic-dns",
"zstd",
]
wireguard = ["dep:boringtun", "dep:ring"]
quic = ["dep:quinn", "dep:quinn-proto", "dep:seahash", "dep:rustls", "dep:rcgen"]
udp-gso = ["dep:quinn-udp"]
kcp = ["dep:kcp-sys"]
mimalloc = ["dep:mimalloc"]
aes-gcm = ["dep:aes-gcm"]
openssl-crypto = ["dep:openssl"]
tun = ["dep:tun"]
websocket = [
"dep:tokio-websockets",
"dep:http",
"dep:forwarded-header-value",
"dep:tokio-rustls",
"dep:rustls",
"dep:rcgen",
]
smoltcp = ["dep:smoltcp"]
socks5 = ["smoltcp"]
ffi-dataplane = ["socks5"]
jemalloc = ["dep:jemallocator", "dep:jemalloc-sys"]
jemalloc-prof = [
"jemalloc",
"dep:jemalloc-ctl",
"jemalloc-ctl/stats",
"jemalloc-sys/profiling",
"jemalloc-sys/stats",
]
tracing = ["tokio/tracing", "dep:console-subscriber"]
hotpath = [
"dep:hotpath",
"hotpath/hotpath",
"hotpath/tokio",
"hotpath/parking_lot",
"hotpath/flume",
]
hotpath-cpu = ["hotpath", "hotpath/hotpath-cpu"]
hotpath-alloc = ["hotpath", "hotpath/hotpath-alloc"]
magic-dns = ["dep:hickory-client", "dep:hickory-server"]
faketcp = ["dep:flume"]
zstd = ["dep:zstd"]
# For Network Extension on macOS
macos-ne = []