Skip to content

Commit

Permalink
Network: Set TOS (#1946)
Browse files Browse the repository at this point in the history
* set type and prioritize alvr's packets on local networks

* add tcp tos and options for advanced users

* revert linux brute force workaround
  • Loading branch information
Vixea committed Jan 4, 2024
1 parent 377c556 commit bb3cc59
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 9 deletions.
1 change: 1 addition & 0 deletions alvr/client_core/src/connection.rs
Expand Up @@ -251,6 +251,7 @@ fn connection_pipeline(
Duration::from_secs(1),
settings.connection.stream_port,
settings.connection.stream_protocol,
settings.connection.dscp,
settings.connection.client_send_buffer_bytes,
settings.connection.client_recv_buffer_bytes,
)
Expand Down
1 change: 1 addition & 0 deletions alvr/server/src/connection.rs
Expand Up @@ -538,6 +538,7 @@ fn connection_pipeline(
client_ip,
settings.connection.stream_port,
settings.connection.stream_protocol,
settings.connection.dscp,
settings.connection.server_send_buffer_bytes,
settings.connection.server_recv_buffer_bytes,
settings.connection.packet_size as _,
Expand Down
41 changes: 40 additions & 1 deletion alvr/session/src/settings.rs
Expand Up @@ -942,6 +942,8 @@ TCP: Slower than UDP, but more stable. Pick this if you experience video or audi
pub web_server_port: u16,
pub osc_local_port: u16,

pub dscp: Option<DscpTos>,

#[schema(strings(display_name = "Streamer send buffer size"))]
pub server_send_buffer_bytes: SocketBufferSize,

Expand Down Expand Up @@ -990,6 +992,30 @@ For now works only on Windows+Nvidia"#
pub statistics_history_size: usize,
}

#[derive(SettingsSchema, Serialize, Deserialize, Clone)]
#[repr(u8)]
#[schema(gui = "button_group")]
pub enum DropProbability {
Low = 0x01,
Medium = 0x10,
High = 0x11,
}

#[derive(SettingsSchema, Serialize, Deserialize, Clone)]
pub enum DscpTos {
BestEffort,

ClassSelector(#[schema(gui(slider(min = 1, max = 7)))] u8),

AssuredForwarding {
#[schema(gui(slider(min = 1, max = 4)))]
class: u8,
drop_probability: DropProbability,
},

ExpeditedForwarding,
}

#[derive(SettingsSchema, Serialize, Deserialize, Clone)]
pub struct RawEventsConfig {
#[schema(flag = "real-time")]
Expand Down Expand Up @@ -1140,7 +1166,7 @@ pub fn session_settings_default() -> SettingsDefault {
ConstantMbps: 30,
Adaptive: BitrateModeAdaptiveDefault {
gui_collapsed: true,
saturation_multiplier: 1.0,
saturation_multiplier: 0.95,
max_bitrate_mbps: SwitchDefault {
enabled: false,
content: 100,
Expand Down Expand Up @@ -1512,6 +1538,19 @@ pub fn session_settings_default() -> SettingsDefault {
web_server_port: 8082,
stream_port: 9944,
osc_local_port: 9942,
dscp: OptionalDefault {
set: false,
content: DscpTosDefault {
ClassSelector: 7,
AssuredForwarding: DscpTosAssuredForwardingDefault {
class: 4,
drop_probability: DropProbabilityDefault {
variant: DropProbabilityDefaultVariant::Low,
},
},
variant: DscpTosDefaultVariant::ExpeditedForwarding,
},
},
server_send_buffer_bytes: socket_buffer.clone(),
server_recv_buffer_bytes: socket_buffer.clone(),
client_send_buffer_bytes: socket_buffer.clone(),
Expand Down
6 changes: 5 additions & 1 deletion alvr/sockets/src/backend/tcp.rs
Expand Up @@ -2,7 +2,7 @@ use crate::LOCAL_IP;

use super::{SocketReader, SocketWriter};
use alvr_common::{anyhow::Result, con_bail, ConResult, HandleTryAgain, ToCon};
use alvr_session::SocketBufferSize;
use alvr_session::{DscpTos, SocketBufferSize};
use std::{
io::Read,
io::Write,
Expand All @@ -13,12 +13,16 @@ use std::{
pub fn bind(
timeout: Duration,
port: u16,
dscp: Option<DscpTos>,
send_buffer_bytes: SocketBufferSize,
recv_buffer_bytes: SocketBufferSize,
) -> Result<TcpListener> {
let socket = TcpListener::bind((LOCAL_IP, port))?.into();

crate::set_socket_buffers(&socket, send_buffer_bytes, recv_buffer_bytes).ok();

crate::set_dscp(&socket, dscp);

socket.set_read_timeout(Some(timeout))?;

Ok(socket.into())
Expand Down
5 changes: 4 additions & 1 deletion alvr/sockets/src/backend/udp.rs
Expand Up @@ -2,7 +2,7 @@ use crate::LOCAL_IP;

use super::{SocketReader, SocketWriter};
use alvr_common::{anyhow::Result, ConResult, HandleTryAgain};
use alvr_session::SocketBufferSize;
use alvr_session::{DscpTos, SocketBufferSize};
use socket2::{MaybeUninitSlice, Socket};
use std::{
ffi::c_int,
Expand All @@ -15,13 +15,16 @@ use std::{
// let tokio set all the internal parameters it needs from the start.
pub fn bind(
port: u16,
dscp: Option<DscpTos>,
send_buffer_bytes: SocketBufferSize,
recv_buffer_bytes: SocketBufferSize,
) -> Result<UdpSocket> {
let socket = UdpSocket::bind((LOCAL_IP, port))?.into();

crate::set_socket_buffers(&socket, send_buffer_bytes, recv_buffer_bytes).ok();

crate::set_dscp(&socket, dscp);

Ok(socket.into())
}

Expand Down
1 change: 1 addition & 0 deletions alvr/sockets/src/control_socket.rs
Expand Up @@ -127,6 +127,7 @@ pub fn get_server_listener(timeout: Duration) -> Result<TcpListener> {
let listener = tcp::bind(
timeout,
CONTROL_PORT,
None,
SocketBufferSize::Default,
SocketBufferSize::Default,
)?;
Expand Down
20 changes: 19 additions & 1 deletion alvr/sockets/src/lib.rs
Expand Up @@ -3,7 +3,8 @@ mod control_socket;
mod stream_socket;

use alvr_common::{anyhow::Result, info};
use alvr_session::SocketBufferSize;
use alvr_session::{DscpTos, SocketBufferSize};
use socket2::Socket;
use std::{
net::{IpAddr, Ipv4Addr},
time::Duration,
Expand Down Expand Up @@ -69,3 +70,20 @@ fn set_socket_buffers(

Ok(())
}

fn set_dscp(socket: &Socket, dscp: Option<DscpTos>) {
// https://en.wikipedia.org/wiki/Differentiated_services
if let Some(dscp) = dscp {
let tos = match dscp {
DscpTos::BestEffort => 0,
DscpTos::ClassSelector(precedence) => precedence << 3,
DscpTos::AssuredForwarding {
class,
drop_probability,
} => (class << 3) | drop_probability as u8,
DscpTos::ExpeditedForwarding => 0b101110,
};

socket.set_tos((tos << 2) as u32).ok();
}
}
17 changes: 12 additions & 5 deletions alvr/sockets/src/stream_socket.rs
Expand Up @@ -20,7 +20,7 @@ use crate::backend::{tcp, udp, SocketReader, SocketWriter};
use alvr_common::{
anyhow::Result, debug, parking_lot::Mutex, AnyhowToCon, ConResult, HandleTryAgain, ToCon,
};
use alvr_session::{SocketBufferSize, SocketProtocol};
use alvr_session::{DscpTos, SocketBufferSize, SocketProtocol};
use serde::{de::DeserializeOwned, Serialize};
use std::{
cmp::Ordering,
Expand Down Expand Up @@ -271,16 +271,21 @@ impl StreamSocketBuilder {
timeout: Duration,
port: u16,
stream_socket_config: SocketProtocol,
stream_tos_config: Option<DscpTos>,
send_buffer_bytes: SocketBufferSize,
recv_buffer_bytes: SocketBufferSize,
) -> Result<Self> {
Ok(match stream_socket_config {
SocketProtocol::Udp => {
StreamSocketBuilder::Udp(udp::bind(port, send_buffer_bytes, recv_buffer_bytes)?)
}
SocketProtocol::Udp => StreamSocketBuilder::Udp(udp::bind(
port,
stream_tos_config,
send_buffer_bytes,
recv_buffer_bytes,
)?),
SocketProtocol::Tcp => StreamSocketBuilder::Tcp(tcp::bind(
timeout,
port,
stream_tos_config,
send_buffer_bytes,
recv_buffer_bytes,
)?),
Expand Down Expand Up @@ -327,14 +332,16 @@ impl StreamSocketBuilder {
client_ip: IpAddr,
port: u16,
protocol: SocketProtocol,
dscp: Option<DscpTos>,
send_buffer_bytes: SocketBufferSize,
recv_buffer_bytes: SocketBufferSize,
max_packet_size: usize,
) -> ConResult<StreamSocket> {
let (send_socket, receive_socket): (Box<dyn SocketWriter>, Box<dyn SocketReader>) =
match protocol {
SocketProtocol::Udp => {
let socket = udp::bind(port, send_buffer_bytes, recv_buffer_bytes).to_con()?;
let socket =
udp::bind(port, dscp, send_buffer_bytes, recv_buffer_bytes).to_con()?;
let (send_socket, receive_socket) =
udp::connect(&socket, client_ip, port, timeout).to_con()?;

Expand Down

0 comments on commit bb3cc59

Please sign in to comment.