// What FILIUS' viewers of a running simulation show, in Java FILIUS: a // switch's source address table (SwitchFirmware.holeSAT, shown by // SatViewer), a home router's NAT table (GatewayFirmware.holeNAT, shown by // NatViewer), each also after its "reset" (loescheSAT, loescheNAT), and the // frames "Pakete verwerfen" drops while it is held (Verbindung.setDrop, // Lauscher.getDroppedDataUnits, shown by SimulationControl). The viewers only // show these rows, so they are taken from the firmware directly. Times are // written with the run's start (the rows hold wall-clock times). // // ViewersRun // // switch switch-lan (retention 5 s): .10 pings .20 and .30; the table; // reset; .10 pings .20 again; the table; aged after the retention; // "Pakete verwerfen" held while .10 pings .30; the dropped frames // nat nat-home (port forwarding TCP 8080 to 192.168.0.10:80): // 192.168.0.10 pings 42.0.0.20 and sends a datagram to its port 7; // the table; reset; the table import filius.hardware.Verbindung; import filius.hardware.knoten.Switch; import filius.rahmenprogramm.nachrichten.Lauscher; import filius.software.system.GatewayFirmware; import filius.software.system.InternetKnotenBetriebssystem; import filius.software.system.SwitchFirmware; import filius.software.transportschicht.UDPSocket; import filius.software.vermittlungsschicht.IcmpPaket; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Vector; public class ViewersRun { static final String SWITCH = "00000000-0000-0000-0000-000000000104"; static final String PC10 = "00000000-0000-0000-0000-000000000101"; static final String GATEWAY = "00000000-0000-0000-0000-000000000502"; static final String LAN_PC = "00000000-0000-0000-0000-000000000501"; static final String SERVER = "00000000-0000-0000-0000-000000000504"; static ScenarioNetwork network; static final List steps = new ArrayList<>(); static InternetKnotenBetriebssystem os(String id) { return (InternetKnotenBetriebssystem) network.nodes.get(id).getSystemSoftware(); } static String ping(String from, String target, int sequence) { IcmpPaket answer = os(from).holeICMP().sendProbe(target, 64, 1, sequence); return answer == null ? "null" : "ICMP " + answer.getIcmpType() + "/" + answer.getIcmpCode(); } static List> rows(Vector> table) { List> rows = new ArrayList<>(); for (Vector row : table) rows.add(new ArrayList<>(row)); return rows; } /** Each learned address's last update, in milliseconds since the start. */ @SuppressWarnings("unchecked") static Map satTimes(SwitchFirmware firmware) throws Exception { Field field = SwitchFirmware.class.getDeclaredField("sat"); field.setAccessible(true); Map sat = (Map) field.get(firmware); Map times = new LinkedHashMap<>(); for (Map.Entry entry : sat.entrySet()) { Method update = entry.getValue().getClass().getMethod("holeLetztesUpdate"); update.setAccessible(true); times.put(entry.getKey().toUpperCase(), ((java.util.Date) update.invoke(entry.getValue())).getTime() - network.start); } return times; } static void step(String name, Map shown) { Map result = new LinkedHashMap<>(); result.put("step", name); result.put("at", System.currentTimeMillis() - network.start); result.putAll(shown); steps.add(result); } static Map sat() throws Exception { SwitchFirmware firmware = (SwitchFirmware) network.nodes.get(SWITCH).getSystemSoftware(); firmware.checkSAT(); Map shown = new LinkedHashMap<>(); shown.put("rows", rows(firmware.holeSAT())); shown.put("updated", satTimes(firmware)); shown.put("ports", ((Switch) network.nodes.get(SWITCH)).getAnschluesse().size()); return shown; } static Map nat() { Map shown = new LinkedHashMap<>(); shown.put("rows", rows(((GatewayFirmware) network.nodes.get(GATEWAY).getSystemSoftware()).holeNAT())); return shown; } public static void main(String[] args) throws Exception { try { run(args); } catch (Throwable error) { error.printStackTrace(); System.exit(1); } System.exit(0); } static void run(String[] args) throws Exception { network = ScenarioNetwork.read(args[0]); String story = args[1]; network.start(); Thread.sleep(500); Map output = new LinkedHashMap<>(); output.put("startEpoch", network.start); if (story.equals("switch")) { Map answers = new LinkedHashMap<>(); answers.put("ping .20", ping(PC10, "192.168.0.20", 1)); answers.put("ping .30", ping(PC10, "192.168.0.30", 2)); Map shown = sat(); shown.put("answers", answers); step("after pings", shown); ((SwitchFirmware) network.nodes.get(SWITCH).getSystemSoftware()).loescheSAT(); step("reset", sat()); Map again = sat(); again.put("answers", Map.of("ping .20", ping(PC10, "192.168.0.20", 3))); again.putAll(sat()); step("ping .20 again", again); Thread.sleep(6000); step("after the retention", sat()); Lauscher.getLauscher().resetDroppedDataUnits(); Verbindung.setDrop(true); String dropped = ping(PC10, "192.168.0.30", 4); Verbindung.setDrop(false); Map drop = new LinkedHashMap<>(); drop.put("answer", dropped); drop.put("dropped", Lauscher.getLauscher().getDroppedDataUnits()); step("dropped while held", drop); Map after = new LinkedHashMap<>(); after.put("answer", ping(PC10, "192.168.0.30", 5)); after.put("dropped", Lauscher.getLauscher().getDroppedDataUnits()); step("released", after); } else { step("start", nat()); Map answers = new LinkedHashMap<>(); answers.put("ping 42.0.0.20", ping(LAN_PC, "42.0.0.20", 1)); UDPSocket socket = new UDPSocket(os(LAN_PC), "42.0.0.20", 7); socket.verbinden(); socket.senden("one"); answers.put("udp port", socket.holeLokalenPort()); Thread.sleep(1500); Map shown = nat(); shown.put("answers", answers); step("after ping and datagram", shown); ((GatewayFirmware) network.nodes.get(GATEWAY).getSystemSoftware()).loescheNAT(); step("reset", nat()); } output.put("steps", steps); try (FileOutputStream out = new FileOutputStream(args[2])) { out.write((FlsOracle.Json.write(output, "") + "\n").getBytes(StandardCharsets.UTF_8)); } network.stop(); System.out.println("viewer steps: " + steps.size()); } }