From 1a1e0d50e6bcb29683293cf5cb73149ea2d507ba Mon Sep 17 00:00:00 2001 From: bgraansm Date: Sat, 26 Aug 2017 09:05:11 -0400 Subject: [PATCH] first commit --- Device.java | 66 +++++++++++++++++++++ Ethernet.java | 141 +++++++++++++++++++++++++++++++++++++++++++++ EthernetFrame.java | 46 +++++++++++++++ Event.java | 65 +++++++++++++++++++++ EventList.java | 38 ++++++++++++ EventType.java | 8 +++ FrameList.java | 19 ++++++ readme.txt | 9 +++ 8 files changed, 392 insertions(+) create mode 100644 Device.java create mode 100644 Ethernet.java create mode 100644 EthernetFrame.java create mode 100644 Event.java create mode 100644 EventList.java create mode 100644 EventType.java create mode 100644 FrameList.java create mode 100644 readme.txt diff --git a/Device.java b/Device.java new file mode 100644 index 0000000..f989173 --- /dev/null +++ b/Device.java @@ -0,0 +1,66 @@ +public class Device { + private EthernetFrame pending; + private int id; + private static Boolean cable = false; + private static double cableAvailNext = 0.0; + private static EthernetFrame cableFrame; + + public Device(int id) { + this.id = id; + } + + public Boolean hasPending() { + return this.pending != null; + } + + public EthernetFrame getFrame() { + return this.pending; + } + + public int getId() { + return this.id; + } + + public Boolean addFrame(EthernetFrame frame) { + if(this.hasPending()) { + return false; + } + + this.pending = frame; + frame.own(this.id); + return true; + } + + public Boolean listen() { + return this.cable; + } + + public Boolean send(){ + if(this.cable) { + return false; + } + this.cableAvailNext = this.pending.finishTime(); + this.cableFrame = this.pending; + this.cable = true; + return true; + } + + public void cableUse() { + this.cable = true; + } + + public double cableAvailTime() { + return this.cableAvailNext; + } + + public void sent() { + this.cable = false; + this.cableFrame = null; + this.cableAvailNext = 0.0; + this.pending = null; + } + + public EthernetFrame frameUse() { + return this.cableFrame; + } +} \ No newline at end of file diff --git a/Ethernet.java b/Ethernet.java new file mode 100644 index 0000000..3975a35 --- /dev/null +++ b/Ethernet.java @@ -0,0 +1,141 @@ +import java.util.*; +import java.text.*; + +public class Ethernet { + private static ArrayList available(ArrayList all) { + ArrayList available = new ArrayList(); + for(Device d : all) { + if(!d.hasPending()) { + available.add(d); + } + } + return available; + } + + public static void main(String[] args) { + long seed = 0; + int numberOfDevices = 0; + int numberOfFrames = 0; + int droppedFrames = 0; + double arrivalRate = 0.0; + double arrivalTime = 0.0; + double bytesSent = 0.0; + double throughput = 0.0; + double prevTime = 0.0; + double size = 0.0; + DecimalFormat df = new DecimalFormat("#.#"); + EventList events = new EventList(); + FrameList frames = new FrameList(); + Random rng; + ArrayList devices = new ArrayList(); + + try { + seed = Integer.parseInt(args[0]); + numberOfDevices = Integer.parseInt(args[1]); + numberOfFrames = Integer.parseInt(args[2]); + arrivalRate = Double.parseDouble(args[3]); + arrivalTime = 2560/arrivalRate; + } catch(NumberFormatException e) { + System.out.println("Arguments should be positive real numbers."); + System.exit(-1); + } catch(ArrayIndexOutOfBoundsException e) { + System.out.println("Please provide 4 arguments."); + System.exit(-1); + } catch(ArithmeticException e) { + System.out.println("arrival_rate should not be 0."); + System.exit(-1); + } + + System.out.println("Input:\tSeed from user = "+seed); + + if(seed == 0) { + seed = System.currentTimeMillis(); + } + rng = new Random(seed); + + System.out.println("\tSeed to use = "+seed); + System.out.println("\t# devices = "+numberOfDevices); + System.out.println("\t# frames to simulate = "+numberOfFrames); + System.out.println("\tMean # arrival frames/100 slot times = "+df.format(arrivalRate)); + System.out.println("\tMean arrival time = "+df.format(arrivalTime)); + + for(int i = 0; i < numberOfDevices; i++) { + devices.add(new Device(i)); + } + + double arrive = 0.0; + for(int i = 0; i < numberOfFrames; i++) { + arrive += rng.nextDouble()*2*arrivalRate; + size = ((Math.log(1-rng.nextDouble())/(-0.5))*1454)+72; + EthernetFrame frame = new EthernetFrame(arrive, size, i+1); + frames.add(frame); + events.add(new Event(arrive, frame, EventType.ARRIVE)); + } + + while(!events.complete()) { + Event next = events.next(); + Event todo; + ArrayList availDevices = available(devices); + Device dev = devices.get(next.getFrame().owner()); + + if(next.typeOfEvent() == EventType.ARRIVE) { + int index = rng.nextInt(availDevices.size()); + dev = availDevices.get(index); + + if(availDevices.size() == 0) { + System.out.println("Devices already have pending frames. Can't assign this frame to a device."); + System.exit(-1); + } + do { + dev = devices.get(rng.nextInt(numberOfDevices)); + } while(dev.hasPending()); + } else if(next.typeOfEvent() == EventType.SENT) { + bytesSent+=next.getFrame().size(); + } + + dev.addFrame(next.getFrame()); + todo = next.execute(dev); + + if(todo.typeOfEvent() == EventType.COLLISION) { + events.collision(dev.frameUse()); + System.out.println("Frame "+dev.frameUse().getId()+" sender detects "+dev.frameUse().getCollisions()+"th collision at "+df.format(next.time())+" mus"); + if(dev.frameUse().getCollisions() <= 10) { + double backoff = rng.nextDouble()*51.2*Math.pow(2.0, dev.frameUse().getCollisions()*1.0); + events.add(new Event(next.time()+backoff, dev.frameUse(), EventType.LISTEN)); + System.out.println("\t\tbacks off for "+df.format(backoff)+" mus"); + } else { + droppedFrames++; + System.out.println("Frame "+dev.frameUse().getId()+" dropped at "+df.format(next.time())+" mus"); + } + events.collision(next.getFrame()); + System.out.println("Frame "+next.getFrame().getId()+" sender detects "+next.getFrame().getCollisions()+"th collision at "+df.format(next.time())+" mus"); + if(next.getFrame().getCollisions() <= 10) { + double backoff = rng.nextDouble()*51.2*Math.pow(2.0, next.getFrame().getCollisions()*1.0); + events.add(new Event(next.time()+backoff, next.getFrame(), EventType.LISTEN)); + System.out.println("\t\tbacks off for "+df.format(backoff)+" mus"); + } else { + droppedFrames++; + System.out.println("Frame "+next.getFrame().getId()+" dropped at "+df.format(next.time())+" mus"); + } + } else if(todo.typeOfEvent() == EventType.FIRST72) { + if(next.time() > prevTime) { + dev.cableUse(); + } + } + if(todo.typeOfEvent() != EventType.NONE && todo.typeOfEvent() != EventType.COLLISION) { + events.add(todo); + } else { + dev.sent(); + } + prevTime = next.time(); + } + + throughput = bytesSent/(prevTime*1000000); + + System.out.println("Performance Report:"); + System.out.println("\t# simulated frames = "+numberOfFrames+" frames"); + System.out.println("\t# bytes successfully sent = "+df.format(bytesSent)+" bytes"); + System.out.println("\t# dropped frames = "+droppedFrames+" frames"); + System.out.println("\t# Ethernet throughput = "+throughput+" bps = "+df.format(throughput*1000000)+" Mbps"); + } +} \ No newline at end of file diff --git a/EthernetFrame.java b/EthernetFrame.java new file mode 100644 index 0000000..798daef --- /dev/null +++ b/EthernetFrame.java @@ -0,0 +1,46 @@ +public class EthernetFrame { + private double arrivalTime; + private int sender; + private double size; + private int id; + private int collisions; + + public EthernetFrame(double arrivalTime, double size, int id) { + this.arrivalTime = arrivalTime; + this.size = size; + this.id = id; + this.collisions = 0; + } + + public double time() { + return 51.6f*this.size/72; + } + + public void detectCollision() { + this.collisions++; + } + + public int getCollisions() { + return this.collisions; + } + + public double finishTime() { + return this.time() + this.arrivalTime; + } + + public void own(int sender) { + this.sender = sender; + } + + public int owner() { + return this.sender; + } + + public int getId() { + return this.id; + } + + public double size() { + return this.size; + } +} \ No newline at end of file diff --git a/Event.java b/Event.java new file mode 100644 index 0000000..d822c74 --- /dev/null +++ b/Event.java @@ -0,0 +1,65 @@ +import java.text.*; + +public class Event { + private double timeOccur; + private EthernetFrame frame; + private EventType type; + + public Event(double time, EthernetFrame frame, EventType type) { + this.timeOccur = time; + this.frame = frame; + this.type = type; + } + + public EthernetFrame getFrame() { + return this.frame; + } + + public double time() { + return this.timeOccur; + } + + public EventType typeOfEvent() { + return this.type; + } + + public Event execute(Device device) { + DecimalFormat df = new DecimalFormat("#.#"); + switch(this.type) { + case ARRIVE: + device.addFrame(this.frame); + System.out.println("Frame "+this.frame.getId()+" arrives @ "+df.format(this.timeOccur)+" mus"); + System.out.println("\tF"+this.frame.getId()+": len="+df.format(this.frame.size())+" dlvtm="+df.format(this.frame.time())+" sdr="+this.frame.owner()+" listen arr@"+df.format(this.timeOccur)+" col="+this.frame.getCollisions()); + + return new Event(this.timeOccur+1.0, this.frame, EventType.LISTEN); + case LISTEN: + String state = "quiet: sends"; + Event ret; + + if(device.listen() && this.timeOccur < device.cableAvailTime()) { + state = "busy"; + ret = new Event(device.cableAvailTime(), this.frame, EventType.LISTEN); + } else { + if(!device.send()) { + this.frame.detectCollision(); + ret = new Event(this.timeOccur+3686.4, this.frame, EventType.COLLISION); + } else { + ret = new Event(this.timeOccur+3686.4, this.frame, EventType.FIRST72); + } + } + System.out.println("Frame "+this.frame.getId()+" sender listens @ "+df.format(this.timeOccur)+" mus ... "+state); + return ret; + + case COLLISION: + break; + case FIRST72: + System.out.println("Frame "+this.frame.getId()+" 1st 72 bytes delivered @ "+df.format(this.timeOccur)+" mus"); + return new Event(this.timeOccur+(51.2*this.frame.size()/72), this.frame, EventType.SENT); + case SENT: + device.sent(); + System.out.println("Frame "+this.frame.getId()+" sending is complete @ "+df.format(this.timeOccur)+" mus"); + this.type = EventType.NONE; + } + return this; + } +} \ No newline at end of file diff --git a/EventList.java b/EventList.java new file mode 100644 index 0000000..80f5be7 --- /dev/null +++ b/EventList.java @@ -0,0 +1,38 @@ +import java.util.*; + +public class EventList { + ArrayList list; + + public EventList() { + this.list = new ArrayList(); + } + + public void add(Event event) { + for(int i=0; i copy = new ArrayList(this.list); + for(int i=copy.size()-1; i>=0; i--) { + if(copy.get(i).getFrame() == frame) { + this.list.remove(i); + } + } + } + + public Boolean complete() { + return this.list.size() == 0; + } + + public Event next() { + Event event = this.list.get(0); + this.list.remove(0); + return event; + } +} \ No newline at end of file diff --git a/EventType.java b/EventType.java new file mode 100644 index 0000000..0be858f --- /dev/null +++ b/EventType.java @@ -0,0 +1,8 @@ +public enum EventType { + ARRIVE, + LISTEN, + COLLISION, + FIRST72, + SENT, + NONE +} \ No newline at end of file diff --git a/FrameList.java b/FrameList.java new file mode 100644 index 0000000..5885925 --- /dev/null +++ b/FrameList.java @@ -0,0 +1,19 @@ +import java.util.*; + +public class FrameList { + ArrayList list; + + public FrameList() { + this.list = new ArrayList(); + } + + public void add(EthernetFrame frame) { + this.list.add(frame); + } + + public EthernetFrame nextFrame() { + EthernetFrame frame = this.list.get(0); + this.list.remove(0); + return frame; + } +} \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..eb22de9 --- /dev/null +++ b/readme.txt @@ -0,0 +1,9 @@ +Assignment No. 2: CIS*2460 - Modelling of Computer Systems +Bronson Graansma 0872249 + -- + To run the simulation: + Navigate to this directory in a command line / shell. + Type: "java Ethernet " + if this fails, type: "javac *.java" and try again. + + Thanks