207 lines
6.6 KiB
Java
207 lines
6.6 KiB
Java
import javax.swing.*;
|
|
import java.util.Arrays;
|
|
|
|
public class RouterNode {
|
|
private int myID;
|
|
private GuiTextArea myGUI;
|
|
private RouterSimulator sim;
|
|
private int[] costs = new int[RouterSimulator.NUM_NODES];
|
|
private int[] routesCosts = new int[RouterSimulator.NUM_NODES];
|
|
private int[] routesList = new int[RouterSimulator.NUM_NODES];
|
|
private int[][] distanceTable = new int[RouterSimulator.NUM_NODES][RouterSimulator.NUM_NODES];
|
|
|
|
// Program parameters
|
|
private int CONST_TAB_SIZE = 12; // Constant used to set column width
|
|
private boolean POISONED_REVERSE = true; // To set poisoned reverse or not
|
|
|
|
/* TDTS06 - Lab 4 */
|
|
|
|
|
|
//--------------------------------------------------
|
|
// Virtual router constructor, init. base values, distance table, routes table & costs table
|
|
public RouterNode(int ID, RouterSimulator sim, int[] costs) {
|
|
myID = ID;
|
|
this.sim = sim;
|
|
myGUI = new GuiTextArea(" Output window for Router #"+ ID + " ");
|
|
|
|
System.arraycopy(costs, 0, this.costs, 0, RouterSimulator.NUM_NODES);
|
|
System.arraycopy(costs, 0, this.routesCosts, 0, RouterSimulator.NUM_NODES);
|
|
|
|
|
|
// Route list initialisation
|
|
for (int i = 0; i < sim.NUM_NODES; i++) {
|
|
// If the cost is not infinity, we have a route
|
|
if (costs[i] != sim.INFINITY){routesList[i] = i;}
|
|
else{routesList[i] = -1;}
|
|
}
|
|
|
|
// Distance table initialisation:
|
|
// Infinity everywhere...
|
|
for (int[] row: distanceTable) {Arrays.fill(row, sim.INFINITY);}
|
|
// ...except for itself
|
|
distanceTable[myID] = Arrays.copyOf(costs, costs.length);
|
|
|
|
// Sending first update to neighbour
|
|
sendUpdate();
|
|
|
|
// Printing first distance table
|
|
printDistanceTable();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------
|
|
// Update the route list from the distanceTable
|
|
private boolean Update() {
|
|
// We are going to check for update to avoid sending useless info.
|
|
boolean updt = false;
|
|
for (int i = 0; i < sim.NUM_NODES; i++) {
|
|
// We ignore ourself
|
|
if (i == myID) {continue;}
|
|
|
|
int newRouteCost = sim.INFINITY;
|
|
|
|
// We keep the old values in memory
|
|
int oldRoute = routesList[i];
|
|
int oldRouteCost = distanceTable[myID][i];
|
|
|
|
for (int j = 0; j < sim.NUM_NODES; j++){
|
|
// We keep ignoring ourself
|
|
if (j == myID) {continue;}
|
|
|
|
// If this is a neighbour AND if the new searched route is greater than the actual distance AND if it is not us
|
|
if(costs[j] != RouterSimulator.INFINITY && newRouteCost > distanceTable[j][i] + costs[j] && j != myID){
|
|
distanceTable[myID][i] = distanceTable[j][i] + costs[j];
|
|
newRouteCost = distanceTable[myID][i];
|
|
routesList[i] = j;
|
|
routesCosts[i] = newRouteCost;
|
|
}
|
|
}
|
|
// If we have changed smth then we have a update
|
|
if(oldRoute != routesList[i] || oldRouteCost != distanceTable[myID][i]){
|
|
updt = true;
|
|
}
|
|
}
|
|
return updt;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------
|
|
public void recvUpdate(RouterPacket pkt) {
|
|
DEBUG("Rcv packet !");
|
|
// Updating the distance table
|
|
distanceTable[pkt.sourceid] = pkt.mincost;
|
|
// Updating the routes list from the distance table
|
|
// and send this update to all neighbour if there
|
|
// are changes
|
|
if (Update()) {sendUpdate();}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------
|
|
private void sendUpdate() {
|
|
for (int i = 0; i < sim.NUM_NODES; i++) {
|
|
int[] sendedCosts = Arrays.copyOf(distanceTable[myID],sim.NUM_NODES);
|
|
|
|
// We ignore non-neighbor nodes
|
|
if(i == myID || costs[i] == sim.INFINITY) {continue;}
|
|
|
|
// Implementing poisoned reverse
|
|
if(POISONED_REVERSE) {
|
|
// For all destination nodes, if our route for a other node go thought
|
|
// this destination node, we set the distance to infinity to avoid that
|
|
// this destination node try to go back thought us and create a loop.
|
|
// See page 418 in the course book (4th edition).
|
|
for (int j = 0; j < RouterSimulator.NUM_NODES; j++) {
|
|
if (routesList[j] == i && j != i) {
|
|
sendedCosts[j] = RouterSimulator.INFINITY;
|
|
}
|
|
}
|
|
}
|
|
RouterPacket pkt = new RouterPacket(myID,i,sendedCosts);
|
|
DEBUG("Sending updt !");
|
|
sim.toLayer2(pkt);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// Function that print a table header
|
|
private void printTabHeader() {
|
|
myGUI.print(F.format("dst",CONST_TAB_SIZE) + " |");
|
|
for (int i = 0; i < sim.NUM_NODES ; i++) {myGUI.print(F.format(i,CONST_TAB_SIZE));}
|
|
myGUI.println("");
|
|
for (int i = 0; i < sim.NUM_NODES ; i++) {
|
|
for (int j = 0; j <= 1.5*CONST_TAB_SIZE; j++) {
|
|
myGUI.print("-");
|
|
}
|
|
}
|
|
myGUI.println("");
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// Print distance table, costs list & routes list when call
|
|
public void printDistanceTable() {
|
|
// Header
|
|
myGUI.println("Current table for " + myID +
|
|
" at time " + sim.getClocktime());
|
|
|
|
// DistanceTable
|
|
myGUI.println("Distancetable: ");
|
|
printTabHeader();
|
|
|
|
// Printing a line for each known routers
|
|
for (int i = 0; i < sim.NUM_NODES; ++i ) {
|
|
// We ignore non-neighbor nodes
|
|
if (costs[i] == sim.INFINITY) continue;
|
|
|
|
myGUI.print(F.format("nbr " + i, CONST_TAB_SIZE) + "|");
|
|
for (int j = 0; j < sim.NUM_NODES; ++j ) {myGUI.print(F.format(distanceTable[i][j],CONST_TAB_SIZE));}
|
|
myGUI.println("");
|
|
}
|
|
myGUI.println("");
|
|
|
|
// Distance vector & routes
|
|
myGUI.println("Our distance vector and routes: ");
|
|
printTabHeader();
|
|
|
|
// Printing costs
|
|
myGUI.print(F.format("cost",CONST_TAB_SIZE) + "|");
|
|
for (int i = 0; i < sim.NUM_NODES; i++) {
|
|
myGUI.print(F.format(routesCosts[i],CONST_TAB_SIZE));
|
|
//myGUI.print(F.format(costs[i],CONST_TAB_SIZE));
|
|
}
|
|
myGUI.println("");
|
|
|
|
// Printing routes
|
|
myGUI.print(F.format("route",CONST_TAB_SIZE) + "|");
|
|
for (int i = 0; i < sim.NUM_NODES; i++) {
|
|
myGUI.print(F.format(routesList[i],CONST_TAB_SIZE));
|
|
}
|
|
myGUI.println("");
|
|
|
|
// Printing info on poisoned reverse
|
|
if (POISONED_REVERSE) {
|
|
myGUI.println("(Poisoned reverse active)");
|
|
}
|
|
else {
|
|
myGUI.println("(No poisoned reverse)");
|
|
}
|
|
myGUI.println("\n");
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// If a link change its cost
|
|
public void updateLinkCost(int dest, int newcost) {
|
|
// Updating costs list
|
|
costs[dest] = newcost;
|
|
// Spreading the update
|
|
if (Update()) {sendUpdate();}
|
|
}
|
|
|
|
// DEBUG FUNCTION - TO REMOVE
|
|
private void DEBUG(String str) {
|
|
//myGUI.print(" DEBUG from " + myID + " at time " + sim.getClocktime() + ": ");
|
|
//myGUI.println(str);
|
|
}
|
|
}
|
|
|
|
|