Skip to content

Commit

Permalink
feat(config): restrict flows to Paris and Dublin strategies (#1007)
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiapple852 committed Mar 2, 2024
1 parent 7c098c6 commit 2344531
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
34 changes: 29 additions & 5 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ pub enum Mode {
Tui,
/// Display a continuous stream of tracing data
Stream,
/// Generate an pretty text table report for N cycles.
/// Generate a pretty text table report for N cycles.
Pretty,
/// Generate a markdown text table report for N cycles.
/// Generate a Markdown text table report for N cycles.
Markdown,
/// Generate a CSV report for N cycles.
Csv,
/// Generate a JSON report for N cycles.
Json,
/// Generate a Graphviz DOT file for N cycles.
Dot,
/// Display all flows.
/// Display all flows for N cycles.
Flows,
/// Do not generate any tracing output for N cycles.
Silent,
Expand Down Expand Up @@ -334,6 +334,16 @@ impl TrippyConfig {
Self::build_config(args, cfg_file, platform)
}

/// The maximum number of flows allowed.
///
/// This is restricted to 1 for the classic strategy.
pub fn max_flows(&self) -> usize {
match self.multipath_strategy {
MultipathStrategy::Classic => 1,
_ => self.tui_max_flows,
}
}

#[allow(clippy::too_many_lines)]
fn build_config(args: Args, cfg_file: ConfigFile, platform: &Platform) -> anyhow::Result<Self> {
let &Platform {
Expand Down Expand Up @@ -641,6 +651,7 @@ impl TrippyConfig {
validate_strategy(multipath_strategy, unprivileged)?;
validate_protocol_strategy(protocol, multipath_strategy)?;
validate_multi(mode, protocol, &args.targets, dns_resolve_all)?;
validate_flows(mode, multipath_strategy)?;
validate_ttl(first_ttl, max_ttl)?;
validate_max_inflight(max_inflight)?;
validate_read_timeout(read_timeout)?;
Expand Down Expand Up @@ -918,6 +929,17 @@ fn validate_multi(
}
}

/// Validate that flows and dot mode are only used with udp protocol and paris
/// or dublin multipath strategy.
fn validate_flows(mode: Mode, strategy: MultipathStrategy) -> anyhow::Result<()> {
match (mode, strategy) {
(Mode::Flows | Mode::Dot, MultipathStrategy::Classic) => Err(anyhow!(
"this mode requires udp protocol with paris or dublin multipath strategy"
)),
_ => Ok(()),
}
}

/// Validate `first_ttl` and `max_ttl`.
fn validate_ttl(first_ttl: u8, max_ttl: u8) -> anyhow::Result<()> {
if (first_ttl as usize) < 1 || (first_ttl as usize) > MAX_HOPS {
Expand Down Expand Up @@ -1150,11 +1172,13 @@ mod tests {
#[test_case("trip example.com --mode markdown", Ok(cfg().mode(Mode::Markdown).max_rounds(Some(10)).build()); "markdown mode")]
#[test_case("trip example.com --mode csv", Ok(cfg().mode(Mode::Csv).max_rounds(Some(10)).build()); "csv mode")]
#[test_case("trip example.com --mode json", Ok(cfg().mode(Mode::Json).max_rounds(Some(10)).build()); "json mode")]
#[test_case("trip example.com --mode dot", Ok(cfg().mode(Mode::Dot).max_rounds(Some(10)).build()); "dot mode")]
#[test_case("trip example.com --mode flows", Ok(cfg().mode(Mode::Flows).max_rounds(Some(10)).build()); "flows mode")]
#[test_case("trip example.com --mode dot --udp -R paris", Ok(cfg().mode(Mode::Dot).max_rounds(Some(10)).multipath_strategy(MultipathStrategy::Paris).protocol(Protocol::Udp).port_direction(PortDirection::FixedSrc(Port(1024))).build()); "dot mode")]
#[test_case("trip example.com --mode flows --udp -R paris", Ok(cfg().mode(Mode::Flows).max_rounds(Some(10)).multipath_strategy(MultipathStrategy::Paris).protocol(Protocol::Udp).port_direction(PortDirection::FixedSrc(Port(1024))).build()); "flows mode")]
#[test_case("trip example.com --mode silent", Ok(cfg().mode(Mode::Silent).max_rounds(Some(10)).build()); "silent mode")]
#[test_case("trip example.com -m tui", Ok(cfg().mode(Mode::Tui).build()); "tui mode short")]
#[test_case("trip example.com --mode foo", Err(anyhow!(format!("error: one of the values isn't valid for an argument"))); "invalid mode")]
#[test_case("trip example.com --mode dot", Err(anyhow!(format!("this mode requires udp protocol with paris or dublin multipath strategy"))); "invalid dot mode")]
#[test_case("trip example.com --mode flows", Err(anyhow!(format!("this mode requires udp protocol with paris or dublin multipath strategy"))); "invalid flows mode")]
fn test_mode(cmd: &str, expected: anyhow::Result<TrippyConfig>) {
compare(parse_config(cmd), expected);
}
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ fn start_tracer(
tracer_config,
channel_config,
cfg.tui_max_samples,
cfg.tui_max_flows,
cfg.max_flows(),
);
let trace_data = backend.trace();
thread::Builder::new()
Expand Down Expand Up @@ -344,7 +344,7 @@ fn make_tui_config(args: &TrippyConfig) -> TuiConfig {
args.tui_geoip_mode,
args.tui_max_addrs,
args.tui_max_samples,
args.tui_max_flows,
args.max_flows(),
args.tui_theme,
&args.tui_bindings,
&args.tui_custom_columns,
Expand Down
9 changes: 6 additions & 3 deletions trippy-config-sample.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
# Allowed values are:
# tui - Display interactive Tui [default]
# stream - Display a continuous stream of tracing data
# pretty - Generate an pretty text table report for N cycles
# markdown - Generate a markdown text table report for N cycles
# pretty - Generate a pretty text table report for N cycles
# markdown - Generate a Markdown text table report for N cycles
# csv - Generate a CSV report for N cycles
# json - Generate a JSON report for N cycles
# dot - Generate a Graphviz DOT report for N cycles
# flows - Display all flows
# flows - Display all flows for N cycles
# silent - Do not generate any output for N cycles
#
# Note: the dot and flows modes are only allowed with paris or dublin
# multipath strategy.
mode = "tui"

# Trace without requiring elevated privileges [default: false]
Expand Down

0 comments on commit 2344531

Please sign in to comment.