SFP-VDSL-Modem auf einem MikroTik-Router einrichten

Reine VDSL-Modems sind eine aussterbende Art. Trotzdem gibt es noch hier und da entsprechende Modems, unter anderem im SFP-Standard. Diese SFP können genutzt werden z.B. einen MikroTik-Router mit einer entsprechenden Funktionalität nachzurüsten. In diesem Fall sollte es die Möglichkeit sein VDSL über das Interface sfp1 zu nutzen. Die erhältlichen SFP-Module für VDSL sind meist baugleich mit dem VersaTec VX-160CE VDSL2-SFP.

Ein VDSL Modem als SFP

Nachdem das Modul im MikroTik-Router installiert wurde, ist das Interface sfp1 aktiv. Die Auto Negotiation muss für das Modul deaktiviert werden. Andernfalls schlägt später die Neuverbindung nach einem Neustart fehl, da das Modul nicht mehr erkannt wird.

Die Auto Negotiation muss für das Modul deaktiviert werden

Eingestellt wird das Modul hierbei auf 1Gbps bei Full Duplex. Im nächsten Schritt muss ein VLAN für die Schnittstelle angelegt werden. Hintergrund ist, das erwartet wird das die Daten sich im VLAN mit einer bestimmten ID befinden. Bei der Deutschen Telekom ist dies die 7, bei anderen Anbietern kann dies teilweise abweichen. So z.B. bei 1&1; dort wird je nach genutzter Infrastruktur die 7 oder die 8 genutzt.

Das VLAN-Interface

Beim anzulegenden VLAN-Interface ist darauf zu achten, das kein Service-Tag gesetzt wird. Nachdem das Interface sfp1 und das entsprechende VLAN-Interface konfiguriert sind, kann im nächsten Schritt die PPPoE-Verbindung eingerichtet werden. Dazu wird unter PPP ein neues PPPoE-Interface eingerichtet. Das zu nutzende Interface für das PPPoE-Interface ist hierbei das VLAN-Interface, im Beispiel sfp1-v7.

Das PPPoE Interface

Im Tab Dail Out müssen die Zugangsdaten von Internetanbieter eingetragen werden. Im Falle einiger Anbieter wie z.B. 1&1 kann es notwendig sein vor dem eigentlichen Nutzernamen ein H zu setzen, da dieser sonst nicht akzeptiert wird und der Authentifizierungsvorgang fehlschlägt. Damit ist das SFP-Modul eingerichtet und die Verbindung kann genutzt werden. Je nach genutztem Modell aus der MikroTik-Palette kann es sein, das nicht die volle Bandbreite genutzt werden kann. Das Problem ist in diesen Fällen meist die CPU-Auslastung durch die PPPoE-Verbindung da diese komplett durch die CPU verarbeitet werden muss. In einem solchen Fall kann zu den Cloud Core-Routern von MikroTik gegriffen werden.

Nachdem die Verbindung hergestellt war, stellte ich im Laufe eines längeren Testes allerdings fest, dass der PPPoE-Link in regelmäßigen Abständen nach 30 – 80 Minuten zusammenbrach und somit leider kein stabiles Internet lieferte. Vermutlich handelt es sich um ein Problem des SFP-Moduls im Zusammenhang mit dem DSLAM.

ExecutorService unter Java nutzen

Wenn unter Java die Ausführung von Quelltext parallelisiert werden soll, so können hierfür Threads genutzt werden:

Thread thread = new Thread(new TestRunnable());
thread.start();

In diesem Beispiel wird für eine auszuführende Aufgabe ein Thread erstellt und dieser anschließend gestartet. Nun kann es Fälle geben, in welchem mehrere Threads die gleiche Aufgabe ausführen sollen, allerdings nicht unbedingt die entsprechende Anzahl von Threads angelegt werden soll. Für eine solche Aufgabe eignet sich ein ExecutorService. Im ersten Schritt sollte ein Runnable definiert werden. In diesem Interface wird eine run-Methode definiert, die den auszuführenden Quellcode enthält:

public static class TestRunnable implements Runnable {

    @Override
    public void run() {
        // Do something
    }
}

Nun kann der ExecutorService angelegt werden und mit einem Threadpool ausgestattet werden. Anschließend werden die neuen Instanzen des Runnable, mittels der execute-Methode, an den ExecutorService übergeben.

// Executor service
ExecutorService executorService = Executors.newCachedThreadPool();

// Add jobs to executor service
for (int i = 0; i < 100; i++) {
    executorService.execute(new TestRunnable());
}

// Shutdown executor service
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

Damit würden die Aufgaben abgearbeitet. Allerdings würde der ExecutorService nun bis zu einem Timeout noch bestehen bleiben. Stattdessen wird er im Beispiel kontrolliert heruntergefahren. Nach der Ausführung der shutdown-Methode nimmt der ExecutorService keine neuen Aufträge mehr an; bestehende Aufträge werden allerdings noch abgearbeitet. Über die Methode awaitTermination wird sichergestellt das der Service wartet, bis alle Aufgaben abgearbeitet sind. Bei der Methode wird ein Timeout angegeben, nach welchem der Service zwangsweise abgeschaltet wird. Damit werden die Aufgaben Stück für Stück abgearbeitet, ohne entsprechende viele Threads zu öffnen. Stattdessen werden Threads aus dem Threadpool wiederverwendet.

