mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-26 22:37:05 -05:00
some virtual-router config work
This commit is contained in:
parent
9fe8f0f102
commit
f2aa066626
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2874,6 +2874,9 @@ name = "ipnet"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnetwork"
|
||||
@ -6555,6 +6558,8 @@ dependencies = [
|
||||
"backtrace",
|
||||
"cfg-if 1.0.0",
|
||||
"chrono",
|
||||
"clap 4.5.20",
|
||||
"config 0.13.4",
|
||||
"console_error_panic_hook",
|
||||
"ctrlc",
|
||||
"eyre",
|
||||
@ -6564,6 +6569,7 @@ dependencies = [
|
||||
"futures_codec",
|
||||
"getrandom",
|
||||
"ifstructs",
|
||||
"ipnet",
|
||||
"jni",
|
||||
"jni-sys",
|
||||
"js-sys",
|
||||
|
@ -44,7 +44,13 @@ tracing = ["dep:tracing", "dep:tracing-subscriber", "tokio/tracing"]
|
||||
debug-locks = []
|
||||
|
||||
virtual-network = []
|
||||
virtual-network-server = ["dep:ws_stream_tungstenite", "dep:async-tungstenite"]
|
||||
virtual-network-server = [
|
||||
"dep:ws_stream_tungstenite",
|
||||
"dep:async-tungstenite",
|
||||
"dep:clap",
|
||||
"dep:config",
|
||||
"dep:ipnet",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
tracing = { version = "0.1.40", features = [
|
||||
@ -95,8 +101,14 @@ socket2 = { version = "0.5.7", features = ["all"] }
|
||||
tokio = { version = "1.38.1", features = ["full"], optional = true }
|
||||
tokio-util = { version = "0.7.11", features = ["compat"], optional = true }
|
||||
tokio-stream = { version = "0.1.15", features = ["net"], optional = true }
|
||||
|
||||
ws_stream_tungstenite = { version = "0.14.0", optional = true }
|
||||
async-tungstenite = { version = "0.28.0", optional = true }
|
||||
clap = { version = "4", features = ["derive"], optional = true }
|
||||
config = { version = "^0", default-features = false, features = [
|
||||
"yaml",
|
||||
], optional = true }
|
||||
ipnet = { version = "2", features = ["serde"], optional = true }
|
||||
|
||||
# Dependencies for WASM builds only
|
||||
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
|
||||
|
@ -1,7 +1,9 @@
|
||||
#![cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
|
||||
|
||||
use cfg_if::*;
|
||||
use clap::Parser;
|
||||
use parking_lot::*;
|
||||
use std::path::PathBuf;
|
||||
use stop_token::StopSource;
|
||||
use veilid_tools::*;
|
||||
|
||||
@ -23,12 +25,33 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about = "Veilid VirtualRouter")]
|
||||
struct CmdlineArgs {
|
||||
/// TCP address to listen on
|
||||
#[arg(short('t'), long)]
|
||||
tcp_addr: Option<SocketAddr>,
|
||||
/// Turn off TCP listener
|
||||
#[arg(long)]
|
||||
no_tcp: bool,
|
||||
/// WS address to listen on
|
||||
#[arg(short('w'), long)]
|
||||
ws_addr: Option<SocketAddr>,
|
||||
/// Turn off WS listener
|
||||
#[arg(long)]
|
||||
no_ws: bool,
|
||||
/// Specify a configuration file to use
|
||||
#[arg(short = 'c', long, value_name = "FILE")]
|
||||
config_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
let stop_source = StopSource::new();
|
||||
let stop_token = stop_source.token();
|
||||
let stop_mutex = Mutex::new(Some(stop_source));
|
||||
|
||||
ctrlc::set_handler(move || {
|
||||
println!("Exiting...");
|
||||
*(stop_mutex.lock()) = None;
|
||||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
@ -36,7 +59,31 @@ fn main() -> Result<(), String> {
|
||||
block_on(async {
|
||||
println!("Veilid VirtualRouter v{}", VERSION);
|
||||
|
||||
let args = CmdlineArgs::parse();
|
||||
|
||||
let router_server = virtual_network::RouterServer::new();
|
||||
let _ss_tcp = if !args.no_tcp {
|
||||
Some(
|
||||
router_server
|
||||
.listen_tcp(args.tcp_addr)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let _ss_ws = if !args.no_ws {
|
||||
Some(
|
||||
router_server
|
||||
.listen_ws(args.ws_addr)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
router_server
|
||||
.run(stop_token)
|
||||
.await
|
@ -46,7 +46,9 @@ impl fmt::Display for VirtualProtocolType {
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub enum ServerProcessorRequest {
|
||||
AllocateMachine,
|
||||
AllocateMachine {
|
||||
profile: String,
|
||||
},
|
||||
ReleaseMachine {
|
||||
machine_id: MachineId,
|
||||
},
|
||||
|
@ -180,8 +180,8 @@ impl RouterClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn allocate_machine(self) -> VirtualNetworkResult<MachineId> {
|
||||
let request = ServerProcessorRequest::AllocateMachine;
|
||||
pub async fn allocate_machine(self, profile: String) -> VirtualNetworkResult<MachineId> {
|
||||
let request = ServerProcessorRequest::AllocateMachine { profile };
|
||||
let ServerProcessorReplyValue::AllocateMachine { machine_id } =
|
||||
self.perform_request(request).await?
|
||||
else {
|
||||
|
168
veilid-tools/src/virtual_network/router_server/config.rs
Normal file
168
veilid-tools/src/virtual_network/router_server/config.rs
Normal file
@ -0,0 +1,168 @@
|
||||
use super::*;
|
||||
use ipnet::*;
|
||||
use serde::*;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
|
||||
pub use ::config::ConfigError;
|
||||
|
||||
fn load_default_config() -> Result<::config::Config, ConfigError> {
|
||||
let default_config = include_str!("default_config.yml");
|
||||
|
||||
::config::Config::builder()
|
||||
.add_source(::config::File::from_str(
|
||||
default_config,
|
||||
::config::FileFormat::Yaml,
|
||||
))
|
||||
.build()
|
||||
}
|
||||
|
||||
fn load_config(cfg: ::config::Config, config_file: &Path) -> Result<::config::Config, ConfigError> {
|
||||
if let Some(config_file_str) = config_file.to_str() {
|
||||
::config::Config::builder()
|
||||
.add_source(cfg)
|
||||
.add_source(::config::File::new(
|
||||
config_file_str,
|
||||
::config::FileFormat::Yaml,
|
||||
))
|
||||
.build()
|
||||
} else {
|
||||
Err(ConfigError::Message(
|
||||
"config file path is not valid UTF-8".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
const fn default_weight() -> f32 {
|
||||
1.0f32
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Profile {
|
||||
machine: One<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Machine {
|
||||
network: One<String>,
|
||||
#[serde(default)]
|
||||
address4: Option<Ipv4Addr>,
|
||||
#[serde(default)]
|
||||
address6: Option<Ipv6Addr>,
|
||||
#[serde(default)]
|
||||
disable_capabilities: Vec<String>,
|
||||
#[serde(default)]
|
||||
bootstrap: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct One<T: fmt::Debug + Clone> {
|
||||
#[serde(flatten)]
|
||||
pub value: Vec<Weighted<T>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct OneOrNone<T: fmt::Debug + Clone> {
|
||||
#[serde(flatten)]
|
||||
pub value: Vec<Weighted<T>>,
|
||||
#[serde(default = "default_weight")]
|
||||
pub none_weight: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct Probability {
|
||||
#[serde(flatten)]
|
||||
probability: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Weighted<T: fmt::Debug + Clone> {
|
||||
#[serde(flatten)]
|
||||
pub value: T,
|
||||
#[serde(default = "default_weight")]
|
||||
pub weight: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Network {
|
||||
#[serde(flatten)]
|
||||
subnets: Subnets,
|
||||
#[serde(default)]
|
||||
distance: Option<Distance>,
|
||||
#[serde(flatten)]
|
||||
performance: Performance,
|
||||
#[serde(default)]
|
||||
gateway: Option<Gateway>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Subnets {
|
||||
subnet4: OneOrNone<Ipv4Net>,
|
||||
subnet6: OneOrNone<Ipv6Net>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Gateway {
|
||||
translation: One<Translation>,
|
||||
upnp: Probability,
|
||||
network: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Distance {
|
||||
min: f32,
|
||||
max: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Distribution {
|
||||
mean: f32,
|
||||
sigma: f32,
|
||||
skew: f32,
|
||||
min: f32,
|
||||
max: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Decay {
|
||||
lambda: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Performance {
|
||||
latency: Distribution,
|
||||
loss: Probability,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub enum Translation {
|
||||
None,
|
||||
PortRestricted,
|
||||
AddressRestricted,
|
||||
Symmetric,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Config {
|
||||
seed: Option<u32>,
|
||||
profiles: HashMap<String, Profile>,
|
||||
machines: HashMap<String, Machine>,
|
||||
networks: HashMap<String, Network>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(config_file: Option<&OsStr>) -> Result<Self, ConfigError> {
|
||||
// Load the default config
|
||||
let mut cfg = load_default_config()?;
|
||||
|
||||
// Merge in the config file if we have one
|
||||
if let Some(config_file) = config_file {
|
||||
let config_file_path = Path::new(config_file);
|
||||
// If the user specifies a config file on the command line then it must exist
|
||||
cfg = load_config(cfg, config_file_path)?;
|
||||
}
|
||||
|
||||
// Generate config
|
||||
cfg.try_deserialize()
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
---
|
||||
seed: 0
|
||||
profiles:
|
||||
- default:
|
||||
- bootstrap:
|
||||
- server:
|
||||
machines:
|
||||
- bootstrap-1.veilid.net:
|
||||
network: "boot"
|
||||
address4: "170.64.128.16"
|
||||
address6: "2a03:b0c0:2:dd::ddd:0010"
|
||||
disable_capabilities:
|
||||
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
|
||||
bootstrap: true
|
||||
- bootstrap-2.veilid.net:
|
||||
network: "boot"
|
||||
address4: "170.64.128.17"
|
||||
address6: "2a03:b0c0:2:dd::ddd:0011"
|
||||
disable_capabilities:
|
||||
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
|
||||
bootstrap: true
|
||||
networks:
|
||||
- internet:
|
||||
distance:
|
||||
min: 0.04
|
||||
max: 2.0
|
||||
latency:
|
||||
mean: 0.200
|
||||
sigma: 0.080
|
||||
skew: 0
|
||||
min: 0.030
|
||||
max: 0.400
|
||||
loss: 0.01
|
||||
- boot:
|
||||
subnet4: ["170.64.128.0/24"]
|
||||
subnet6: ["2a03:b0c0:2::/48"]
|
||||
latency:
|
||||
mean: 0.0038
|
||||
sigma: 0.001416
|
||||
skew: 0.0009
|
||||
min: 0.0015
|
||||
max: 0.0075
|
||||
loss: 0.0
|
@ -1,3 +1,5 @@
|
||||
mod config;
|
||||
|
||||
use super::*;
|
||||
use async_tungstenite::accept_async;
|
||||
use futures_codec::{Bytes, BytesCodec, FramedRead, FramedWrite};
|
||||
@ -139,7 +141,7 @@ impl RouterServer {
|
||||
.new_client_sender
|
||||
.send(inbound_receiver_fut)
|
||||
{
|
||||
// Error register connection processor
|
||||
// Error registering connection processor
|
||||
error!("{}", e);
|
||||
break;
|
||||
}
|
||||
@ -201,7 +203,7 @@ impl RouterServer {
|
||||
.new_client_sender
|
||||
.send(inbound_receiver_fut)
|
||||
{
|
||||
// Error register connection processor
|
||||
// Error registering connection processor
|
||||
error!("{}", e);
|
||||
break;
|
||||
}
|
||||
@ -310,10 +312,112 @@ impl RouterServer {
|
||||
self,
|
||||
cmd: ServerProcessorCommand,
|
||||
outbound_sender: flume::Sender<ServerProcessorEvent>,
|
||||
) -> RouterServerResult<()> {
|
||||
match cmd {
|
||||
ServerProcessorCommand::Message(server_processor_message) => {
|
||||
self.process_message(
|
||||
server_processor_message.message_id,
|
||||
server_processor_message.request,
|
||||
outbound_sender,
|
||||
)
|
||||
.await
|
||||
}
|
||||
ServerProcessorCommand::CloseSocket {
|
||||
machine_id,
|
||||
socket_id,
|
||||
} => {
|
||||
self.process_close_socket(machine_id, socket_id, outbound_sender)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn process_close_socket(
|
||||
self,
|
||||
machine_id: MachineId,
|
||||
socket_id: SocketId,
|
||||
outbound_sender: flume::Sender<ServerProcessorEvent>,
|
||||
) -> RouterServerResult<()> {
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn process_message(
|
||||
self,
|
||||
message_id: MessageId,
|
||||
request: ServerProcessorRequest,
|
||||
outbound_sender: flume::Sender<ServerProcessorEvent>,
|
||||
) -> RouterServerResult<()> {
|
||||
match request {
|
||||
ServerProcessorRequest::AllocateMachine { profile } => todo!(),
|
||||
ServerProcessorRequest::ReleaseMachine { machine_id } => todo!(),
|
||||
ServerProcessorRequest::GetInterfaces { machine_id } => todo!(),
|
||||
ServerProcessorRequest::TcpConnect {
|
||||
machine_id,
|
||||
local_address,
|
||||
remote_address,
|
||||
timeout_ms,
|
||||
options,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::TcpBind {
|
||||
machine_id,
|
||||
local_address,
|
||||
options,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::TcpAccept {
|
||||
machine_id,
|
||||
listen_socket_id,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::TcpShutdown {
|
||||
machine_id,
|
||||
socket_id,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::UdpBind {
|
||||
machine_id,
|
||||
local_address,
|
||||
options,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::Send {
|
||||
machine_id,
|
||||
socket_id,
|
||||
data,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::SendTo {
|
||||
machine_id,
|
||||
socket_id,
|
||||
remote_address,
|
||||
data,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::Recv {
|
||||
machine_id,
|
||||
socket_id,
|
||||
len,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::RecvFrom {
|
||||
machine_id,
|
||||
socket_id,
|
||||
len,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::GetRoutedLocalAddress {
|
||||
machine_id,
|
||||
address_type,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::FindGateway { machine_id } => todo!(),
|
||||
ServerProcessorRequest::GetExternalAddress { gateway_id } => todo!(),
|
||||
ServerProcessorRequest::AddPort {
|
||||
gateway_id,
|
||||
protocol,
|
||||
external_port,
|
||||
local_address,
|
||||
lease_duration_ms,
|
||||
description,
|
||||
} => todo!(),
|
||||
ServerProcessorRequest::RemovePort {
|
||||
gateway_id,
|
||||
protocol,
|
||||
external_port,
|
||||
} => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RouterServer {
|
||||
|
Loading…
x
Reference in New Issue
Block a user