feat(core): the packet capture's table after Java's Lauscher, measured against Java's own tables
captureRows.ts builds Java's rows per frame (Lauscher.datenVorbereiten): Ethernet; ARP, ICMP or IP; TCP or UDP; the data with Java's protocol recognition; with addresses and ports or ports only. The comment stays structured; captureCommentText says it with given words and numbers. ScenarioNetwork writes Java's finished tables per card (Lauscher.getDaten, German locale); all runtime runs are recorded again, NatRun has ttlOut. expectSameCaptures compares both views for every frame. Fixed where the engine differed: an ARP request's target MAC is the broadcast address, an ICMP error's identifier and sequence number are 0 (RFC 792), and host unreachable from a router carries the packet as forwarded. Not taken: Java's lower-case broadcast address in a reply to 0.0.0.0, and the typo 'Exeeded'. RIP keeps its recordings: Java's staggered router start now gives a different startup on this machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -476,3 +476,33 @@ Javas Switch prüft seine Tabelle einmal je Sekunde ab dem Start
|
||||
nach der Lernzeit; der Kern genau bei ihr. Das ist gewollt und wird nicht
|
||||
gemessen: Wo Java nur in einem Takt nachsieht, macht der Kern es genauer
|
||||
(Entscheidung 01.10.2026; dasselbe für die NAT-Einträge des Heimrouters).
|
||||
|
||||
## Tabelle des Mitschnitts
|
||||
|
||||
Seit F2.8b schreibt `ScenarioNetwork.writeFrames` neben den Frames Javas
|
||||
fertige Tabelle jeder Karte (`Lauscher.getDaten`): `rows` mit Adresse:Port
|
||||
(das Fenster „Datenaustausch"), `layeredRows` nur mit Ports (die
|
||||
Schichtenansicht); je Zeile Nummer, Quelle, Ziel, Protokoll, Schicht,
|
||||
Bemerkung, ohne die Uhrzeit. Java läuft dabei mit `Locale.GERMANY`
|
||||
(`Information.getLocaleOrDefault`): deutsche Wörter, Tausenderpunkte. Alle
|
||||
Laufzeit-Läufe sind dafür neu aufgenommen (bis auf `dhcp-lan`, s. oben);
|
||||
`NatRun` hat den Ablauf `ttlOut` (Ping mit TTL 1 aus dem LAN: der Heimrouter
|
||||
meldet „Zeit überschritten").
|
||||
|
||||
Gemessen (01.10.2026), wo der Kern abwich:
|
||||
|
||||
* Eine ARP-Anfrage trägt als Ziel-MAC `FF:FF:FF:FF:FF:FF`
|
||||
(`ARP.sendeARPBroadcast`), der Kern trug Nullen (wie Swift).
|
||||
* Eine ICMP-Fehlermeldung trägt Identifier und Sequenznummer 0, der Kern
|
||||
kopierte die des Echos (wie Swift).
|
||||
* „Host nicht erreichbar" vom Router trägt das Paket mit gesenkter TTL (wie
|
||||
er es weitergeleitet hat), der Kern das angekommene.
|
||||
|
||||
Bewusst nicht übernommen: Javas Antwort an `0.0.0.0` schreibt die
|
||||
Broadcast-Adresse klein (`ARP.sendArpReply`), der Kern immer groß; „ICMP
|
||||
Time Exeeded" ist ein Tippfehler.
|
||||
|
||||
RIP: Der Anlauf entscheidet, wie viele Zufallspausen jeder Router zieht
|
||||
(jede Nachricht zieht eine), und der hängt an Javas Startreihenfolge. Eine
|
||||
Aufnahme, deren Anlauf von dem des Kerns (alle Router zugleich) abweicht,
|
||||
liegt danach in allen Zeiten daneben; das Werkzeug wird dann wiederholt.
|
||||
|
||||
@@ -154,7 +154,7 @@ done
|
||||
|
||||
# NAT as Java FILIUS runs it: nat-home's home router between a LAN PC and two
|
||||
# WAN hosts (NatRun); frames, calls and the router's NAT table at the end.
|
||||
for run in pingOut:10000 udpOut:10000 udpTwoRemotes:25000 tcpOut:20000 forward:20000 pingWan:15000; do
|
||||
for run in pingOut:10000 udpOut:10000 udpTwoRemotes:25000 tcpOut:20000 forward:20000 pingWan:15000 ttlOut:10000; do
|
||||
story="${run%%:*}"
|
||||
output="$root/packages/core/test/scenarios/nat-java-$story.java.json"
|
||||
rm -f "$output"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// forward 42.0.0.20 connects to 42.0.0.10:8080, forwarded to
|
||||
// 192.168.0.10:80; sends, receives, closes
|
||||
// pingWan 42.0.0.20 pings 42.0.0.10, then 192.168.0.10
|
||||
// ttlOut 192.168.0.10 pings 42.0.0.20 with TTL 1: time exceeded
|
||||
|
||||
import filius.software.nat.NatEntry;
|
||||
import filius.software.nat.NatGateway;
|
||||
@@ -194,6 +195,9 @@ public class NatRun {
|
||||
Thread.sleep(200);
|
||||
tcpClient(SERVER, "42.0.0.10", 8080);
|
||||
break;
|
||||
case "ttlOut":
|
||||
call("sendProbe 42.0.0.20", () -> icmp(os(LAN_PC).holeICMP().sendProbe("42.0.0.20", 1, 1, 1)));
|
||||
break;
|
||||
case "pingWan":
|
||||
call("sendProbe 42.0.0.10", () -> icmp(os(SERVER).holeICMP().sendProbe("42.0.0.10", 64, 1, 1)));
|
||||
call("sendProbe 192.168.0.10", () -> icmp(os(SERVER).holeICMP().sendProbe("192.168.0.10", 64, 1, 2)));
|
||||
|
||||
@@ -242,6 +242,32 @@ public class ScenarioNetwork {
|
||||
out.close(']');
|
||||
}
|
||||
out.close('}');
|
||||
writeRows(out, "rows", true);
|
||||
writeRows(out, "layeredRows", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The packet capture's table of each card as FILIUS shows it
|
||||
* (Lauscher.getDaten): with addresses and ports (`rows`, the data exchange
|
||||
* window) or ports only (`layeredRows`, the layered view). Each row: number,
|
||||
* source, destination, protocol, layer, comment — its time (the wall clock)
|
||||
* left out.
|
||||
*/
|
||||
void writeRows(Json out, String key, boolean withAddresses) {
|
||||
out.key(key).open('{');
|
||||
for (Map.Entry<String, String> entry : macByNode.entrySet()) {
|
||||
out.key(entry.getKey()).open('[');
|
||||
for (Object[] row : Lauscher.getLauscher().getDaten(entry.getValue(), withAddresses, 1)) {
|
||||
out.open('[');
|
||||
for (int column = 0; column < row.length; column++) {
|
||||
if (column == 1) continue;
|
||||
out.string(row[column] == null ? null : String.valueOf(row[column]));
|
||||
}
|
||||
out.close(']');
|
||||
}
|
||||
out.close(']');
|
||||
}
|
||||
out.close('}');
|
||||
}
|
||||
|
||||
/** Each host's address, mask, gateway and DNS server. */
|
||||
|
||||
Reference in New Issue
Block a user