Exception-Hierarchie unter Java

Java nutzt, wie viele andere Sprachen, Exceptions zur Fehlersignalisierung und Fehlerbehandlung. Folgender Code würde hierbei dem Anschein nach alle Exceptions fangen:

try {
  // Do something wrong
} catch(Exception e) {
  // Gotta Catch 'Em All
}

An dieser Stelle trügt der Schein nicht. Allerdings werden nur einige Fehlerklassen gefangen, nämlich nur solche vom Typ Exception. Die Hierarchie der Fehlerklassen ist unter Java ein wenig differenzierter. In Java erbt jede Klasse implizit von der Klasse Object und so erbt auch die Klasse Throwable von dieser und implementiert das Interface Serializable.

Die Hierarchie der Klassen, welche für Fehlersignalisierung zuständig sind

Von der Klasse Throwable wiederum erben die Klassen Error und Exception. Fehler vom Typ Error stellen laut Definition immer Fehler innerhalb der JVM da, während Exceptions gewöhnliche Fehler des Programmes bzw. des Entwicklers sind. Sollen nun alle Fehlerklassen gefangen werden, so müsste der Quellcode wie folgt aussehen:

try {
  // Do something wrong
} catch(Throwable t) {
  // Gotta Catch 'Em All
}

Das Beispiel sollte nur als solches betrachtet werden, da es sich immer empfiehlt spezielle Fehler zu fangen und zu behandeln. Ein solch allgemeiner Fehlerhandler eignet sich nur für Spezialfälle wie z.B. das Logging nicht behandelter Fehler. Die Hierarchie verästelt sich anschließend noch weiter, so erben unterschiedlichste Klassen von der Klasse Error. Bei der Klasse Exception sieht dies ähnlich aus, allerdings existiert hier eine Besonderheit, die Klasse RuntimeException. Normalerweise muss eine Methode Exceptions, die sie wirft im Methodenkopf bekannt geben, wenn sie nicht in der Methode behandelt werden:

public static void example() throws Exception {
  throw new Exception();
}

Bei Klassen die von der Klasse RuntimeException erben muss diese Bekanntmachung im Methodenkopf nicht erfolgen. Sie werden trotzdem nach oben durchgereicht bis sie gefangen werden oder sich das Programm beendet, wenn die Behandlung der Exception nicht durchgeführt wurde.

Maps unter Java mit computeIfAbsent nutzen

Wenn eine Map unter Java etwas komplexer wird, wie z.B. folgende Map:

Map<String, List<String>> testMap = new HashMap<>();

wird das befüllen derselbigen interessant. In diesem Beispiel soll ein Key und ein neuer Value für die Liste vom Typ String hinzugefügt werden. Damit dies funktioniert muss überprüft werden ob der Key bereits existiert und wenn dies nicht der Fall ist, ein neuer Key angelegt werden. Im kompletten Beispiel sieht das Ganze so aus:

String key = "ABC";
String valueForList = "DEF";

Map<String, List<String>> testMap = new HashMap<>();

if(!testMap.containsKey(key)) {
    testMap.put(key, new ArrayList<>());
} 

testMap.get(key).add(valueForList);

Einfacher und unkomplizierter ist es die Methode computeIfAbsent zu nutzen, welche seit Java 8 in der Definition des Map-Interfaces enthalten ist. Mit der Nutzung der Methode verkürzt sich das Beispiel wie folgt:

String key = "ABC";
String valueForList = "DEF";

Map<String, List<String>> testMap = new HashMap<>();
testMap.computeIfAbsent(key, s -> new ArrayList<>()).add(valueForList);

Damit wird automatisch eine neue ArrayList angelegt, wenn der entsprechende Schlüssel noch nicht hinterlegt ist. Anschließend kann der entsprechende Wert für die Liste hinzugefügt werden.

Arduino für den Industrieeinsatz

Die Arduino-Familie ist im Grundsatz für das schnelle Prototyping gedacht. Der Einsatz in Industrieumgebungen ist also nicht allzu empfehlenswert. Das haben sich die Macher des Controllino ebenfalls gedacht. Finanziert über Kickstarter, entwickelten sie eine speicherprogrammierbare Steuerung, welche Arduino-kompatibel ist und sich für den Industrieeinsatz eignet.

controllino.biz

Der Controllino verfügt, je nach Modell, über bis zu 21 Eingänge, 24 Ausgänge, 16-Relay-Ausgänge und unterschiedlichste Interfaces zur Ansteuerung, wie I2C oder SPI. Daneben verfügt er über einen USB- und einen Ethernet-Anschluss. Ebenfalls integriert ist eine Real time clock. Bezogen werden kann der Controllino über die offizielle Seite unter controllino.biz. Preislich bewegen sich die Controller in einem Bereich von ein- bis dreihundert Euro, je nachdem welches Modell gewählt wird.