Skip to content

Commit 3a4d249

Browse files
author
Tilmann Zäschke
committed
0.6.0!!!
1 parent 2b10b9a commit 3a4d249

File tree

7 files changed

+381
-32
lines changed

7 files changed

+381
-32
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
<dependency>
8484
<groupId>org.scion</groupId>
8585
<artifactId>jpan</artifactId>
86-
<version>0.5.3</version>
86+
<version>0.6.0-SNAPSHOT</version>
8787
</dependency>
8888

8989
<dependency>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2025 ETH Zurich
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package org.scion.jpan;
16+
17+
import com.google.protobuf.ByteString;
18+
import org.scion.jpan.proto.daemon.Daemon;
19+
20+
import java.net.InetAddress;
21+
import java.net.UnknownHostException;
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
25+
public class PathHelper {
26+
27+
public static List<Path> createPaths(int n) {
28+
List<Path> paths = new ArrayList<>();
29+
for (int i = 0; i < n; i++) {
30+
Daemon.Path.Builder builder = Daemon.Path.newBuilder();
31+
builder.setRaw(ByteString.copyFrom(new byte[]{}));
32+
try {
33+
InetAddress dst = InetAddress.getByAddress(new byte[]{123, 123, 123, 123});
34+
paths.add(RequestPath.create(builder.build(), n + 1, dst, 12345));
35+
} catch (UnknownHostException e) {
36+
throw new ScionRuntimeException("Unable to create test path", e);
37+
}
38+
}
39+
return paths;
40+
}
41+
42+
}

