//Title: Single Message Measurement for available network bandwidth //Version: //Copyright: Copyright (c) 1998 //Author: xhe //Company: UCCS package Simulator; //import java.awt.*; //import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.*; import java.lang.Runnable; public class SingleMessMeasurement extends Measurement implements Runnable { double RoundTripTime; double temp_band = 0; // for debug usage public SingleMessMeasurement(JPanel ch,String trafficpattern,double smt,double emt,double tmi, double pmi, boolean trafficoutput) { try { super.ThreadInit(ch,trafficpattern,smt,emt,tmi,pmi,trafficoutput); jbInit(); } catch (Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { // initilize the newwork topology based on configure file StringTokenizer t; Double DTemp; //EQ = new EventsQueue(); try { BufferedReader ifile = new BufferedReader(new FileReader("configure.txt")); String s; int iterate=0; // first line for four parameters of PInternalTime, PBIntervalTime // TInternalTime and TBIntervalTime // we get them in the parent class of Measurement s = ifile.readLine(); // skip the first line // second line for five number: how many Router, Link and Road, // the fourth number is the number of the bottleneck Link // the fifth number is the number of how many probing message in one probing route s = ifile.readLine(); t = new StringTokenizer(s,"|"); numOfRouter = Integer.parseInt(t.nextToken()); numOfLink = Integer.parseInt(t.nextToken()); numOfRoad = Integer.parseInt(t.nextToken()); Routers = new Router[numOfRouter+1]; Links = new Link[numOfLink+1]; RoadTable = new RouterTable[numOfRoad]; // generate all the routers: range starts from 1 for(int i=1; i<= numOfRouter; i++) Routers[i] = new Router(this,i); // generate all the links: range starts from 1 for(int i=1; i<= numOfLink; i++) { //int distance = rnd.nextInt(1000)+3; // a random link distance; Links[i] = new Link(this,LinkLength,i,LinkBandwidth); } BottleneckLink = Links[Integer.parseInt(t.nextToken())]; BottleneckLink.BottleneckLink = true; // set the field BottleneckLink.LinkBandwidth = BottleneckLinkBandwidth; // retrieve how many messages needed in one Cprobing cycle CprobingNum = Integer.parseInt(t.nextToken()); // create the router table, start from 0 // each line after third line(included) is a single road table while (iterate < numOfRoad) { s = ifile.readLine(); t = new StringTokenizer(s,"|"); int RoadNodeNum = t.countTokens(); RoadTable[iterate] = new RouterTable(iterate,RoadNodeNum); int num=0; String tmp; while (num < RoadNodeNum){ tmp = t.nextToken(); if (tmp.charAt(0) == 'L') // this is a link object RoadTable[iterate].append(Links[Integer.parseInt(tmp.substring(1))],num); else RoadTable[iterate].append(Routers[Integer.parseInt(tmp.substring(1))],num); num++; } // end of one single line, inner while iterate ++; } // end of all road table, outer while EQ = new EventsQueue(RoadTable); ifile.close(); } catch (IOException d) { System.out.print("Error" + d); System.exit(1); } // open a log file for the writing of simulator try { LogFile = new PrintWriter(new FileWriter("log.txt")); PFile = new PrintWriter(new FileWriter("probing.txt")); EventFile = new PrintWriter(new FileWriter("RoundTripTime.txt")); } catch(IOException k) { System.out.print("Error" + k); System.exit(1); } } public void run() { // there is only one probing agent. // The first router of the first road is the probing agent. // the first router in each of the rest roads is the traffic generation agent. Message M,NewM; double Start_TrafficTime = 0.3; // initializing the start event // for the probing agent // generate the initial probing message, size is static value 46 bytes // in the web traffic pattern, the probing message launch is triggered by a HTTP-response message // because we are only interesting in the available bandwidth when there are traffic in network if (!(traffic.trafficType.equals("Web"))) { M = new Message(0,0,"Probe-start",46*8,Start_MeaTime); // the message nubmer is useless. EQ.insert(M); } // Generate one "RoundTripTime-Probing" type messages // to measure the relatively accurate round trip time for a message // the probing agent sends this type message always. // This probing message is declared with traffic message constructor // because the queuing time at each object of its route is 0.0 M = new Message(0,0,"RoundTripTime-ProbingRequest",ProbingMessageSize*8,0.0); //M = new Message(0,0,RoadTable[0].numOfNode,0,"RoundTripTime-ProbingRequest",ProbingMessageSize*8,0,0,false); M.MessMeasurementType = UnitripProbe; //M = new Message(0,0,"RoundTripTime-ProbingRequest",46*8,6.0); EQ.insert(M); if (traffic.trafficType.equals("Web")) { // web traffic pattern M = new Message(0,1,"WebMess-start",46*8,Start_TrafficTime); pareto = new Pareto(); weibull = new Weibull(); } else { // for flat/slope traffic pattern // Generate the first "Traffic-start" type message // always the first traffic agent is to use it to set the bottleneck M = new Message(0,1,"Traffic-start",46*8,Start_TrafficTime); } EQ.insert(M); // what is the time to report the traffic M = new Message(0,1,"Traffic-report",8,Start_TrafficTime+TBIntervalTime); EQ.insert(M); // generate the last "Simulation-end" message // all arguments except the data type are useless. M = new Message(0,0,"Simulation-end",8,end_time); EQ.insert(M); // start event dispatching while ((M = EQ.nextItem()) != null) { boolean flag = false; String MessageType = M.MessageType; if (MessageType.compareTo("Simulation-end") == 0) { PFile.close(); LogFile.close(); // close all the opened file in Router for(int i=1; i<= numOfRouter; i++) Routers[i].OFILE.close(); // close all the opened file in Link for(int i=1; i<= numOfLink; i++) Links[i].OFILE.close(); EventFile.close(); return; } if (MessageType.compareTo("RoundTripTime-ProbingRequest") == 0) { // wakeup the corresponding object to handle this message // set the wakeup time of the message next time. // this setted time is stored in the Backup_nextArrivalTime if (UnitripProbe) { boolean responseMess_GetToDestination = RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); if (!responseMess_GetToDestination) EQ.insert(M); // The response message does not reach its source else { RoundTripTime = M.getArrivalTime(); LogFile.println("UniTrip Time: "+ RoundTripTime); EventFile.println("10|"+ RoundTripTime); } } else { RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); EQ.insert(M); } flag = true; } if (!flag && (MessageType.compareTo("RoundTripTime-ProbingResponse") == 0)) { // wakeup the corresponding object to handle this message // set the wakeup time of the message next time. /* double old_ArrivalTime = M.getArrivalTime(); */ boolean responseMess_GetToDestination = RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); if (!responseMess_GetToDestination) EQ.insert(M); // The response message does not reach its source else { RoundTripTime = M.getArrivalTime(); LogFile.println("Round Trip Time: "+ RoundTripTime); EventFile.println("10|"+ RoundTripTime); } flag = true; } if (MessageType.compareTo("Traffic-start") == 0) { // there is only one Traffic-start message, it starts generating general traffic // generate a new traffic message // the message type is "HTTP-request" NewM = new Message(++MaxMessNum,M.RouterTableNum,"HTTP-request",traffic.TrafficMessSize,M.getArrivalTime()); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); BottleneckLink.reset_bottlelink(M.getArrivalTime()); // change M type to a new traffic generation message: "New-TrafficMess" // wakeup me to generate the next traffic message in one traffic route // message number is useless. M.MessageType = "New-TrafficMess"; M.setTime(M.getArrivalTime()+traffic.TIntervalTime); EQ.insert(M); flag = true; } if (!flag && (MessageType.compareTo("New-TrafficMess") == 0)) { // traffic agent generates a new traffic message // generate the next traffic message generation message // generate a new traffic message // change the message type to "HTTP-request" //NewM = new Message(++MaxMessNum,M.RouterTableNum,"HTTP-request",(rnd.nextInt(2400)+100)*8,M.getArrivalTime()); ++MaxMessNum; NewM = new Message(MaxMessNum,M.RouterTableNum,"HTTP-request",traffic.TrafficMessSize,M.getArrivalTime()); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); // set next "New-TrafficMess" generation time // wakeup me to generate the next new traffic message M.setTime(M.getArrivalTime()+traffic.TIntervalTime); EQ.insert(M); flag = true; } if (!flag && (MessageType.compareTo("Traffic-report") == 0)) { // traffic report message to update the log file and chart UpdateLog(M.getArrivalTime()); BottleneckLink.reset_bottlelink(M.getArrivalTime()); // reset next "Traffic-report" time M.setTime(M.getArrivalTime()+TBIntervalTime); EQ.insert(M); flag = true; } if (!flag && (MessageType.compareTo("Probe-start") == 0)) { // probing agent generates a new probing route // generate the next probing message generation message // set the next probing start message time // let the bottleneck link reset the start time to measure bandwidth // probing message number always from 1 to ProbingMessNum //BottleneckLink.Pstarting_time = M.getArrivalTime(); // generate a new probing message: "ICMP-request" NewM = new Message(1,M.RouterTableNum,RoadTable[M.RouterTableNum].numOfNode, M.getArrivalTime(),"ICMP-request",ProbingMessageSize*8,M.getArrivalTime(),0,UnitripProbe); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); if (traffic.trafficType.equals("Slope")) traffic.ArguChange(true); // generate the next "Probing-start" message //int temp = rnd.nextInt(1000); M.setTime(M.getArrivalTime()+PBIntervalTime); //M.setTime(M.getArrivalTime()+(double)(temp/1e+4)); EQ.insert(M); flag = true; } if (!flag && (MessageType.compareTo("WebMess-start") == 0)) { double AT = M.getArrivalTime(); // only the first one is this kind of message, the following web request messages // are generated by "New-WebMess" kind message // generate a new web request message: "HTTP-request" // the original request message number is always 0 // the reference pages' number is start from 1 to reference number. NewM = new Message(0,M.RouterTableNum,"HTTP-request",46*8,AT); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); BottleneckLink.reset_bottlelink(M.getArrivalTime()); /*/ reset the next web message generation time // the time is conform to pareto distribution double Fx = rnd.nextDouble(); double lowerBound = 1.0; double alpha = 1.5; double gap = pareto.getX(Fx,lowerBound,alpha)/100; //double gap = pareto.getX(Fx,0.2,1); M.MessageType = "New-WebMess"; M.setTime(AT+gap); EQ.insert(M); */ for (int pp=1; pp<=300; pp++) { double Fx = rnd.nextDouble(); double lowerBound = 1.0; double alpha = 1.5; //double gap = pareto.getX(Fx,lowerBound,alpha); double gap = pareto.getX(Fx,0.2,1); AT += gap; NewM = new Message(0,M.RouterTableNum,"New-WebMess",ProbingMessageSize*8,AT); EQ.insert(NewM); } flag = true; } if (!flag && (MessageType.compareTo("New-WebMess") == 0)) { double AT = M.getArrivalTime(); // generate a new web request message: "HTTP-request" // the original request message number is always 0 // the reference pages' number is start from 1 to reference number. NewM = new Message(0,M.RouterTableNum,"HTTP-request",ProbingMessageSize*8,AT); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); BottleneckLink.reset_bottlelink(AT); chart.Set_PointI(2); chart.Set_PointI(3); // probing message is triggered by the traffic generation // we are only interesting in the avaliable bandwidth under certain traffic // we choose four probing samples for each traffic generation if (AT >= Start_MeaTime) { double generation_time = M.getArrivalTime(); for (int i=1; i<=1; i++) { NewM = new Message(i,0,RoadTable[M.RouterTableNum].numOfNode, generation_time,"ICMP-request",ProbingMessageSize*8,generation_time,0,UnitripProbe); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); generation_time += 4*TInternalTime; } } // reset the next web request message generation time // the time is conform to pareto distribution double Fx = rnd.nextDouble(); double lowerBound = 1.0; double alpha = 1.5; //double gap = pareto.getX(Fx,lowerBound,alpha); double gap = pareto.getX(Fx,0.2,1); M.setTime(AT+gap); EQ.insert(M); flag = true; } if (!flag && (MessageType.compareTo("HTTP-request") == 0)) { // wakeup the corresponding object to handle this message // set the wakeup time of the message next time. boolean responseMess_GetToDestination = RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); if (!responseMess_GetToDestination) EQ.insert(M); flag = true; } // "HTTP-response" message type is only shown up in Web traffic pattern if (!flag && (MessageType.compareTo("HTTP-response") == 0)) { // wakeup the corresponding object to handle this message // set the wakeup time of the message next time. //double old_ArrivalTime = M.getArrivalTime(); boolean responseMess_GetToDestination = RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); if (!responseMess_GetToDestination) EQ.insert(M); // The response message does not back to its source if (responseMess_GetToDestination && traffic.trafficType.equals("Web")) { if (M.MessNum == 0) { // the last returned message generated by one request // how many references will be generated based on pareto distribution double Fx = rnd.nextDouble(); double lowerBound = 1.0; double alpha = 2.43; int numberOfReferences = (int) pareto.getX(Fx,lowerBound,alpha); double GenerationTime = M.getArrivalTime(); for(int i=1; i<= numberOfReferences; i++) { NewM = new Message(i,M.RouterTableNum,"HTTP-request",ProbingMessageSize*8,GenerationTime); RoadTable[NewM.RouterTableNum].Node(NewM.NextObjectIndex).EventHandler(NewM); EQ.insert(NewM); // the time gap between references is conform to weibull distribution Fx = rnd.nextDouble(); //lowerBound = 1.0; alpha = 1.46; double beta = 0.382; double gap = weibull.getX(Fx,alpha,beta); GenerationTime += gap; } } } flag = true; } if (!flag && (MessageType.compareTo("ICMP-request") == 0)) { // wakeup the corresponding object to handle this message // set the wakeup time of the message next time. if (UnitripProbe) { boolean responseMess_GetToDestination = RoadTable[M.RouterTableNum].Node(M.NextObjectIndex).EventHandler(M); if (!responseMess_GetToDestination) EQ.insert(M); // The response message does not back to its source else { double delaytime = M.getArrivalTime() - M.Pstarting_time - RoundTripTime; double NewRoundTripTime = M.getArrivalTime() - M.Pstarting_time; double Measured_Band ; Measured_Band = (BottleneckLinkBandwidth * RoundTripTime)/NewRoundTripTime; /* if (delaytime > 3.68e-5) Measured_Band = 46*8/delaytime; else Measured_Band = BottleneckLinkBandwidth; */ PFile.println("UnitripProbe Starting time: " + M.Pstarting_time); for (int i=0; i 3.68e-5) Measured_Band = 46*8/delaytime; else Measured_Band = BottleneckLinkBandwidth; */ PFile.println("Starting time: " + M.Pstarting_time); for (int i=0; i= Start_MeaTime) { // update the log file and chart long QueuingSize =(long)(BottleneckLink.Transfered_bit - (BottleneckLinkBandwidth*TBIntervalTime)); //long QueuingSize = EQ.getQueueSize(BottleneckLink,output_time); if (QueuingSize < 0) QueuingSize = 0; //double Available_BandWidth = LinkBandwidth - (BottleneckLink.Transfered_bit/TBIntervalTime); //if (QueuingSize > 0) double Available_BandWidth = BottleneckLinkBandwidth*((double)(ProbingMessageSize*8)/(ProbingMessageSize*8+QueuingSize)); LogFile.println("Starting Time: "+ BottleneckLink.Tstarting_time + " End Time: " + output_time + " Available BandWidth: "+ Available_BandWidth+" | " + QueuingSize + " | " +traffic.TIntervalTime + " | "+EQ.getNumElements()); temp_band = Available_BandWidth; if (trafficoutput) { final double time = output_time; final double band = Available_BandWidth*10/BottleneckLinkBandwidth; Runnable updateJPanel = new Runnable() { public void run() { chart.JPanelUpdate(2,time,band); } }; SwingUtilities.invokeLater(updateJPanel); } /* if ( Available_BandWidth < 100000) { PFile.close(); LogFile.close(); // close all the opened file in Router for(int i=1; i<= numOfRouter; i++) Routers[i].OFILE.close(); // close all the opened file in Link for(int i=1; i<= numOfLink; i++) Links[i].OFILE.close(); EventFile.close(); return; } */ //if (traffic.trafficType.equals("Slope")) // traffic.ArguChange(output_time > Start_MeaTime); } } }