Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

-- Nothing yet

### Added

- Added command line `--help` and several options to multi-ping.
[#20](https://github.com/netsec-ethz/scion-java-multiping/pull/20)

## [0.5.0] - 2025-09-09

### Added
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ java -jar scion-multiping-0.5.0-executable.jar [tool-command]
Some tools require configuration files, see below in the tool description sections.
See also the troubleshooting section below in case of issues.

# Help

To get command line help, the tool can be executed with:

```
java -jar scion-multiping-0.5.0-executable.jar --help
```


# Download Assignments

The tool
Expand All @@ -34,7 +43,9 @@ Note: the `isd-as-assignments.csv` output file can be directly used as input fil

The tool
parses [Anapayas ISD/AS assignment website](https://docs.anapaya.net/en/latest/resources/isd-as-assignments/),
identifies the shortest path to each AS and sends a traceroute to each AS.
identifies the shortest or fastest path to each AS and sends a traceroute to each AS.
By default is will use the fastest path (determined by a traceroute over all paths), but it can be
configured to use the shortest path (`--shortest`).
It reports the number of paths to each AS as well as the shortest path with latency, remote IP, hop
count and remote IP.

Expand Down
87 changes: 83 additions & 4 deletions src/main/java/org/scion/multiping/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,35 @@
public class Main {

public static void main(String[] args) throws IOException {
if (args.length != 1) {
printUsage();
System.exit(1);
}
checkArgs(args, 1, Integer.MAX_VALUE);
String mode = args[0].toLowerCase(Locale.ROOT);
String[] newArgs = Arrays.copyOfRange(args, 1, args.length);
switch (mode) {
case "download-assignments":
{
checkArgs(args, 1, 1);
DownloadAssignments.main(newArgs);
return;
}
case "help":
{
printHelp(args.length == 1 ? "" : args[1]);
return;
}
case "ping-all":
{
PingAll.main(newArgs);
return;
}
case "ping-repeat":
{
checkArgs(args, 1, 1);
PingRepeat.main(newArgs);
return;
}
case "ping-responder":
{
checkArgs(args, 1, 1);
PingResponder.main(newArgs);
return;
}
Expand All @@ -55,6 +60,33 @@ public static void main(String[] args) throws IOException {
}
}

private static void checkArgs(String[] args, int minArgs, int maxArgs) {
if (args.length < minArgs || args.length > maxArgs) {
Util.println("Invalid number of arguments.");
printUsage();
System.exit(1);
}
}

private static void printHelp(String mode) {
switch (mode) {
case "download-assignments":
printUsageDownloadAssignments();
return;
case "ping-all":
printUsagePingAll();
return;
case "ping-repeat":
printUsagePingRepeat();
return;
case "ping-responder":
printUsagePingResponder();
return;
default:
printUsage();
}
}

private static void printUsage() {
Util.println("Usage: scion-multiping [MODE]");
Util.println("where MODE is one of: ");
Expand All @@ -65,6 +97,53 @@ private static void printUsage() {
" - `ping-repeat` for repeatedly probing (traceroute) multiple paths to multiple ASes.");
Util.println(
" - `ping-responder` for starting a server that responds to incoming echo requests.");
Util.println(" - `help [MODE]` for getting more help for a given mode.");
Util.println("");
}

private static void printUsageDownloadAssignments() {
Util.println("Usage: scion-multiping download-assignments");
Util.println();
Util.println(
" This tool downloads a list of known ISD/AS assignments and saves it to a file.");
Util.println(" The output file is called `isd-as-assignments.csv`.");
Util.println("");
}

static void printUsagePingAll() {
Util.println(
"Usage: ping-all [--help] [--fastest|--shortest|--shortest_echo|--fastest_sync] [--port <port>] [--shim]");
Util.println(" --help Show this help message.");
Util.println(" --fastest Use fastest path with SCMP traceroute (default).");
Util.println(
" The fastest path is determined by running a single traceroute on all path.");
// Util.println(" --fastest_sync Use fastest path with SCMP traceroute (synchronous)");
Util.println(" --shortest Use shortest path (fewest hops) with SCMP traceroute.");
// Util.println(" --shortest_echo Use shortest path with SCMP echo");
Util.println(
" --port <port> Use specified local port (default " + PingAll.localPort + ").");
Util.println(" --shim Start with SHIM enabled (default disabled).");
Util.println("");
}

private static void printUsagePingRepeat() {
Util.println("Usage: scion-multiping ping-repeat");
Util.println();
Util.println(
" This tool is used for repeatedly probing (traceroute) multiple paths to multiple ASes.");
Util.println(" The destination ASes are read from a file `isd-as-assignments.csv`.");
Util.println(" Other configuration options can be defined in `ping-repeat-config.json`.");
Util.println(" Results are written to a CSV file `ping-results.csv`.");
Util.println(" See README.md for more information.");
Util.println("");
}

private static void printUsagePingResponder() {
Util.println("Usage: scion-multiping ping-responder");
Util.println();
Util.println(" This command starts a server that responds to incoming echo requests.");
Util.println(" It takes a configuration file `ping-responder-config.json` as input.");
Util.println(" See README.md for more information.");
Util.println("");
}
}
64 changes: 57 additions & 7 deletions src/main/java/org/scion/multiping/PingAll.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ public class PingAll {
private static final boolean SHOW_ONLY_ICMP = false;
private static final Config config = new Config();

private static final int LOCAL_PORT = 30041;
private static final boolean STOP_SHIM = true;
static int localPort = 30041;
private static boolean startShim = false;

static {
config.tryICMP = false;
Expand Down Expand Up @@ -88,21 +88,71 @@ enum Policy {
this.service = service;
}

public static void main(String[] args) throws IOException {
public static void main(String[] argsArray) throws IOException {
PRINT = true;
// System.setProperty(Constants.PROPERTY_DNS_SEARCH_DOMAINS, "ethz.ch.");
System.setProperty(Constants.PROPERTY_SHIM, STOP_SHIM ? "false" : "true"); // disable SHIM

Policy policy = parseArgs(argsArray);

System.setProperty(Constants.PROPERTY_SHIM, startShim ? "true" : "false"); // disable SHIM

println("Settings:");
println(" Path policy = " + DEFAULT_POLICY);
println(" Path policy = " + policy);
println(" ICMP=" + config.tryICMP);
println(" printOnlyICMP=" + SHOW_ONLY_ICMP);

PingAll pingAll = new PingAll(DEFAULT_POLICY, ScionProvider.defaultProvider(LOCAL_PORT));
PingAll pingAll = new PingAll(policy, ScionProvider.defaultProvider(localPort));
pingAll.run();
pingAll.summary.prettyPrint();
}

private static Policy parseArgs(String[] argsArray) {
List<String> args = new ArrayList<>(Arrays.asList(argsArray));
Policy policy = DEFAULT_POLICY;
while (!args.isEmpty()) {
switch (args.get(0)) {
case "--fastest":
policy = Policy.FASTEST_TR_ASYNC;
break;
case "--shortest":
policy = Policy.SHORTEST_TR;
break;
case "--shortest_echo":
policy = Policy.SHORTEST_ECHO;
break;
case "--fastest_sync":
policy = Policy.FASTEST_TR;
break;
case "--help":
Main.printUsagePingAll();
System.exit(0);
case "--shim":
startShim = true;
break;
case "--port":
if (args.size() < 2) {
Util.println("Error: --port requires a port number");
Main.printUsagePingAll();
System.exit(1);
}
try {
localPort = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
Util.println("Error: Invalid port number: " + args.get(1));
Main.printUsagePingAll();
System.exit(1);
}
args.remove(1);
break;
default:
Util.println("Unknown option: " + args.get(0));
Main.printUsagePingAll();
System.exit(1);
}
args.remove(0);
}
return policy;
}

ResultSummary run() throws IOException {
List<ParseAssignments.HostEntry> allASes = service.getIsdAsEntries();
// remove entry for local AS
Expand Down
Loading