test(java-oracle): ArpRun records ARP as Java FILIUS runs it
Sends to addresses no card has on the new arp-routed network (ping on the LAN and behind a router, two UDP datagrams, one behind a failing one): frames and calls. ScenarioNetwork builds routers and their interfaces. Measured: ARP asks twice, a round trip each, then host unreachable; the thread that waits is the ping's caller, the router's IP thread, or the node's transport thread per protocol, which blocks the next send. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"frames": {
|
||||
"00000000-0000-0000-0000-000000000301": [
|
||||
{
|
||||
"time": 716,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3467,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000302": [
|
||||
{
|
||||
"time": 837,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3578,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000303": []
|
||||
},
|
||||
"events": [
|
||||
[
|
||||
712,
|
||||
"sendProbe 10.0.0.9 called"
|
||||
],
|
||||
[
|
||||
6222,
|
||||
"sendProbe 10.0.0.9 returned ICMP 3/1 from 127.0.0.1"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"frames": {
|
||||
"00000000-0000-0000-0000-000000000301": [
|
||||
{
|
||||
"time": 720,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.1"
|
||||
},
|
||||
{
|
||||
"time": 955,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"arp": 2,
|
||||
"senderIp": "10.0.0.1",
|
||||
"targetIp": "10.0.0.2"
|
||||
},
|
||||
{
|
||||
"time": 959,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "02:00:00:00:03:21",
|
||||
"icmp": 8
|
||||
},
|
||||
{
|
||||
"time": 6685,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"icmp": 3
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000302": [
|
||||
{
|
||||
"time": 841,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.1"
|
||||
},
|
||||
{
|
||||
"time": 843,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"arp": 2,
|
||||
"senderIp": "10.0.0.1",
|
||||
"targetIp": "10.0.0.2"
|
||||
},
|
||||
{
|
||||
"time": 1072,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "02:00:00:00:03:21",
|
||||
"icmp": 8
|
||||
},
|
||||
{
|
||||
"time": 6574,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"icmp": 3
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000303": [
|
||||
{
|
||||
"time": 1128,
|
||||
"source": "02:00:00:00:03:22",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "20.0.0.1",
|
||||
"targetIp": "20.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3878,
|
||||
"source": "02:00:00:00:03:22",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "20.0.0.1",
|
||||
"targetIp": "20.0.0.9"
|
||||
}
|
||||
]
|
||||
},
|
||||
"events": [
|
||||
[
|
||||
716,
|
||||
"sendProbe 20.0.0.9 called"
|
||||
],
|
||||
[
|
||||
3709,
|
||||
"sendProbe 20.0.0.9 returned null"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"frames": {
|
||||
"00000000-0000-0000-0000-000000000301": [
|
||||
{
|
||||
"time": 724,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3475,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 6230,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.1"
|
||||
},
|
||||
{
|
||||
"time": 6453,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"arp": 2,
|
||||
"senderIp": "10.0.0.1",
|
||||
"targetIp": "10.0.0.2"
|
||||
},
|
||||
{
|
||||
"time": 6453,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "02:00:00:00:03:21",
|
||||
"sourceIp": "10.0.0.2",
|
||||
"destinationIp": "20.0.0.2",
|
||||
"protocol": 17,
|
||||
"sourcePort": 64055,
|
||||
"destinationPort": 9,
|
||||
"payload": "dahinter"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000302": [
|
||||
{
|
||||
"time": 846,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3586,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 6341,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.1"
|
||||
},
|
||||
{
|
||||
"time": 6342,
|
||||
"source": "02:00:00:00:03:21",
|
||||
"destination": "02:00:00:00:03:11",
|
||||
"arp": 2,
|
||||
"senderIp": "10.0.0.1",
|
||||
"targetIp": "10.0.0.2"
|
||||
},
|
||||
{
|
||||
"time": 6566,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "02:00:00:00:03:21",
|
||||
"sourceIp": "10.0.0.2",
|
||||
"destinationIp": "20.0.0.2",
|
||||
"protocol": 17,
|
||||
"sourcePort": 64055,
|
||||
"destinationPort": 9,
|
||||
"payload": "dahinter"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000303": [
|
||||
{
|
||||
"time": 6622,
|
||||
"source": "02:00:00:00:03:22",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "20.0.0.1",
|
||||
"targetIp": "20.0.0.2"
|
||||
},
|
||||
{
|
||||
"time": 6622,
|
||||
"source": "02:00:00:00:03:13",
|
||||
"destination": "02:00:00:00:03:22",
|
||||
"arp": 2,
|
||||
"senderIp": "20.0.0.2",
|
||||
"targetIp": "20.0.0.1"
|
||||
},
|
||||
{
|
||||
"time": 6733,
|
||||
"source": "02:00:00:00:03:22",
|
||||
"destination": "02:00:00:00:03:13",
|
||||
"sourceIp": "10.0.0.2",
|
||||
"destinationIp": "20.0.0.2",
|
||||
"protocol": 17,
|
||||
"sourcePort": 64055,
|
||||
"destinationPort": 9,
|
||||
"payload": "dahinter"
|
||||
}
|
||||
]
|
||||
},
|
||||
"events": [
|
||||
[
|
||||
716,
|
||||
"senden verloren called"
|
||||
],
|
||||
[
|
||||
720,
|
||||
"senden verloren returned "
|
||||
],
|
||||
[
|
||||
720,
|
||||
"senden dahinter called"
|
||||
],
|
||||
[
|
||||
6230,
|
||||
"senden dahinter returned "
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"frames": {
|
||||
"00000000-0000-0000-0000-000000000301": [
|
||||
{
|
||||
"time": 722,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3473,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 6228,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 8978,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000302": [
|
||||
{
|
||||
"time": 844,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 3584,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 6339,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
},
|
||||
{
|
||||
"time": 9090,
|
||||
"source": "02:00:00:00:03:11",
|
||||
"destination": "FF:FF:FF:FF:FF:FF",
|
||||
"arp": 1,
|
||||
"senderIp": "10.0.0.2",
|
||||
"targetIp": "10.0.0.9"
|
||||
}
|
||||
],
|
||||
"00000000-0000-0000-0000-000000000303": []
|
||||
},
|
||||
"events": [
|
||||
[
|
||||
713,
|
||||
"senden eins called"
|
||||
],
|
||||
[
|
||||
718,
|
||||
"senden eins returned "
|
||||
],
|
||||
[
|
||||
718,
|
||||
"senden zwei called"
|
||||
],
|
||||
[
|
||||
6228,
|
||||
"senden zwei returned "
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"seed": 61,
|
||||
"nodes": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000301",
|
||||
"kind": "pc",
|
||||
"ports": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000311",
|
||||
"label": "eth0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000302",
|
||||
"kind": "router",
|
||||
"ports": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000321",
|
||||
"label": "eth0"
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000322",
|
||||
"label": "eth1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000303",
|
||||
"kind": "pc",
|
||||
"ports": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000313",
|
||||
"label": "eth0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000304",
|
||||
"kind": "networkSwitch",
|
||||
"ports": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000341",
|
||||
"label": "sw1"
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000342",
|
||||
"label": "sw2"
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-000000000343",
|
||||
"label": "sw3"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000000F301",
|
||||
"sourceNode": "00000000-0000-0000-0000-000000000301",
|
||||
"sourcePort": "00000000-0000-0000-0000-000000000311",
|
||||
"targetNode": "00000000-0000-0000-0000-000000000304",
|
||||
"targetPort": "00000000-0000-0000-0000-000000000341"
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000000F302",
|
||||
"sourceNode": "00000000-0000-0000-0000-000000000302",
|
||||
"sourcePort": "00000000-0000-0000-0000-000000000321",
|
||||
"targetNode": "00000000-0000-0000-0000-000000000304",
|
||||
"targetPort": "00000000-0000-0000-0000-000000000342"
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000000F303",
|
||||
"sourceNode": "00000000-0000-0000-0000-000000000302",
|
||||
"sourcePort": "00000000-0000-0000-0000-000000000322",
|
||||
"targetNode": "00000000-0000-0000-0000-000000000303",
|
||||
"targetPort": "00000000-0000-0000-0000-000000000313"
|
||||
}
|
||||
],
|
||||
"devices": {
|
||||
"00000000-0000-0000-0000-000000000301": {
|
||||
"ip": "10.0.0.2",
|
||||
"mask": "255.255.255.0",
|
||||
"gateway": "10.0.0.1"
|
||||
},
|
||||
"00000000-0000-0000-0000-000000000302": {
|
||||
"ip": "10.0.0.1",
|
||||
"mask": "255.255.255.0"
|
||||
},
|
||||
"00000000-0000-0000-0000-000000000303": {
|
||||
"ip": "20.0.0.2",
|
||||
"mask": "255.255.255.0",
|
||||
"gateway": "20.0.0.1"
|
||||
}
|
||||
},
|
||||
"interfaces": [
|
||||
{
|
||||
"node": "00000000-0000-0000-0000-000000000302",
|
||||
"port": "00000000-0000-0000-0000-000000000321",
|
||||
"ip": "10.0.0.1",
|
||||
"mask": "255.255.255.0"
|
||||
},
|
||||
{
|
||||
"node": "00000000-0000-0000-0000-000000000302",
|
||||
"port": "00000000-0000-0000-0000-000000000322",
|
||||
"ip": "20.0.0.1",
|
||||
"mask": "255.255.255.0"
|
||||
}
|
||||
],
|
||||
"steps": []
|
||||
}
|
||||
@@ -247,3 +247,29 @@ unbekannten Namen (leere Antwort), und ein Verweis steht mit NS und A des
|
||||
Nameservers im Antwortteil. Der Resolver folgt dem Verweis selbst
|
||||
(iterativ) und wartet je Anfrage 5 RTT (13750 ms bei 90 %); ohne Server
|
||||
fragt ARP zweimal im Abstand einer RTT, dann scheitert der Aufruf.
|
||||
|
||||
## ARP zur Laufzeit
|
||||
|
||||
`ArpRun` sendet auf dem Netz von `arp-routed` (10.0.0.2 über einen Switch am
|
||||
Router 10.0.0.1, 20.0.0.2 am Router 20.0.0.1; `ScenarioNetwork` baut dazu
|
||||
Router mit `setzeAnzahlAnschluesse` und den `interfaces` des Szenarios) an
|
||||
Adressen, die keine Karte hat, und schreibt nach `arp-java-<ablauf>.java.json`
|
||||
die Frames und die Aufrufe. Abläufe: `pingLan` (Ping an 10.0.0.9,
|
||||
`ICMP.sendProbe`), `pingRouted` (Ping an 20.0.0.9), `udpTwice` (zwei
|
||||
Datagramme an 10.0.0.9), `udpBehind` (eines an 10.0.0.9, dann eines an
|
||||
20.0.0.2).
|
||||
|
||||
Gemessen (30.09.2026), was der Kern (nach Swift) anders macht:
|
||||
|
||||
* ARP fragt bis zu zweimal und wartet je eine RTT (`holeARPTabellenEintrag(ziel,
|
||||
2, …)`); dann „Host unreachable" (ICMP 3/1). Einen Negativ-Cache gibt es
|
||||
nicht: das nächste Paket fragt wieder zweimal.
|
||||
* Wer wartet, ist ein Thread: beim Ping der Aufrufer (5,5 s, dann ICMP 3/1
|
||||
vom eigenen Rechner, Absender 127.0.0.1), beim Weiterleiten der IP-Thread
|
||||
des Routers, bei UDP und TCP der Transport-Thread je Protokoll und Knoten.
|
||||
`senden` kehrt sofort zurück, aber der Transport-Thread hält seine
|
||||
Warteschlange gesperrt, solange er wartet: das nächste `senden` blockiert
|
||||
bis dahin (5,5 s), und ein Datagramm an einen erreichbaren Rechner geht
|
||||
erst danach.
|
||||
* Ein Ping wartet eine RTT auf die Antwort; das „Host unreachable" des
|
||||
Routers (nach dessen 5,5 s) kommt zu spät.
|
||||
|
||||
@@ -21,7 +21,7 @@ if [ ! -f "$upstream/target/filius.jar" ]; then
|
||||
fi
|
||||
classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
|
||||
mkdir -p "$here/.build"
|
||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/ScenarioNetwork.java" "$here/src/DhcpRun.java" "$here/src/TcpRun.java" "$here/src/DnsRun.java"
|
||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/ScenarioNetwork.java" "$here/src/DhcpRun.java" "$here/src/TcpRun.java" "$here/src/DnsRun.java" "$here/src/ArpRun.java"
|
||||
# FILIUS writes its settings below $HOME; keep them out of the real one.
|
||||
mkdir -p "$here/.build/home"
|
||||
# Removed first: a crashed run must not leave the previous result standing.
|
||||
@@ -141,3 +141,13 @@ for run in address:5000 mail:5000 referral:5000 unknown:5000 noServer:22000; do
|
||||
"$root/packages/core/test/scenarios/dns-lan.scenario.json" "$story" "${run##*:}" "$output" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$output"
|
||||
done
|
||||
|
||||
# ARP as Java FILIUS runs it: sends to addresses no card has on arp-routed's
|
||||
# network (ArpRun); frames and the calls, for the core's ARP comparison.
|
||||
for story in pingLan pingRouted udpTwice udpBehind; do
|
||||
output="$root/packages/core/test/scenarios/arp-java-$story.java.json"
|
||||
rm -f "$output"
|
||||
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" ArpRun \
|
||||
"$root/packages/core/test/scenarios/arp-routed.scenario.json" "$story" 16000 "$output" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$output"
|
||||
done
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Runs a story of sends to addresses ARP cannot resolve on arp-routed's
|
||||
// network in Java FILIUS (ScenarioNetwork) and records every frame each card
|
||||
// saw and when each call started and ended.
|
||||
//
|
||||
// ArpRun <scenario.json> <story> <milliseconds> <out.json>
|
||||
//
|
||||
// 10.0.0.2 sits behind a switch on the router's 10.0.0.1; 20.0.0.2 on the
|
||||
// router's 20.0.0.1. No card has 10.0.0.9 or 20.0.0.9. The stories:
|
||||
// pingLan 10.0.0.2 pings 10.0.0.9 (ICMP.sendProbe, as the ping command)
|
||||
// pingRouted 10.0.0.2 pings 20.0.0.9: the router's ARP fails
|
||||
// udpTwice 10.0.0.2 sends two UDP datagrams to 10.0.0.9 at once
|
||||
// udpBehind 10.0.0.2 sends a UDP datagram to 10.0.0.9, then one to 20.0.0.2
|
||||
|
||||
import filius.software.transportschicht.UDPSocket;
|
||||
import filius.software.vermittlungsschicht.IcmpPaket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArpRun {
|
||||
static final String HOST = "00000000-0000-0000-0000-000000000301";
|
||||
|
||||
static ScenarioNetwork network;
|
||||
static final List<Object[]> events = new ArrayList<>();
|
||||
|
||||
interface Call {
|
||||
String run() throws Exception;
|
||||
}
|
||||
|
||||
static synchronized void event(String what) {
|
||||
events.add(new Object[] { System.currentTimeMillis() - network.start, what });
|
||||
}
|
||||
|
||||
static void call(String label, Call call) {
|
||||
event(label + " called");
|
||||
try {
|
||||
event(label + " returned " + call.run());
|
||||
} catch (Exception e) {
|
||||
event(label + " failed " + e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
static String icmp(IcmpPaket packet) {
|
||||
return packet == null ? "null" : "ICMP " + packet.getIcmpType() + "/" + packet.getIcmpCode() + " from " + packet.getSender();
|
||||
}
|
||||
|
||||
static void send(String target, String payload) throws Exception {
|
||||
UDPSocket socket = new UDPSocket(network.system(HOST), target, 9);
|
||||
socket.verbinden();
|
||||
socket.senden(payload);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
network = ScenarioNetwork.read(args[0]);
|
||||
String story = args[1];
|
||||
long end = Long.parseLong(args[2]);
|
||||
network.start();
|
||||
Thread.sleep(500);
|
||||
switch (story) {
|
||||
case "pingLan":
|
||||
call("sendProbe 10.0.0.9", () -> icmp(network.system(HOST).holeICMP().sendProbe("10.0.0.9", 64, 1, 1)));
|
||||
break;
|
||||
case "pingRouted":
|
||||
call("sendProbe 20.0.0.9", () -> icmp(network.system(HOST).holeICMP().sendProbe("20.0.0.9", 64, 1, 1)));
|
||||
break;
|
||||
case "udpTwice":
|
||||
call("senden eins", () -> {
|
||||
send("10.0.0.9", "eins");
|
||||
return "";
|
||||
});
|
||||
call("senden zwei", () -> {
|
||||
send("10.0.0.9", "zwei");
|
||||
return "";
|
||||
});
|
||||
break;
|
||||
case "udpBehind":
|
||||
call("senden verloren", () -> {
|
||||
send("10.0.0.9", "verloren");
|
||||
return "";
|
||||
});
|
||||
call("senden dahinter", () -> {
|
||||
send("20.0.0.2", "dahinter");
|
||||
return "";
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unknown story " + story);
|
||||
}
|
||||
long rest = network.start + end - System.currentTimeMillis();
|
||||
if (rest > 0) Thread.sleep(rest);
|
||||
|
||||
ScenarioNetwork.Json out = new ScenarioNetwork.Json();
|
||||
out.open('{');
|
||||
network.writeFrames(out);
|
||||
synchronized (ArpRun.class) {
|
||||
out.key("events").open('[');
|
||||
for (Object[] each : events) out.open('[').number((Long) each[0]).string((String) each[1]).close(']');
|
||||
out.close(']');
|
||||
}
|
||||
out.close('}');
|
||||
network.stop();
|
||||
ScenarioNetwork.write(args[3], out);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import filius.hardware.knoten.LokalerKnoten;
|
||||
import filius.hardware.knoten.Notebook;
|
||||
import filius.hardware.knoten.Rechner;
|
||||
import filius.hardware.knoten.Switch;
|
||||
import filius.hardware.knoten.Vermittlungsrechner;
|
||||
import filius.rahmenprogramm.nachrichten.Lauscher;
|
||||
import filius.software.dhcp.DHCPServer;
|
||||
import filius.software.dns.DNSServer;
|
||||
@@ -59,6 +60,7 @@ public class ScenarioNetwork {
|
||||
|
||||
private void build(Map<String, Object> scenario) {
|
||||
Map<String, Port> ports = new HashMap<>();
|
||||
Map<String, NetzwerkInterface> nicsByPort = new HashMap<>();
|
||||
for (Object each : list(scenario.get("nodes"))) {
|
||||
Map<String, Object> node = map(each);
|
||||
String id = (String) node.get("id");
|
||||
@@ -75,18 +77,25 @@ public class ScenarioNetwork {
|
||||
case "networkSwitch":
|
||||
knoten = new Switch();
|
||||
break;
|
||||
case "router":
|
||||
knoten = new Vermittlungsrechner();
|
||||
((InternetKnoten) knoten).setzeAnzahlAnschluesse(nodePorts.size());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("node kind " + kind + " is not built by this tool");
|
||||
}
|
||||
knoten.setName(id);
|
||||
if (knoten instanceof InternetKnoten) {
|
||||
if (nodePorts.size() != 1) throw new IllegalArgumentException("a host has one port here");
|
||||
Map<String, Object> port = map(nodePorts.get(0));
|
||||
NetzwerkInterface nic = ((InternetKnoten) knoten).getNetzwerkInterfaces().get(0);
|
||||
List<NetzwerkInterface> nics = ((InternetKnoten) knoten).getNetzwerkInterfaces();
|
||||
for (int index = 0; index < nodePorts.size(); index++) {
|
||||
Map<String, Object> port = map(nodePorts.get(index));
|
||||
NetzwerkInterface nic = nics.get(index);
|
||||
String mac = port.containsKey("mac") ? (String) port.get("mac") : stableMac((String) port.get("id"));
|
||||
nic.setMac(mac);
|
||||
ports.put((String) port.get("id"), nic.getPort());
|
||||
macByNode.put(id, mac);
|
||||
nicsByPort.put((String) port.get("id"), nic);
|
||||
if (index == 0) macByNode.put(id, mac);
|
||||
}
|
||||
} else {
|
||||
LinkedList<Port> switchPorts = ((LokalerKnoten) knoten).getAnschluesse();
|
||||
for (int index = 0; index < nodePorts.size(); index++) {
|
||||
@@ -103,6 +112,13 @@ public class ScenarioNetwork {
|
||||
nic.setGateway((String) device.getOrDefault("gateway", ""));
|
||||
nic.setDns((String) device.getOrDefault("dns", ""));
|
||||
}
|
||||
// A router's other cards: `interfaces` names them by port.
|
||||
for (Object each : list(scenario.getOrDefault("interfaces", new ArrayList<>()))) {
|
||||
Map<String, Object> item = map(each);
|
||||
NetzwerkInterface nic = nicsByPort.get(item.get("port"));
|
||||
nic.setIp((String) item.get("ip"));
|
||||
nic.setSubnetzMaske((String) item.get("mask"));
|
||||
}
|
||||
for (Object each : list(scenario.get("links"))) {
|
||||
Map<String, Object> link = map(each);
|
||||
Kabel cable = new Kabel();
|
||||
|
||||
Reference in New Issue
Block a user