├── README.md ├── modivsim-forwardRefactor └── modivsim-forwardRefactor │ ├── ModivSim.iml │ ├── out │ └── production │ │ └── ModivSim │ │ ├── ClientHandler.class │ │ ├── FlowRouting$Flow.class │ │ ├── FlowRouting$Topology.class │ │ ├── FlowRouting.class │ │ ├── FlowRoutingFolder │ │ ├── flows.txt │ │ └── forwardingTable.txt │ │ ├── Message.class │ │ ├── ModivSim$1.class │ │ ├── ModivSim.class │ │ ├── Node$1.class │ │ ├── Node.class │ │ ├── PathStruct.class │ │ └── nodeFolder │ │ ├── Node0.txt │ │ ├── Node1.txt │ │ ├── Node2.txt │ │ ├── Node3.txt │ │ └── Node4.txt │ └── src │ ├── ClientHandler.java │ ├── FlowRouting.java │ ├── FlowRoutingFolder │ ├── flows.txt │ └── forwardingTable.txt │ ├── Message.java │ ├── ModivSim.java │ ├── Node.java │ ├── PathStruct.java │ └── nodeFolder │ ├── Node0.txt │ ├── Node1.txt │ ├── Node2.txt │ ├── Node3.txt │ └── Node4.txt └── topology.png /README.md: -------------------------------------------------------------------------------- 1 | # Distance-Vector-Routing-and-Flow-Control-Simulator 2 | 3 | The project simulates a network traffic in a given topology where the distance vector algorithm is used for path computations and routing. The topology of the network is given and cannot be changed by the user. User can change the path costs between each router, and specify any number of flows from any router to the other. Package size also can be changed. After the user specifies, the program can run the network traffic. 4 | 5 | The program basically consists of two major parts: 6 | - Distance Vector Computation 7 | - Forwarding and Routing Algorithm 8 | 9 | *Distance Vector Computation:* 10 | In this part, the user enters the path costs, and the distance vectors are computed by the program, and exported to a text file. 11 | 12 | *Flow Routing Algorithm:* 13 | In this part, the program takes the output of first part, the distance vectors, as an input to construct the topology. The user enters each packet flow to be executed, i.e., specifies the packages to be transmitted from which router to which router with the sizes of packages. Then, the program simulates the traffic at each steps of each packages including visited routers, queues, delays etc. 14 | 15 | Used skills: 16 | * Socket programming in router communications 17 | * Multi-Threading 18 | * De-centralized programming 19 | * Object-oriented design 20 | * I/O Management, File Reading/Writing 21 | * Implementation of Distance Vector, Routing/Forwarding, and Flow Control Algorithms 22 | 23 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/ModivSim.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ClientHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ClientHandler.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting$Flow.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting$Flow.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting$Topology.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting$Topology.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRouting.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRoutingFolder/flows.txt: -------------------------------------------------------------------------------- 1 | 2,4,200 2 | 3,0,150 3 | 3,1,200 4 | 3,0,150 5 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/FlowRoutingFolder/forwardingTable.txt: -------------------------------------------------------------------------------- 1 | {1=1=2, 2=2=1, 3=2=1, 4=1=2} 2 | {0=0=2, 2=0=2, 3=4=0, 4=4=0} 3 | {0=0=1, 1=0=1, 3=3=0, 4=0=1} 4 | {0=2=4, 1=4=2, 2=2=4, 4=4=2} 5 | {0=1=3, 1=1=3, 2=1=3, 3=3=1} -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Message.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Message.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ModivSim$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ModivSim$1.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ModivSim.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/ModivSim.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Node$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Node$1.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Node.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/Node.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/PathStruct.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/PathStruct.class -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/nodeFolder/Node0.txt: -------------------------------------------------------------------------------- 1 | 0,(1,5,10),(2,3,15) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/nodeFolder/Node1.txt: -------------------------------------------------------------------------------- 1 | 1,(0,5,10),(2,9,5),(4,1,15) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/nodeFolder/Node2.txt: -------------------------------------------------------------------------------- 1 | 2,(0,3,15),(1,9,5),(3,3,10) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/nodeFolder/Node3.txt: -------------------------------------------------------------------------------- 1 | 3,(2,3,10),(4,7,5) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/out/production/ModivSim/nodeFolder/Node4.txt: -------------------------------------------------------------------------------- 1 | 4,(1,1,15),(3,7,5) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/ClientHandler.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.net.Socket; 3 | 4 | public class ClientHandler extends Thread { 5 | ObjectOutputStream out; 6 | ObjectInputStream in; 7 | final Socket s; 8 | int clientID; 9 | int serverID; 10 | Node clientNode; 11 | 12 | public ClientHandler(Socket s,ObjectInputStream in, ObjectOutputStream out, int clientID, int serverID, Node clientNode) throws IOException { 13 | this.s = s; 14 | this.clientID = clientID; 15 | this.serverID = serverID; 16 | this.clientNode = clientNode; 17 | 18 | this.out = out; 19 | this.in = in; 20 | } 21 | 22 | public void sendMessage(Message msg) throws IOException { 23 | out.writeObject(msg); 24 | out.flush(); 25 | out.reset(); 26 | } 27 | 28 | public void receiveMessage() throws IOException, ClassNotFoundException { 29 | Message m = (Message) in.readObject(); 30 | if (m.changed){ 31 | clientNode.receiveUpdate(m); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/FlowRouting.java: -------------------------------------------------------------------------------- 1 | import javafx.util.Pair; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | import java.util.*; 7 | 8 | 9 | public class FlowRouting { 10 | private static ArrayList flows = new ArrayList<>(); 11 | private static int numFlows; 12 | private static List list = new ArrayList(); //template list to form synchronized list 13 | private static List forwardingTable = Collections.synchronizedList(list); 14 | private static Topology topology = new Topology(); 15 | private static double time = 0; 16 | 17 | //** FLOWS */ 18 | private static class Flow { 19 | public final int priority; 20 | public final int srcNode; 21 | public final int dstNode; 22 | public final double dataSize; 23 | public boolean done = false; 24 | public boolean queued = false; 25 | public double actionTime; 26 | public double queueEndTime; 27 | public double[] lastActParameters; // [last proceed path's BW, travel time] 28 | public List lastPath; // last proceed path 29 | public ArrayList path = new ArrayList<>(); 30 | public Flow(int srcNode,int dstNode,int dataSize,int priority){ 31 | this.srcNode=srcNode; 32 | this.dstNode=dstNode; 33 | this.dataSize=dataSize; 34 | this.priority=priority; 35 | actionTime=0; 36 | queueEndTime=999; 37 | lastActParameters= new double[]{999, 0}; 38 | } 39 | public void toStr(){ 40 | System.out.println("Source Node: "+srcNode+", Destination Node: "+dstNode+", Data Size: "+dataSize+", Priority: "+priority); 41 | } 42 | } 43 | private static void readFlows() throws IOException{ // reads flows from the text flows.txt 44 | int priorityCount = -1; 45 | String [] tokens; 46 | BufferedReader reader; 47 | reader = new BufferedReader(new FileReader("./src/FlowRoutingFolder/flows.txt")); 48 | String line = reader.readLine(); 49 | System.out.println("Flows are read from \"flows.txt\": "); 50 | while (line != null) { 51 | priorityCount++; 52 | ArrayList a = new ArrayList<>(); 53 | tokens = line.split("[,()]+"); 54 | for(String s: tokens){ 55 | a.add(Integer.parseInt(s)); 56 | } 57 | Flow f = new Flow(a.get(0),a.get(1),a.get(2),priorityCount); 58 | flows.add(f); 59 | System.out.print("f"+f.priority+": "+line+" ->\t"); 60 | f.toStr(); 61 | line = reader.readLine(); 62 | } 63 | numFlows=flows.size(); 64 | reader.close(); 65 | } 66 | 67 | //** TOPOLOGY */ 68 | private static class Topology { 69 | protected Map> topologyMap = new HashMap<>(); 70 | public Topology(){ 71 | constructTopology(); 72 | } 73 | public ArrayList neighbours(int node){ //returns the neighbour nodes of the given node 74 | ArrayList arr = new ArrayList<>(); 75 | for(int i=0;i<5;i++){ 76 | if(node!=i){ 77 | if(topologyMap.containsKey(link(node,i))){ 78 | arr.add(i); 79 | } 80 | } 81 | } 82 | return arr; 83 | } 84 | private void constructTopology(){ 85 | topologyMap.put(link(0,1),linkProperties(10,1,0)); 86 | topologyMap.put(link(0,2),linkProperties(15,1,0)); 87 | topologyMap.put(link(1,2),linkProperties(5,1,0)); 88 | topologyMap.put(link(1,4),linkProperties(15,1,0)); 89 | topologyMap.put(link(2,3),linkProperties(10,1,0)); 90 | topologyMap.put(link(4,3),linkProperties(5,1,0)); 91 | } 92 | 93 | private String link(int a,int b){ // it takes the nodes of link (interchangeably), turns into String version which is the format used in topologyMap 94 | return String.valueOf(Integer.min(a,b))+"-"+String.valueOf(Integer.max(a,b)); 95 | } 96 | private ArrayList linkProperties(double bandwidth, double availability,double reservedTime){ 97 | ArrayList arr = new ArrayList<>(); 98 | arr.add(bandwidth); 99 | arr.add(availability); 100 | arr.add(reservedTime); 101 | return arr; 102 | } 103 | public double getLinkBW(int a, int b){ 104 | try{ 105 | return topologyMap.get(link(a,b)).get(0); 106 | }catch(NullPointerException e){ 107 | System.out.println("There is no link between "+a+" and "+b); 108 | return -1; 109 | } 110 | 111 | } 112 | public double getLinkAvail(int a, int b){ 113 | try{ 114 | if(a==b) return 1; 115 | else return topologyMap.get(link(a,b)).get(1); 116 | }catch(NullPointerException e){ 117 | System.out.println("There is no link between "+a+" and "+b); 118 | return -1; 119 | } 120 | 121 | } 122 | public double getLinkRsdTime(int a, int b){ 123 | try{ 124 | if(a==b) return 0; 125 | else return topologyMap.get(link(a,b)).get(2); 126 | }catch(NullPointerException e){ 127 | System.out.println("There is no link between "+a+" and "+b); 128 | return -1; 129 | } 130 | 131 | } 132 | public void setLinkAvail(int a, int b, double av){ 133 | try{ 134 | topologyMap.get(link(a,b)).set(1,av); 135 | }catch(NullPointerException e){ 136 | System.out.println("There is no link between "+a+" and "+b); 137 | } 138 | } 139 | public void setLinkRsdTime(int a, int b, double rs){ 140 | try{ 141 | topologyMap.get(link(a,b)).set(2,rs); 142 | }catch(NullPointerException e){ 143 | System.out.println("There is no link between "+a+" and "+b); 144 | } 145 | } 146 | public void update(double actionTime, List subPath) throws ConcurrentModificationException { 147 | int e = subPath.get(0); 148 | int ePlus = 0; 149 | for(int i=1; i { 158 | if(v.get(2)<=time){ 159 | v.set(1,(double)1); 160 | v.set(2,time); 161 | } 162 | }); 163 | } 164 | public void printTopology(){ 165 | topologyMap.forEach((k, v) -> { 166 | System.out.println("Link ("+k+") -> BW: "+v.get(0)+",\t Availability(0/1): "+v.get(1)+",\t Reserved Until Time: "+v.get(2)); 167 | }); 168 | } 169 | } 170 | 171 | //** FORWARDING */ 172 | private static List> readForwardingTable() throws IOException{ 173 | String [] tokens = null; 174 | ArrayList arr; 175 | List> forTable = new ArrayList<>(); 176 | BufferedReader reader; 177 | reader = new BufferedReader(new FileReader("./src/FlowRoutingFolder/forwardingTable.txt")); 178 | String line = reader.readLine(); 179 | 180 | while (line != null) { 181 | arr = new ArrayList<>(); 182 | tokens = line.split("[,{}= ]+"); 183 | for(String a: tokens){ 184 | try{ arr.add(Integer.parseInt(a)); 185 | }catch(NumberFormatException e){} 186 | } 187 | forTable.add(arr); 188 | line = reader.readLine(); 189 | } 190 | reader.close(); 191 | System.out.println("Forwarding Table is read from \"forwardingTable.txt\": "); 192 | return forTable; 193 | } 194 | private static void implementForwardingTable() throws IOException{ 195 | List> forTableArray = readForwardingTable(); 196 | int size = forTableArray.size(); 197 | int trio = 0; 198 | for(ArrayList ar : forTableArray){ 199 | Map> forwardingEntry = new HashMap<>(); 200 | for(int i=0; i<(size-1);i++){ 201 | trio = i*3; 202 | forwardingEntry.put(ar.get(trio), new Pair(ar.get(trio+1) , ar.get(trio+2)) ); 203 | } 204 | forwardingTable.add(forwardingEntry); 205 | } 206 | printForwardingTable(); 207 | } 208 | private static void printForwardingTable(){ 209 | for(Map m :forwardingTable){ 210 | System.out.println(m); 211 | } 212 | } 213 | private static double nextHop(int src, int dst){ 214 | return ((Pair) forwardingTable.get(src).get(dst)).getKey(); 215 | } 216 | private static double alternativeHop(int src, int dst){ 217 | return ((Pair) forwardingTable.get(src).get(dst)).getValue(); 218 | } 219 | private static double [] suggestedDst(int src,int dst){ 220 | double[] sug = {0,0}; // [suggested next node, action if it turns out to be queued] 221 | double next = nextHop(src,dst); 222 | double altNext = alternativeHop(src,dst); 223 | if(topology.getLinkAvail(src,(int)next)==1){ 224 | sug[0] = next; 225 | }else if(topology.getLinkAvail(src,(int)altNext)==1){ 226 | sug[0] = altNext; 227 | }else{ 228 | sug[1] = Double.min(topology.getLinkRsdTime(src,(int)next),topology.getLinkRsdTime(src, (int)altNext)); 229 | sug[0] = 999; // queue 230 | } 231 | return sug; 232 | } 233 | 234 | //** ROUTING */ 235 | private static void arrangeFlows(){ 236 | List flowsStatus = new ArrayList<>(); 237 | for(int i=0; i Completion Status of Flows: "+flowsStatus.toString()); 248 | 249 | for(int i=0; i subPath = f.path.subList(startOfSubPath,size); 373 | if(!(size==1 && time==0)){ // If sub-path does not consist only of initial (source) node 374 | System.out.println(" *f"+f.priority+": path added."); 375 | double minBW=999; 376 | for(int i=startOfSubPath; i subPath,double bottleneckBW,int subPathSize ){ 388 | 389 | double passingTime = 0; 390 | f.lastPath = subPath.subList(0,subPathSize); 391 | 392 | // CHECKING EFFECT/STATUS OF LAST PATH 393 | if(f.lastActParameters[0]!=999){ // The effect of last path still remains -> while transmission occurs, queue opened (new sub-path added) 394 | if(f.lastActParameters[0]f.queueEndTime){ // if needed, save the required info of newly added path 416 | System.out.println(" *f"+f.priority+"'s sub-path transmission lasts longer than the queue time. Action time is considered as queue time."); 417 | f.lastPath = subPath; 418 | f.lastActParameters[0]=bottleneckBW; 419 | f.lastActParameters[1]=f.queueEndTime-time; 420 | f.actionTime=f.queueEndTime; 421 | } 422 | } 423 | 424 | topology.update(f.actionTime,subPath); 425 | } 426 | private static void proceedToClosestActionTime(){ 427 | double tempTime = time; 428 | topology.topologyMap.forEach((k, v) -> { 429 | if (v.get(2)>tempTime){ 430 | if(time==tempTime) time=v.get(2); 431 | time = Double.min(time,v.get(2)); 432 | } 433 | }); 434 | topology.clear(); 435 | 436 | } 437 | private static boolean isLoopPrisoner(double suggestion, Flow f) { // Looks for cases where secret potential loop traps might be hided. (even if it is not seemed so) 438 | boolean isPrisoner = true ; 439 | for(int n : topology.neighbours((int)suggestion)){ 440 | if(!f.path.contains(n)) isPrisoner = false; 441 | } 442 | return isPrisoner; 443 | } 444 | 445 | //** MAIN METHOD*/ 446 | public static void main(String[] args) throws IOException { 447 | System.out.println(); 448 | System.out.println("*************************** PROGRAM INITIALIZATION ***************************"); 449 | readFlows(); 450 | System.out.println(); 451 | implementForwardingTable(); 452 | System.out.println(); 453 | System.out.println("Topology is constructed by using bandwidth and forwarding table info."); 454 | topology.printTopology(); 455 | System.out.println(); 456 | arrangeFlows(); 457 | 458 | } 459 | 460 | } 461 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/FlowRoutingFolder/flows.txt: -------------------------------------------------------------------------------- 1 | 2,4,200 2 | 3,0,150 3 | 3,1,200 4 | 3,0,150 5 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/FlowRoutingFolder/forwardingTable.txt: -------------------------------------------------------------------------------- 1 | {1=1=2, 2=2=1, 3=2=1, 4=1=2} 2 | {0=0=2, 2=0=2, 3=4=0, 4=4=0} 3 | {0=0=1, 1=0=1, 3=3=0, 4=0=1} 4 | {0=2=4, 1=4=2, 2=2=4, 4=4=2} 5 | {0=1=3, 1=1=3, 2=1=3, 3=3=1} -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/Message.java: -------------------------------------------------------------------------------- 1 | import java.io.Serializable; 2 | import java.util.Arrays; 3 | 4 | public class Message implements Serializable{ 5 | int senderNodeID; 6 | int receiverNodeID; 7 | int senderDistanceVector[]; 8 | boolean changed; 9 | 10 | public Message(int senderNodeID, int receiverNodeID, int senderDistanceVector[], boolean changed){ 11 | this.senderNodeID = senderNodeID; 12 | this.receiverNodeID = receiverNodeID; 13 | this.senderDistanceVector = senderDistanceVector; 14 | this.changed=changed; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "Message{" + 20 | "senderNodeID=" + senderNodeID + 21 | ", receiverNodeID=" + receiverNodeID + 22 | ", senderDistanceVector=" + Arrays.toString(senderDistanceVector) + 23 | '}'; 24 | } 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/ModivSim.java: -------------------------------------------------------------------------------- 1 | import javafx.util.Pair; 2 | 3 | import java.io.*; 4 | import java.net.ServerSocket; 5 | import java.net.Socket; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.Paths; 9 | import java.util.*; 10 | import java.util.concurrent.Executors; 11 | import java.util.concurrent.ScheduledExecutorService; 12 | import java.util.concurrent.ScheduledFuture; 13 | import java.util.logging.MemoryHandler; 14 | import java.util.stream.Collectors; 15 | import java.util.stream.IntStream; 16 | 17 | import static java.util.concurrent.TimeUnit.*; 18 | 19 | public class ModivSim 20 | { 21 | private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 22 | static HashMap, ArrayList> paths=new HashMap<>(); 23 | static ArrayList nodes = new ArrayList<>(); 24 | private static int numNodes; 25 | private static boolean[] visited=new boolean[numNodes]; 26 | private static Stack path= new Stack<>(); 27 | static int round = 0; 28 | 29 | public static Node readNode(File filePath, int nodeCount) throws IOException { 30 | String content; 31 | HashMap linkCost = new HashMap<>(); 32 | HashMap linkBandwidth = new HashMap<>(); 33 | ArrayList dynamicLinks= new ArrayList<>(); 34 | 35 | content = new String(Files.readAllBytes(Paths.get(filePath.toURI()))); 36 | String[] tokens = content.split(",[(]"); 37 | 38 | int nodeId = Integer.parseInt(tokens[0]); 39 | 40 | for (int i = 1; i < tokens.length; i++) { 41 | // reading neighbour 42 | String neighbour = tokens[i]; 43 | //System.out.println(neighbour); 44 | 45 | neighbour = neighbour.replaceAll("[()]", ""); 46 | 47 | String[] ntokens = neighbour.split(","); 48 | // System.out.println(Arrays.toString(ntokens)); 49 | int nId = Integer.parseInt(ntokens[0]); 50 | if(ntokens[1].equals("x")){ 51 | dynamicLinks.add(nId); 52 | linkCost.put(nId, getRandomNumberInRange(1,10)); 53 | }else{ 54 | linkCost.put(nId, Integer.parseInt(ntokens[1])); 55 | } 56 | 57 | 58 | linkBandwidth.put(nId, Integer.parseInt(ntokens[2])); 59 | } 60 | Node ans = new Node(nodeId, linkCost, linkBandwidth, nodeCount,dynamicLinks); 61 | //System.out.println("node with nodeid " + nodeId); 62 | nodes.add(ans); 63 | return ans; 64 | } 65 | 66 | public static synchronized void scheduleOperation() { 67 | final Runnable updater = new Runnable() { 68 | public void run() { 69 | checkConvergence(); 70 | } 71 | }; 72 | final ScheduledFuture updaterHandle = scheduler.scheduleAtFixedRate(updater, 5, 1, SECONDS); 73 | } 74 | 75 | private static void checkConvergence() { 76 | boolean converged = true; 77 | for (Node node: nodes){ 78 | if(node.changed==true){ 79 | converged=false; 80 | } 81 | } 82 | if (converged){ 83 | System.out.println("Simulation converged."); 84 | 85 | for (int i = 0; i < numNodes; i++) { 86 | nodes.get(i).setConverged(true); 87 | for (int j = 0; j < numNodes; j++) { 88 | visited= new boolean[numNodes]; 89 | path= new Stack<>(); 90 | 91 | System.out.println("PRINTING PATHS FROM "+i+ " TO "+j); 92 | ArrayList pathStructs= new ArrayList<>(); 93 | printAllPaths(i,j,0,pathStructs); 94 | paths.put(new Pair<>(i,j),pathStructs); 95 | } 96 | } 97 | populateForwardingTables(); 98 | 99 | for (Node node: nodes){ 100 | System.out.println(node.forwardingTable); 101 | } 102 | 103 | try { 104 | File file = new File("./src/FlowRoutingFolder/forwardingTable.txt"); 105 | FileWriter writer = new FileWriter(file); 106 | BufferedWriter bufferedWriter = new BufferedWriter(writer); 107 | int size=nodes.size(); 108 | for (Node node: nodes){ 109 | bufferedWriter.write(node.forwardingTable.toString()); 110 | if (!(node.nodeID==size-1)) bufferedWriter.newLine(); 111 | } 112 | bufferedWriter.close(); 113 | } catch (IOException e) { 114 | e.printStackTrace(); 115 | } 116 | 117 | scheduler.shutdown(); 118 | }else{ 119 | round++; 120 | } 121 | } 122 | 123 | private static void populateForwardingTables() { 124 | for (Node node: nodes){ 125 | HashMap> forwardingTable= new HashMap<>(); 126 | 127 | for (int i=0; i< numNodes; i++){ 128 | if (node.nodeID != i){ 129 | ArrayList allPaths = paths.get(new Pair<>(node.nodeID,i)); 130 | 131 | Collections.sort(allPaths,Comparator.comparing(PathStruct::getCost)); 132 | PathStruct minPath = allPaths.get(0); 133 | 134 | int firstHop; 135 | int secondHop = 0; 136 | if (minPath.path.size() == 1){ 137 | firstHop= i; 138 | }else{ 139 | firstHop= (int) minPath.path.toArray()[1]; 140 | } 141 | for (int j = 1; j < allPaths.size(); j++) { 142 | PathStruct secondMinPath = allPaths.get(j); 143 | if (secondMinPath.path.size() == 1){ 144 | secondHop= i; 145 | }else{ 146 | secondHop= (int) secondMinPath.path.toArray()[1]; 147 | } 148 | if (firstHop != secondHop){ 149 | break; 150 | } 151 | } 152 | 153 | 154 | forwardingTable.put(Integer.toString(i), new Pair<>(firstHop,secondHop)); 155 | } 156 | } 157 | node.forwardingTable=forwardingTable; 158 | } 159 | } 160 | 161 | private static void printAllPaths(int src, int dest, int currentCost, ArrayList pathStructs){ 162 | if (src == dest){ 163 | pathStructs.add(new PathStruct((Stack) path.clone(),currentCost)); 164 | System.out.println(Arrays.toString(path.toArray())+ " cost = "+ currentCost); 165 | 166 | }else{ 167 | visited[src] = true; 168 | path.push(src); 169 | for (int adjacentNode: nodes.get(src).neighbourIds){ 170 | if (visited[adjacentNode] == false){ 171 | printAllPaths(adjacentNode,dest, nodes.get(src).distanceTable[adjacentNode][adjacentNode]+currentCost,pathStructs); 172 | } 173 | } 174 | visited[src] = false; 175 | path.pop(); 176 | } 177 | } 178 | 179 | private static int getRandomNumberInRange(int min, int max) { 180 | 181 | if (min >= max) { 182 | throw new IllegalArgumentException("max must be greater than min"); 183 | } 184 | 185 | Random r = new Random(); 186 | return r.nextInt((max - min) + 1) + min; 187 | } 188 | 189 | 190 | 191 | public static void main(String[] args) throws IOException { 192 | 193 | // get node count 194 | File nodeFolder = new File("./src/nodeFolder/"); 195 | 196 | int nodeCount = nodeFolder.listFiles().length; 197 | numNodes= nodeCount; 198 | 199 | for (int i = 0; i < nodeCount; i++) { 200 | Thread t = readNode(nodeFolder.listFiles()[i], nodeCount); 201 | t.start(); 202 | } 203 | 204 | nodes.parallelStream().forEach((node) -> { 205 | try { 206 | node.establishConnections(); 207 | } catch (IOException e) { 208 | e.printStackTrace(); 209 | } 210 | }); 211 | 212 | scheduleOperation(); 213 | 214 | } 215 | } -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/Node.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.io.*; 3 | import java.net.ServerSocket; 4 | import java.net.Socket; 5 | import java.time.Instant; 6 | import java.util.*; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.ScheduledExecutorService; 9 | import java.util.concurrent.ScheduledFuture; 10 | 11 | import static java.util.concurrent.TimeUnit.*; 12 | 13 | import javafx.util.Pair; 14 | 15 | import javax.swing.*; 16 | 17 | public class Node extends Thread { 18 | private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 19 | HashSet neighbourIds=new HashSet<>(); 20 | int nodeID; 21 | HashMap linkCost; // id, linkcost 22 | HashMap linkBandwith; // id, linkbandwith 23 | int[][] distanceTable; //[i,j] is cost to node i via j 24 | int[] bottleneckBandwithTable; 25 | int[] distanceVector; // shortest distance to any given node 26 | private int numNodes; 27 | ArrayList dynamicLinks; 28 | Socket s; 29 | ServerSocket ss; 30 | ObjectInputStream ois; 31 | ObjectOutputStream oos; 32 | boolean changed = true; 33 | boolean converged = false; 34 | int round = 0; 35 | 36 | ArrayList ClientPeers = new ArrayList<>(); 37 | ArrayList ServerPeers = new ArrayList<>(); 38 | HashMap> forwardingTable; 39 | private int port; 40 | 41 | JTextArea textArea; 42 | JFrame frame; 43 | 44 | Instant instant = Instant.now(); 45 | long start = instant.getEpochSecond(); 46 | 47 | 48 | public Node(int nodeID, HashMap linkCost, HashMap linkBandwidth, int numNodes,ArrayList dynamicLinks) { 49 | this.nodeID = nodeID; 50 | this.linkCost = linkCost; 51 | this.linkBandwith = linkBandwidth; 52 | this.numNodes = numNodes; 53 | this.dynamicLinks=dynamicLinks; 54 | distanceTable = new int[numNodes][numNodes]; 55 | for (int i = 0; i < numNodes; i++) { 56 | for (int j = 0; j < numNodes; j++) { 57 | distanceTable[i][j] = 999; // set everything to inf 58 | } 59 | } 60 | distanceTable[nodeID][nodeID] = 0; 61 | distanceVector = new int[numNodes]; 62 | for (int i = 0; i < numNodes; i++) { 63 | distanceVector[i] = 999; 64 | } 65 | linkCost.forEach((k, v) -> { 66 | distanceTable[k][k] = v; 67 | distanceVector[k] = v; 68 | }); 69 | distanceVector[nodeID] = 0; 70 | 71 | 72 | bottleneckBandwithTable = new int[numNodes]; 73 | 74 | port = 12345 + nodeID; 75 | 76 | 77 | frame = new JFrame("Node " + nodeID); 78 | JPanel p = new JPanel(); 79 | 80 | //frame.setLocation(new Point(300*(nodeID%2), 300*nodeID)); 81 | /*frame.setPreferredSize(new Dimension(1000,200)); 82 | frame.setMaximumSize(new Dimension(1000,200)); 83 | frame.setMinimumSize(new Dimension(1000,200));*/ 84 | //frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 85 | //p.setLayout(new BoxLayout(p,1)); 86 | 87 | //JPanel mainPanel = new JPanel(); 88 | textArea = new JTextArea(); 89 | p.add(textArea); 90 | frame.add(p); 91 | 92 | //mainPanel.setLayout(new BorderLayout()); 93 | //frame.getContentPane().add(mainPanel); 94 | textArea.setText(String.format("In node %d at time %d, round %d\nLink costs: %s\nDistance vector: %s\nDistance table: %s\n", nodeID, 0, round, linkCost, 95 | Arrays.toString(distanceVector), Arrays.deepToString(distanceTable))); 96 | frame.pack(); 97 | //frame.setLocationRelativeTo(null); 98 | frame.setLocationByPlatform(true); 99 | frame.setLocation(frame.getSize().width*(nodeID%2),frame.getSize().height*(nodeID%5)); 100 | frame.setVisible(true); 101 | 102 | 103 | } 104 | 105 | private static int getRandomNumberInRange(int min, int max) { 106 | 107 | if (min >= max) { 108 | throw new IllegalArgumentException("max must be greater than min"); 109 | } 110 | 111 | Random r = new Random(); 112 | return r.nextInt((max - min) + 1) + min; 113 | } 114 | 115 | public void setConverged(boolean converged) { 116 | this.converged = converged; 117 | } 118 | 119 | @Override 120 | public void run() { 121 | try { 122 | ss = new ServerSocket(port); 123 | } catch (Exception e) { 124 | System.out.println(e); 125 | } 126 | 127 | scheduleOperation(); 128 | 129 | } 130 | 131 | public synchronized void scheduleOperation() { 132 | final Runnable updater = new Runnable() { 133 | public void run() { 134 | try { 135 | sendReceiveMessages(); 136 | } catch (IOException e) { 137 | e.printStackTrace(); 138 | } catch (ClassNotFoundException e) { 139 | e.printStackTrace(); 140 | } 141 | } 142 | }; 143 | final ScheduledFuture updaterHandle = scheduler.scheduleAtFixedRate(updater, 4, 1, SECONDS); 144 | } 145 | 146 | protected void sendReceiveMessages() throws IOException, ClassNotFoundException { 147 | 148 | //change dynamic links if necessary 149 | for (int neighbourId: dynamicLinks){ 150 | boolean willChange = getRandomNumberInRange(1,2)==1; 151 | if (willChange){ 152 | changed=true; 153 | int newCost=getRandomNumberInRange(1,10); 154 | linkCost.put(neighbourId,newCost); 155 | //update distance vector 156 | distanceTable[neighbourId][neighbourId]=newCost; 157 | distanceVector[neighbourId]=Arrays.stream(distanceTable[neighbourId]).min().getAsInt(); 158 | } 159 | } 160 | 161 | 162 | //send update to all peers 163 | sendUpdate(); 164 | 165 | //receive update from all peers 166 | recieveMessages(); 167 | 168 | } 169 | 170 | public void establishConnections() throws IOException { 171 | // first connect to smaller id neighbors as client 172 | 173 | linkCost.forEach((k, v) -> { 174 | if (k < nodeID) { 175 | try { 176 | Socket socket = new Socket("localhost", 12345 + k); 177 | ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); 178 | ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 179 | 180 | Thread t = new ClientHandler(socket, in, out, nodeID, k, this); 181 | ClientPeers.add((ClientHandler) t); 182 | 183 | t.start(); 184 | } catch (IOException e) { 185 | e.printStackTrace(); 186 | } 187 | 188 | } 189 | 190 | }); 191 | 192 | // then wait for higher id neighbors as server 193 | linkCost.forEach((k, v) -> { 194 | if (k > nodeID) { 195 | try { 196 | Socket s = ss.accept(); 197 | ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream()); 198 | ObjectInputStream in = new ObjectInputStream(s.getInputStream()); 199 | // create a new thread object 200 | Thread t = new ClientHandler(s, in, out, k, nodeID, this); 201 | ServerPeers.add((ClientHandler) t); 202 | // Invoking the start() method 203 | t.start(); 204 | } catch (IOException e) { 205 | e.printStackTrace(); 206 | } 207 | } 208 | }); 209 | 210 | 211 | } 212 | 213 | public void receiveUpdate(Message m) { 214 | //changed = false; 215 | this.neighbourIds.add(m.senderNodeID); 216 | for (int i = 0; i < numNodes; i++) { 217 | if (i != nodeID) 218 | distanceTable[i][m.senderNodeID] = m.senderDistanceVector[i] + linkCost.get(m.senderNodeID); 219 | } 220 | for (int i=0; i> getForwardingTable() { 277 | return forwardingTable; 278 | } 279 | 280 | } -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/PathStruct.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Stack; 3 | 4 | public class PathStruct { 5 | public Stack getPath() { 6 | return path; 7 | } 8 | 9 | public int getCost() { 10 | return cost; 11 | } 12 | 13 | Stack path; 14 | int cost; 15 | 16 | PathStruct(Stack path, int cost){ 17 | this.cost=cost; 18 | this.path=path; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/nodeFolder/Node0.txt: -------------------------------------------------------------------------------- 1 | 0,(1,5,10),(2,3,15) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/nodeFolder/Node1.txt: -------------------------------------------------------------------------------- 1 | 1,(0,5,10),(2,9,5),(4,1,15) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/nodeFolder/Node2.txt: -------------------------------------------------------------------------------- 1 | 2,(0,3,15),(1,9,5),(3,3,10) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/nodeFolder/Node3.txt: -------------------------------------------------------------------------------- 1 | 3,(2,3,10),(4,7,5) -------------------------------------------------------------------------------- /modivsim-forwardRefactor/modivsim-forwardRefactor/src/nodeFolder/Node4.txt: -------------------------------------------------------------------------------- 1 | 4,(1,1,15),(3,7,5) -------------------------------------------------------------------------------- /topology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DenizKrdy98/Distance-Vector-Routing-and-Flow-Control-Simulator/7004ba333549f960d80f85b84b63a901b643f06c/topology.png --------------------------------------------------------------------------------