/*
** This file is part of Filius, a network construction and simulation software.
**
** Originally created at the University of Siegen, Institute "Didactics of
** Informatics and E-Learning" by a students' project group:
** members (2006-2007):
** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding,
** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer
** supervisors:
** Stefan Freischlad (maintainer until 2009), Peer Stechert
** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de>
** and Stefan Freischlad
** Filius is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) version 3.
**
** Filius is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE. See the GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Filius. If not, see <http://www.gnu.org/licenses/>.
*/
package filius.software.system;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Vector;
import filius.Main;
import filius.hardware.Port;
import filius.hardware.knoten.Switch;
import filius.rahmenprogramm.I18n;
import filius.software.netzzugangsschicht.EthernetFrame;
import filius.software.netzzugangsschicht.SwitchPortBeobachter;
/**
* Diese Klasse stellt die Funktionalitaet des Switches zur Verfuegung.
* Wichtiges Element ist die Source Address Table (SAT). Der Switch operiert nur
* auf der Netzzugangsschicht, auf der MAC-Adressen verwendet werden.
*/
public class SwitchFirmware extends SystemSoftware implements I18n {
private static final long serialVersionUID = 1L;
/**
* Die Source Address Tabel (SAT), in der die MAC-Adressen den physischen
* Anschluessen des Switch zugeordnet werden
*/
private HashMap<String, Port> sat = null;
/**
* Liste der Anschlussbeobachter. Sie implementieren die Netzzugangsschicht.
*/
private LinkedList<SwitchPortBeobachter> switchBeobachter;
/**
* Hier werden bereits weitergeleitete Frames gespeichert. Wird ein Frame
* wiederholt verschickt, beispielsweise wegen einer Verbindung, die zwei
* Anschluesse kurzschliesst, wird der Frame verworfen.
*
* @see filius.software.netzzugangsschicht.SwitchPortBeobachter
*/
private LinkedList<EthernetFrame> durchgelaufeneFrames = new LinkedList<EthernetFrame>();
/**
* Hier wird die Netzzugangsschicht des Switch initialisiert und gestartet.
* Ausserdem wird die SAT zurueckgesetzt.
*/
public void starten() {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (SwitchFirmware), starten()");
SwitchPortBeobachter anschlussBeobachter;
sat = new HashMap<String, Port>();
switchBeobachter = new LinkedList<SwitchPortBeobachter>();
ListIterator it = ((Switch) getKnoten()).getAnschluesse()
.listIterator();
while (it.hasNext()) {
Port anschluss = (Port) it.next();
anschlussBeobachter = new SwitchPortBeobachter(this, anschluss);
anschlussBeobachter.starten();
switchBeobachter.add(anschlussBeobachter);
}
}
/** Hier wird die Netzzugangsschicht des Switch gestoppt. */
public void beenden() {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (SwitchFirmware), beenden()");
ListIterator it = switchBeobachter.listIterator();
while (it.hasNext()) {
SwitchPortBeobachter anschlussBeobachter = (SwitchPortBeobachter) it
.next();
anschlussBeobachter.beenden();
}
}
/** Diese Methode wird genutzt, um die SAT abzurufen. */
public Vector holeSAT() {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (SwitchFirmware), holeSAT()");
Vector<Vector> eintraege = new Vector<Vector>();
Vector<String> eintrag;
String ausgabe;
for (String elem : sat.keySet()) {
Port anschluss = (Port) sat.get(elem);
ausgabe = messages.getString("sw_switchfirmware_msg1")
+ " "+((Switch) getKnoten()).getAnschluesse()
.indexOf(anschluss);
eintrag = new Vector<String>();
eintrag.add(elem.toUpperCase());
eintrag.add(ausgabe);
eintraege.add(eintrag);
}
return eintraege;
}
/**
* Methode zum erzeugen eines neuen Eintrags in der SAT. Wenn bereits ein
* Eintrag zu der uebergebenen MAC-Adresse vorliegt, wird der alte Eintrag
* aktualisiert.
*
* @param macAdresse
* die MAC-Adresse des entfernten Anschlusses
* @param anschluss
* der Anschluss des Switch, der mit dem entfernten Anschluss
* verbunden ist
*/
public void hinzuSatEintrag(String macAdresse, Port anschluss) {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (SwitchFirmware), hinzuSatEintrag("+macAdresse+","+anschluss+")");
if (!sat.containsKey(macAdresse)) {
// Main.debug.println("SwitchFirmware: Neuer Eintrag in SAT-Tabelle: " + macAdresse + "->" + anschluss.toString());
}
else {
sat.remove(macAdresse);
// Main.debug.println("SwitchFirmware: Eintrag fuer " + macAdresse + " in SAT aktualisiert.");
}
sat.put(macAdresse, anschluss);
}
/**
* Mit dieser Methode wird der Anschluss ausgewaehlt, der die Verbindung zum
* Anschuss mit der uebergebenen MAC-Adresse herstellt. Dazu wird die SAT
* verwendet.
*
* @param macAdresse
* die Zieladresse eines Frames nach der in der SAT gesucht
* werden soll
* @return der Anschluss zur MAC oder null, wenn kein passender Eintrag
* existiert
*/
public Port holeAnschlussFuerMAC(String macAdresse) {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (SwitchFirmware), holeAnschlussFuerMAC("+macAdresse+")");
if (sat.containsKey(macAdresse)) {
return (Port) sat.get(macAdresse);
}
else {
return null;
}
}
/**
* Methode zum Zugriff auf die bereits durchgelaufenen Frames. Diese wird
* dazu genutzt um Fehler durch Zyklen zu vermeiden.
*
* @return Liste der bereits weitergeleiteten Frames.
*/
public LinkedList<EthernetFrame> holeDurchgelaufeneFrames() {
return durchgelaufeneFrames;
}
}