src/main/java/org/scion/multiping/PingAll.java

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,14 @@ public class PingAll {
7474
private int nPathSuccess = 0;
7575
private int nPathTimeout = 0;
7676

77-
private static final Set<Long> listedAs = new HashSet<>();
78-
private static final Set<Long> seenAs = new HashSet<>();
79-
private static final List<Result> results = new ArrayList<>();
77+
private final Set<Long> listedAs = new HashSet<>();
78+
private final Set<Long> seenAs = new HashSet<>();
79+
private final List<Result> results = new ArrayList<>();
8080

81-
private enum Policy {
81+
private final ScmpProvider service;
82+
private Policy policy = Policy.FASTEST_TR_ASYNC;
83+
84+
enum Policy {
8285
/** Fastest path using SCMP traceroute */
8386
FASTEST_TR,
8487
/** Fastest path using SCMP async traceroute */
@@ -90,28 +93,37 @@ private enum Policy {
9093
SHORTEST_ECHO
9194
}
9295

93-
private static final Policy POLICY = Policy.FASTEST_TR_ASYNC;
96+
private static Policy DEFAULT_POLICY = Policy.FASTEST_TR_ASYNC;
9497
private static final boolean SHOW_PATH = false;
9598

99+
PingAll(Policy policy, ScmpProvider service) {
100+
this.policy = policy;
101+
this.service = service;
102+
}
103+
96104
public static void main(String[] args) throws IOException {
97105
PRINT = true;
98106
// System.setProperty(Constants.PROPERTY_DNS_SEARCH_DOMAINS, "ethz.ch.");
99107
System.setProperty(Constants.PROPERTY_SHIM, STOP_SHIM ? "false" : "true"); // disable SHIM
100108

101109
println("Settings:");
102-
println(" Path policy = " + POLICY);
110+
println(" Path policy = " + DEFAULT_POLICY);
103111
println(" ICMP=" + config.tryICMP);
104112
println(" printOnlyICMP=" + SHOW_ONLY_ICMP);
105113

106-
PingAll demo = new PingAll();
107-
List<ParseAssignments.HostEntry> allASes = DownloadAssignmentsFromWeb.getList();
114+
PingAll pingAll = new PingAll(DEFAULT_POLICY, ScmpProvider.defaultProvider(localPort));
115+
pingAll.run();
116+
}
117+
118+
void run() throws IOException {
119+
List<ParseAssignments.HostEntry> allASes = service.getIsdAsEntries();
108120
// remove entry for local AS
109121
long localAS = Scion.defaultService().getLocalIsdAs();
110122
allASes = allASes.stream().filter(e -> e.getIsdAs() != localAS).collect(Collectors.toList());
111123
// Process all ASes
112124
for (ParseAssignments.HostEntry e : allASes) {
113125
print(ScionUtil.toStringIA(e.getIsdAs()) + " \"" + e.getName() + "\" ");
114-
demo.runDemo(e);
126+
runAS(e);
115127
listedAs.add(e.getIsdAs());
116128
}
117129

@@ -151,26 +163,25 @@ public static void main(String[] args) throws IOException {
151163

152164
println("");
153165
println("AS Stats:");
154-
println(" all = " + demo.nAsTried);
155-
println(" success = " + demo.nAsSuccess);
156-
println(" no path = " + demo.nAsNoPathFound);
157-
println(" timeout = " + demo.nAsTimeout);
158-
println(" error = " + demo.nAsError);
166+
println(" all = " + nAsTried);
167+
println(" success = " + nAsSuccess);
168+
println(" no path = " + nAsNoPathFound);
169+
println(" timeout = " + nAsTimeout);
170+
println(" error = " + nAsError);
159171
println(" not listed = " + nSeenButNotListed);
160172
println("Path Stats:");
161-
println(" all = " + demo.nPathTried);
162-
println(" success = " + demo.nPathSuccess);
163-
println(" timeout = " + demo.nPathTimeout);
173+
println(" all = " + nPathTried);
174+
println(" success = " + nPathSuccess);
175+
println(" timeout = " + nPathTimeout);
164176
println("ICMP Stats:");
165177
println(" all = " + ICMP.nIcmpTried);
166178
println(" success = " + ICMP.nIcmpSuccess);
167179
println(" timeout = " + ICMP.nIcmpTimeout);
168180
println(" error = " + ICMP.nIcmpError);
169181
}
170182

171-
private void runDemo(ParseAssignments.HostEntry remote) throws IOException {
183+
private void runAS(ParseAssignments.HostEntry remote) throws IOException {
172184
nAsTried++;
173-
ScionService service = Scion.defaultService();
174185
// Dummy address. The traceroute will contact the control service IP instead.
175186
InetSocketAddress destinationAddress =
176187
new InetSocketAddress(InetAddress.getByAddress(new byte[] {0, 0, 0, 0}), 30041);
@@ -191,9 +202,16 @@ private void runDemo(ParseAssignments.HostEntry remote) throws IOException {
191202
}
192203
nPaths = paths.size();
193204
msg[0] = findPaths(paths, bestPath);
194-
if (msg[0] != null && REPEAT > 1) {
195-
try (ScmpSender sender = Scmp.newSenderBuilder().setLocalPort(localPort).build()) {
205+
if (bestPath.get() == null) {
206+
nAsTimeout++;
207+
}
208+
// bestPath is null if all paths have timed out
209+
if (msg[0] != null && bestPath.get() != null && REPEAT > 1) {
210+
try (ScmpProvider.Sync sender = service.getSync()) {
196211
for (int i = 1; i < msg.length; i++) {
212+
if (bestPath.get() == null) {
213+
break;
214+
}
197215
List<Scmp.TracerouteMessage> messages = sender.sendTracerouteRequest(bestPath.get());
198216
msg[i] = messages.get(messages.size() - 1);
199217
}
@@ -249,7 +267,7 @@ private void runDemo(ParseAssignments.HostEntry remote) throws IOException {
249267
}
250268

251269
private Scmp.TimedMessage findPaths(List<Path> paths, Ref<Path> bestOut) {
252-
switch (POLICY) {
270+
switch (policy) {
253271
case FASTEST_TR:
254272
return findFastestTR(paths, bestOut);
255273
case FASTEST_TR_ASYNC:
@@ -267,7 +285,7 @@ private Scmp.EchoMessage findShortestEcho(List<Path> paths, Ref<Path> refBest) {
267285
Path path = PathPolicy.MIN_HOPS.filter(paths).get(0);
268286
refBest.set(path);
269287
ByteBuffer bb = ByteBuffer.allocate(0);
270-
try (ScmpSender sender = Scmp.newSenderBuilder().setLocalPort(localPort).build()) {
288+
try (ScmpProvider.Sync sender = service.getSync()) {
271289
nPathTried++;
272290
Scmp.EchoMessage msg = sender.sendEchoRequest(path, bb);
273291
if (msg == null) {
@@ -294,7 +312,7 @@ private Scmp.EchoMessage findShortestEcho(List<Path> paths, Ref<Path> refBest) {
294312
private Scmp.TracerouteMessage findShortestTR(List<Path> paths, Ref<Path> refBest) {
295313
Path path = PathPolicy.MIN_HOPS.filter(paths).get(0);
296314
refBest.set(path);
297-
try (ScmpSender sender = Scmp.newSenderBuilder().setLocalPort(localPort).build()) {
315+
try (ScmpProvider.Sync sender = service.getSync()) {
298316
nPathTried++;
299317
List<Scmp.TracerouteMessage> messages = sender.sendTracerouteRequest(path);
300318
if (messages.isEmpty()) {
@@ -325,7 +343,7 @@ private Scmp.TracerouteMessage findShortestTR(List<Path> paths, Ref<Path> refBes
325343

326344
private Scmp.TracerouteMessage findFastestTR(List<Path> paths, Ref<Path> refBest) {
327345
Scmp.TracerouteMessage best = null;
328-
try (ScmpSender sender = Scmp.newSenderBuilder().setLocalPort(localPort).build()) {
346+
try (ScmpProvider.Sync sender = service.getSync()) {
329347
for (Path path : paths) {
330348
nPathTried++;
331349
List<Scmp.TracerouteMessage> messages = sender.sendTracerouteRequest(path);
@@ -390,8 +408,7 @@ public void onException(Throwable t) {
390408
};
391409

392410
Scmp.TracerouteMessage best = null;
393-
try (ScmpSenderAsync sender =
394-
Scmp.newSenderAsyncBuilder(handler).setLocalPort(localPort).build()) {
411+
try (ScmpProvider.Async sender = service.getAsync(handler)) {
395412
for (Path path : paths) {
396413
nPathTried++;
397414
int id = sender.sendTracerouteLast(path);
@@ -442,15 +459,15 @@ public void onException(Throwable t) {
442459
return best;
443460
}
444461

445-
private static double avg(Predicate<Result> filter, ToDoubleFunction<Result> mapper) {
462+
private double avg(Predicate<Result> filter, ToDoubleFunction<Result> mapper) {
446463
return results.stream().filter(filter).mapToDouble(mapper).average().orElse(-1);
447464
}
448465

449-
private static Result max(Predicate<Result> filter, Comparator<Result> comparator) {
466+
private Result max(Predicate<Result> filter, Comparator<Result> comparator) {
450467
return results.stream().filter(filter).max(comparator).orElseThrow(NoSuchElementException::new);
451468
}
452469

453-
private static <T> double median(Predicate<Result> filter, Function<Result, T> mapper) {
470+
private <T> double median(Predicate<Result> filter, Function<Result, T> mapper) {
454471
List<T> list =
455472
results.stream().filter(filter).map(mapper).sorted().collect(Collectors.toList());
456473
if (list.isEmpty()) {

src/main/java/org/scion/multiping/util/Result.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public Result(ParseAssignments.HostEntry e, Scmp.TimedMessage msg, Path request,
5757
}
5858
this.nPaths = nPaths;
5959
this.path = request;
60-
nHops = PathRawParser.create(request.getRawPath()).getHopCount();
60+
nHops = request != null ? PathRawParser.create(request.getRawPath()).getHopCount() : -1;
6161
remoteIP = msg.getPath().getRemoteAddress().getHostAddress();
6262
if (msg.isTimedOut()) {
6363
state = State.TIMEOUT;
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2025 ETH Zurich
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package org.scion.multiping.util;
16+
17+
import org.scion.jpan.*;
18+
19+
import java.io.IOException;
20+
import java.net.InetSocketAddress;
21+
import java.nio.ByteBuffer;
22+
import java.util.List;
23+
import java.util.function.BiFunction;
24+
import java.util.function.Function;
25+
import java.util.function.Supplier;
26+
27+
public class ScmpProvider {
28+
29+
public interface Async extends AutoCloseable {
30+
int sendTracerouteLast(Path path) throws IOException;
31+
32+
void close() throws IOException;
33+
}
34+
35+
public interface Sync extends AutoCloseable {
36+
Scmp.EchoMessage sendEchoRequest(Path path, ByteBuffer bb) throws IOException;
37+
38+
List<Scmp.TracerouteMessage> sendTracerouteRequest(Path path) throws IOException;
39+
40+
void close() throws IOException;
41+
}
42+
43+
private static class AsyncDefault implements Async {
44+
private final ScmpSenderAsync sender;
45+
AsyncDefault(ScmpSenderAsync sender) {
46+
this.sender = sender;
47+
}
48+
49+
@Override
50+
public int sendTracerouteLast(Path path) throws IOException {
51+
return sender.sendTracerouteLast(path);
52+
}
53+
54+
@Override
55+
public void close() throws IOException {
56+
sender.close();
57+
}
58+
}
59+
60+
private static class SyncDefault implements Sync {
61+
private final ScmpSender sender;
62+
SyncDefault(ScmpSender sender) {
63+
this.sender = sender;
64+
}
65+
66+
@Override
67+
public Scmp.EchoMessage sendEchoRequest(Path path, ByteBuffer bb) throws IOException {
68+
return sender.sendEchoRequest(path, bb);
69+
}
70+
71+
@Override
72+
public List<Scmp.TracerouteMessage> sendTracerouteRequest(Path path) throws IOException {
73+
return sender.sendTracerouteRequest(path);
74+
}
75+
76+
@Override
77+
public void close() throws IOException {
78+
sender.close();
79+
}
80+
}
81+
82+
private final Supplier<Sync> senderSupplier;
83+
private final Function<ScmpSenderAsync.ResponseHandler, Async> senderAsyncSupplier;
84+
private final Supplier<List<ParseAssignments.HostEntry>> assignmentSupplier;
85+
private final Supplier<Long> localIsdAsSupplier;
86+
private final BiFunction<Long, InetSocketAddress, List<Path>> localDefaultPathsSupplier;
87+
88+
public static ScmpProvider defaultProvider(int localPort) {
89+
return new ScmpProvider(() -> new SyncDefault(Scmp.newSenderBuilder().setLocalPort(localPort).build()),
90+
handler -> new AsyncDefault(Scmp.newSenderAsyncBuilder(handler).setLocalPort(localPort).build()),
91+
DownloadAssignmentsFromWeb::getList,
92+
()->Scion.defaultService().getLocalIsdAs(),
93+
(isdAs, address) -> Scion.defaultService().getPaths(isdAs, address)
94+
);
95+
}
96+
97+
public static ScmpProvider createAsync(
98+
Function<ScmpSenderAsync.ResponseHandler, Async> senderAsyncSupplier,
99+
Supplier<List<ParseAssignments.HostEntry>> assignmentSupplier,
100+
Supplier<Long> localIsdAs,
101+
BiFunction<Long, InetSocketAddress, List<Path>> paths) {
102+
return new ScmpProvider(null, senderAsyncSupplier, assignmentSupplier, localIsdAs, paths);
103+
}
104+
105+
public static ScmpProvider createSync(Supplier<Sync> senderSupplier,
106+
Supplier<List<ParseAssignments.HostEntry>> assignmentSupplier,
107+
Supplier<Long> localIsdAsSupplier,
108+
BiFunction<Long, InetSocketAddress, List<Path>> localDefaultPathsSupplier) {
109+
return new ScmpProvider(senderSupplier, null, assignmentSupplier, localIsdAsSupplier, localDefaultPathsSupplier);
110+
}
111+
112+
private ScmpProvider(Supplier<Sync> senderSupplier,
113+
Function<ScmpSenderAsync.ResponseHandler, Async> senderAsyncSupplier,
114+
Supplier<List<ParseAssignments.HostEntry>> assignmentSupplier,
115+
Supplier<Long> localIsdAsSupplier,
116+
BiFunction<Long, InetSocketAddress, List<Path>> localDefaultPathsSupplier) {
117+
this.assignmentSupplier = assignmentSupplier;
118+
this.senderSupplier = senderSupplier;
119+
this.senderAsyncSupplier = senderAsyncSupplier;
120+
this.localIsdAsSupplier = localIsdAsSupplier;
121+
this.localDefaultPathsSupplier = localDefaultPathsSupplier;
122+
}
123+
124+
public List<ParseAssignments.HostEntry> getIsdAsEntries() {
125+
return assignmentSupplier.get();
126+
}
127+
128+
public Async getAsync(ScmpSenderAsync.ResponseHandler handler) {
129+
return senderAsyncSupplier.apply(handler);
130+
}
131+
132+
public Sync getSync() {
133+
return senderSupplier.get();
134+
}
135+
136+
public List<Path> getPaths(long isdAs, InetSocketAddress destinationAddress) {
137+
return localDefaultPathsSupplier.apply(isdAs, destinationAddress);
138+
}
139+
140+
public long getLocalIsdAs() {
141+
return localIsdAsSupplier.get();
142+
}
143+
144+
}

0 commit comments

Comments
 (0)