From 96d3832f025452af33fda17e1a09eeb78455e7fa Mon Sep 17 00:00:00 2001 From: Stanislav Baiduzhyi Date: Wed, 19 Jun 2024 15:11:23 +0100 Subject: [PATCH] CVPN-956: handling of Full error on tun io-uring send Treating tun io-uring Full error as OK scenario. It is effectively the same scenario as a buffer in a network switch/router filling up so dropping the traffic is appropriate, higher level protocols (e.g. TCP) running over the tunnel will use their congestion control algorithms to adjust their send rate. --- Cargo.lock | 1 + lightway-app-utils/Cargo.toml | 1 + lightway-app-utils/src/iouring.rs | 16 +++++++++++++--- lightway-app-utils/src/lib.rs | 1 + lightway-app-utils/src/metrics.rs | 8 ++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 lightway-app-utils/src/metrics.rs diff --git a/Cargo.lock b/Cargo.lock index 9e1b11c..7d57021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -992,6 +992,7 @@ dependencies = [ "humantime", "io-uring", "lightway-core", + "metrics", "pnet", "serde", "serde_with", diff --git a/lightway-app-utils/Cargo.toml b/lightway-app-utils/Cargo.toml index c095e51..01cadcc 100644 --- a/lightway-app-utils/Cargo.toml +++ b/lightway-app-utils/Cargo.toml @@ -32,6 +32,7 @@ tokio-eventfd = "0.2.1" dashmap = "5.5.3" thiserror = "1.0.57" tokio-tun = "0.11.2" +metrics = "0.23.0" [[example]] name = "udprelay" diff --git a/lightway-app-utils/src/iouring.rs b/lightway-app-utils/src/iouring.rs index 48e9fb3..4c9a743 100644 --- a/lightway-app-utils/src/iouring.rs +++ b/lightway-app-utils/src/iouring.rs @@ -18,6 +18,7 @@ use std::{ }; use tokio::{io::AsyncReadExt, sync::Semaphore}; use tokio_eventfd::EventFd; +use crate::metrics::inside_io_send_failed; const REGISTERED_FD_INDEX: u32 = 0; const IOURING_SQPOLL_IDLE_TIME: u32 = 100; @@ -190,11 +191,20 @@ impl IOUring { /// Try Send packet to Tun device pub fn try_send(&self, buf: BytesMut) -> IOUringResult<()> { - self.inner + let try_send_res = self.inner .send_q .tx - .try_send(buf) - .map_err(IOUringError::SendError) + .try_send(buf); + match try_send_res { + Ok(()) => Ok(()), + Err(e) if e.is_full() => { + // it is effectively the same scenario as a buffer in a network + // switch/router filling up so dropping the traffic is appropriate + inside_io_send_failed(); + Ok(()) + }, + Err(e) => Err(IOUringError::SendError(e)) + } } } diff --git a/lightway-app-utils/src/lib.rs b/lightway-app-utils/src/lib.rs index a892ec9..24cb1c1 100644 --- a/lightway-app-utils/src/lib.rs +++ b/lightway-app-utils/src/lib.rs @@ -26,5 +26,6 @@ pub use iouring::IOUring; pub use tun::Tun; +mod metrics; mod utils; pub use utils::is_file_path_valid; diff --git a/lightway-app-utils/src/metrics.rs b/lightway-app-utils/src/metrics.rs new file mode 100644 index 0000000..682bd20 --- /dev/null +++ b/lightway-app-utils/src/metrics.rs @@ -0,0 +1,8 @@ +use metrics::counter; + +const METRIC_TUN_IOURING_PACKET_DROPPED: &str = "tun_iouring_packet_dropped"; + +/// Receiving [`crate::iouring::IOUringError::SendError`] means that the +pub(crate) fn inside_io_send_failed() { + counter!(METRIC_TUN_IOURING_PACKET_DROPPED).increment(1); +}