buf size changes, update leg select, update client socket, set lowat

This commit is contained in:
Трапезников Кирилл Иванович
2026-04-10 20:52:41 +10:00
parent eb23825bf5
commit c0c5943da7
10 changed files with 133 additions and 136 deletions
+6
View File
@@ -165,6 +165,12 @@ impl TcpConnection {
if !self.server_eof {
loop {
let pending_size: usize = self.pending_data.iter().map(|b| b.len()).sum();
if pending_size >= 4 * NetworkConfig::global().mtu {
break;
}
match self.core.rx.try_recv() {
Ok(data) => {
self.pending_data.push_back(data);
+19 -46
View File
@@ -8,6 +8,7 @@ use smoltcp::{
iface::{Config, Interface, SocketSet},
phy::DeviceCapabilities,
};
use tokio::sync::mpsc::UnboundedReceiver;
use std::net::Ipv4Addr;
use std::sync::atomic::Ordering;
use std::{
@@ -36,7 +37,7 @@ pub struct Engine {
manager: ConnectionManager,
device: VirtTunDevice,
to_smoltcp_tx: Sender<TokenBuffer>,
from_smoltcp_rx: Option<Receiver<TokenBuffer>>,
from_smoltcp_rx: Option<UnboundedReceiver<TokenBuffer>>,
avail: Arc<AtomicBool>,
rx_from_tunnel: mpsc::Receiver<RawCastFrame>,
}
@@ -123,22 +124,15 @@ impl Engine {
if let Some(token) = msg {
self.manager.try_create_socket_from_packet(&token, &mut self.socket_set);
// 🔥 ФИКС: try_send вместо send.
// Если Muxer/smoltcp вернул "BUSY", smoltcp не запишет этот пакет.
// Очередь дропнет пакет, и ОС поймет, что нужно сбавить скорость TCP.
if self.to_smoltcp_tx.try_send(token).is_ok() {
// 🔥 ФИКС 1: Используем .send().await.
// Мы не имеем права терять пакеты внутри системы.
// Если smoltcp занят, TUN Reader просто подождет.
if self.to_smoltcp_tx.send(token).await.is_ok() {
self.device.mark_rx_available();
}
let mut count = 0;
while let Ok(token) = tun_to_engine_rx.try_recv() {
self.manager.try_create_socket_from_packet(&token, &mut self.socket_set);
if self.to_smoltcp_tx.try_send(token).is_ok() {
self.device.mark_rx_available();
}
count += 1;
if count >= 32 { break; }
}
// Пакетную обработку Ok(token) = try_recv лучше убрать или
// тоже заменить на логику, которая не дропает данные.
} else { break; }
}
}
@@ -150,7 +144,7 @@ impl Engine {
self.interface
.poll(now, &mut self.device, &mut self.socket_set)
}
fn spawn_tun_reader(
mut reader: DeviceReader,
to_engine: mpsc::Sender<TokenBuffer>,
@@ -160,47 +154,26 @@ impl Engine {
debug!("TUN Reader task started");
let mut buf = [0u8; 65536];
while let Ok(n) = reader.read(&mut buf).await {
if n == 0 {
break;
}
let first_byte = buf[0];
let version = first_byte >> 4;
if version == 4 {
if buf[12..16] == [0, 0, 0, 0] {
continue;
}
if buf[16] >= 224 && buf[16] <= 239 {
continue;
}
} else if version == 6 {
if first_byte == 0xff {
continue;
}
}
if n == 0 { break; }
// ... (фильтрация IP) ...
let mut token = TokenBuffer::with_capacity(n);
token.extend_from_slice(&buf[..n]);
// 🚨 ИСПОЛЬЗУЕМ .await. Это создаст идеальный Backpressure!
// Если Engine занят, TUN просто перестанет читать из ОС.
match to_engine.try_send(token) {
Ok(_) => {
is_avail.store(true, Ordering::Release);
}
Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => {
// Пакет отброшен (Drop). Идеальное поведение для борьбы с Bufferbloat.
}
Err(_) => break, // Канал закрыт
}
// 🔥 ФИКС 2: Возвращаем .send().await!
// Это заставит ОС притормозить отправку пакетов,
// если туннель перегружен. Пинг упадет, так как пакеты
// будут стоять в очереди ОС, а не дропаться.
if to_engine.send(token).await.is_ok() {
is_avail.store(true, Ordering::Release);
} else { break; }
}
warn!("TUN Reader task stopped");
});
}
fn spawn_tun_writer(
mut writer: DeviceWriter,
mut from_smoltcp: Receiver<TokenBuffer>,
mut from_smoltcp: UnboundedReceiver<TokenBuffer>, // 🔥 Обновили тип
) {
tokio::spawn(async move {
debug!("TUN Writer task started");
+6 -9
View File
@@ -79,9 +79,8 @@ impl DerefMut for TokenBuffer {
pub struct VirtTunDevice {
capabilities: DeviceCapabilities,
// 🔥 ФИКС: Используем ограниченные каналы вместо Unbounded
rx_queue: mpsc::Receiver<TokenBuffer>,
tx_queue: mpsc::Sender<TokenBuffer>,
rx_queue: mpsc::Receiver<TokenBuffer>, // Входящие из TUN оставляем ограниченными (Backpressure)
tx_queue: mpsc::UnboundedSender<TokenBuffer>, // 🔥 ФИКС: Исходящие в TUN делаем БЕЗЛИМИТНЫМИ
rx_avail: Arc<AtomicBool>,
rx_bytes: u64,
@@ -104,12 +103,11 @@ impl VirtTunDevice {
) -> (
Self,
mpsc::Sender<TokenBuffer>,
mpsc::Receiver<TokenBuffer>,
mpsc::UnboundedReceiver<TokenBuffer>,
Arc<AtomicBool>,
) {
// 🔥 ФИКС: Ограничиваем очередь физики до 128 пакетов
let (to_smoltcp_tx, to_smoltcp_rx) = mpsc::channel(128);
let (from_smoltcp_tx, from_smoltcp_rx) = mpsc::channel(128);
let (from_smoltcp_tx, from_smoltcp_rx) = mpsc::unbounded_channel(); // 🔥 Безлимитный канал
let rx_avail = Arc::new(AtomicBool::new(false));
let now = StdInstant::now();
@@ -250,9 +248,8 @@ impl phy::TxToken for VirtTxToken<'_> {
GLOBAL_RX_BYTES.fetch_add(len as u64, Ordering::Relaxed);
GLOBAL_RX_PACKETS.fetch_add(1, Ordering::Relaxed);
// 🔥 ФИКС: Используем try_send. Если буфер полон (сеть тормозит), дропаем пакет!
// Это сигнализирует TCP-стеку об ограничении канала.
let _ = self.0.tx_queue.try_send(buffer);
// 🔥 ФИКС: Отправляем в безлимитный канал. Никаких дропов внутри локальной машины!
let _ = self.0.tx_queue.send(buffer);
result
}
}