diff --git a/a.out.dSYM/Contents/Info.plist b/a.out.dSYM/Contents/Info.plist new file mode 100644 index 0000000..3679a65 --- /dev/null +++ b/a.out.dSYM/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.a.out + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/f.txt b/f.txt new file mode 100644 index 0000000..0928128 --- /dev/null +++ b/f.txt @@ -0,0 +1,366 @@ +lambda: 0.01 +T: 20 +Throughput: 308.701 Bps +Average Network Delay: 8.26926e-07 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 40 +Throughput: 31.8001 Bps +Average Network Delay: 3.12177e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 80 +Throughput: 241.501 Bps +Average Network Delay: 9.86634e-07 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 160 +Throughput: 122.1 Bps +Average Network Delay: 1.92688e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 320 +Throughput: 97.6004 Bps +Average Network Delay: 4.78762e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 400 +Throughput: 97.1004 Bps +Average Network Delay: 4.78138e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.05 +T: 20 +Throughput: 1279.03 Bps +Average Network Delay: 8.88095e-07 s/B +Average Network Delay: 0.000946561 s/packet +Average Network Delay (per instructions): 8.88073e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 40 +Throughput: 849.72 Bps +Average Network Delay: 1.14496e-06 s/B +Average Network Delay: 0.000810727 s/packet +Average Network Delay (per instructions): 1.14493e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 80 +Throughput: 812.92 Bps +Average Network Delay: 1.42929e-06 s/B +Average Network Delay: 0.000968227 s/packet +Average Network Delay (per instructions): 1.42926e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 160 +Throughput: 950.123 Bps +Average Network Delay: 1.69863e-06 s/B +Average Network Delay: 0.00134489 s/packet +Average Network Delay (per instructions): 1.69859e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 320 +Throughput: 1091.73 Bps +Average Network Delay: 3.01445e-06 s/B +Average Network Delay: 0.00274239 s/packet +Average Network Delay (per instructions): 3.01438e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 400 +Throughput: 419.51 Bps +Average Network Delay: 6.62425e-06 s/B +Average Network Delay: 0.00231573 s/packet +Average Network Delay (per instructions): 6.62409e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.1 +T: 20 +Throughput: 2231.71 Bps +Average Network Delay: 9.29801e-07 s/B +Average Network Delay: 0.00086456 s/packet +Average Network Delay (per instructions): 9.29756e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 40 +Throughput: 1513.97 Bps +Average Network Delay: 1.19423e-06 s/B +Average Network Delay: 0.00075331 s/packet +Average Network Delay (per instructions): 1.19417e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 80 +Throughput: 1974.59 Bps +Average Network Delay: 1.40083e-06 s/B +Average Network Delay: 0.00115248 s/packet +Average Network Delay (per instructions): 1.40076e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 160 +Throughput: 1723.88 Bps +Average Network Delay: 1.99556e-06 s/B +Average Network Delay: 0.00143331 s/packet +Average Network Delay (per instructions): 1.99546e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 320 +Throughput: 2161.6 Bps +Average Network Delay: 2.68931e-06 s/B +Average Network Delay: 0.00242206 s/packet +Average Network Delay (per instructions): 2.68918e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 400 +Throughput: 2001.2 Bps +Average Network Delay: 3.08128e-06 s/B +Average Network Delay: 0.00256914 s/packet +Average Network Delay (per instructions): 3.08113e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.3 +T: 20 +Throughput: 5703.78 Bps +Average Network Delay: 9.20996e-07 s/B +Average Network Delay: 0.000772418 s/packet +Average Network Delay (per instructions): 9.20871e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 40 +Throughput: 6070.34 Bps +Average Network Delay: 1.06254e-06 s/B +Average Network Delay: 0.000921299 s/packet +Average Network Delay (per instructions): 1.06239e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.3 +T: 80 +Throughput: 4687.34 Bps +Average Network Delay: 1.40599e-06 s/B +Average Network Delay: 0.000969035 s/packet +Average Network Delay (per instructions): 1.4058e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 160 +Throughput: 3632.19 Bps +Average Network Delay: 2.43176e-06 s/B +Average Network Delay: 0.00129874 s/packet +Average Network Delay (per instructions): 2.43143e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 320 +Throughput: 6025.24 Bps +Average Network Delay: 2.72344e-06 s/B +Average Network Delay: 0.00234387 s/packet +Average Network Delay (per instructions): 2.72306e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.3 +T: 400 +Throughput: 5730.1 Bps +Average Network Delay: 3.0147e-06 s/B +Average Network Delay: 0.00246744 s/packet +Average Network Delay (per instructions): 3.01428e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.6 +T: 20 +Throughput: 11168.7 Bps +Average Network Delay: 9.5311e-07 s/B +Average Network Delay: 0.000831432 s/packet +Average Network Delay (per instructions): 9.52867e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 128 +------------------------------------------------------ +lambda: 0.6 +T: 40 +Throughput: 9911.4 Bps +Average Network Delay: 1.10231e-06 s/B +Average Network Delay: 0.000866879 s/packet +Average Network Delay (per instructions): 1.10203e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 80 +Throughput: 10761 Bps +Average Network Delay: 1.2735e-06 s/B +Average Network Delay: 0.00108736 s/packet +Average Network Delay (per instructions): 1.27318e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 160 +Throughput: 10981.2 Bps +Average Network Delay: 1.78939e-06 s/B +Average Network Delay: 0.0015591 s/packet +Average Network Delay (per instructions): 1.78894e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 320 +Throughput: 8163.86 Bps +Average Network Delay: 3.50556e-06 s/B +Average Network Delay: 0.00227077 s/packet +Average Network Delay (per instructions): 3.50468e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 400 +Throughput: 10973.4 Bps +Average Network Delay: 3.42795e-06 s/B +Average Network Delay: 0.00280644 s/packet +Average Network Delay (per instructions): 3.42704e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 134 +------------------------------------------------------ +lambda: 0.8 +T: 20 +Throughput: 14293.4 Bps +Average Network Delay: 9.2127e-07 s/B +Average Network Delay: 0.000792997 s/packet +Average Network Delay (per instructions): 9.20965e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 40 +Throughput: 15190.9 Bps +Average Network Delay: 1.03502e-06 s/B +Average Network Delay: 0.000946853 s/packet +Average Network Delay (per instructions): 1.03468e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 80 +Throughput: 11400.2 Bps +Average Network Delay: 1.45895e-06 s/B +Average Network Delay: 0.00100161 s/packet +Average Network Delay (per instructions): 1.45846e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 160 +Throughput: 14805.4 Bps +Average Network Delay: 1.81492e-06 s/B +Average Network Delay: 0.00161818 s/packet +Average Network Delay (per instructions): 1.81432e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 320 +Throughput: 14111.3 Bps +Average Network Delay: 2.78043e-06 s/B +Average Network Delay: 0.00233467 s/packet +Average Network Delay (per instructions): 2.7795e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 168 +------------------------------------------------------ +lambda: 0.8 +T: 400 +Throughput: 13067.2 Bps +Average Network Delay: 3.4313e-06 s/B +Average Network Delay: 0.00270017 s/packet +Average Network Delay (per instructions): 3.43016e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.9 +T: 20 +Throughput: 14621.9 Bps +Average Network Delay: 9.75482e-07 s/B +Average Network Delay: 0.000774898 s/packet +Average Network Delay (per instructions): 9.75125e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 184 +------------------------------------------------------ +lambda: 0.9 +T: 40 +Throughput: 15429.4 Bps +Average Network Delay: 1.12303e-06 s/B +Average Network Delay: 0.000951725 s/packet +Average Network Delay (per instructions): 1.12262e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 80 +Throughput: 15956.5 Bps +Average Network Delay: 1.29028e-06 s/B +Average Network Delay: 0.00113082 s/packet +Average Network Delay (per instructions): 1.28981e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 160 +Throughput: 13024.3 Bps +Average Network Delay: 1.92281e-06 s/B +Average Network Delay: 0.00139079 s/packet +Average Network Delay (per instructions): 1.92211e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 180 +------------------------------------------------------ +lambda: 0.9 +T: 320 +Throughput: 14204.8 Bps +Average Network Delay: 3.03224e-06 s/B +Average Network Delay: 0.00236575 s/packet +Average Network Delay (per instructions): 3.03114e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 400 +Throughput: 15867.7 Bps +Average Network Delay: 3.1339e-06 s/B +Average Network Delay: 0.0027313 s/packet +Average Network Delay (per instructions): 3.13276e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ diff --git a/fwlan.cpp b/fwlan.cpp new file mode 100644 index 0000000..57df419 --- /dev/null +++ b/fwlan.cpp @@ -0,0 +1,837 @@ +#include +#include +#include +#include +#include // max +#include +#include +#include // for hooman random stuff + + +// these should be constant for our project + const double maxRTM = 3; // maximum number of retransmissions + const int maxPktSize = 1544; // maximum size of a packet in bytes + const int ackPktSize = 64; // acknowledgement packet size in bytes + const double channelCapacity = 11000000.0; // 11 Mbps (bits) + const double SIFS = 0.00005; // 0.05 msec, delay before ack + const double DIFS = 0.0001; // 0.1 msec, delay before send + const double SYNC = 0.00001; // 0.01 msec + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*std::log(1-u)); +} + +double dataLengthFrame(double rate) +{ + // http://en.cppreference.com/w/cpp/numeric/random/exponential_distribution + std::random_device rd; + std::mt19937 gen(rd()); + + std::exponential_distribution<> d(1); // generate nedt between 0 and 1 + + return int(maxPktSize * d(gen)); +} + +double transmissionTime(int bytes) +{ + return (bytes * 8) / (channelCapacity); +} + +// generate a random backoff value less than or equal to T that is not currently in the backoff list +int generateRandomBackOff(int T, const int backoff[], int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(1, T); //(inclusive, inclusive) + + int rd = idist(rgen); + + // make sure the backoff value is not already given to another node + // this is for collision avoidance as the TA told us to do, even though + // it doesn't really happen in real life. + for (int i = 0; i < N; i++) + { + if (rd == backoff[i]) + { + return generateRandomBackOff(T, backoff, N); + } + } + return rd; +} + +int randomDestination(int source, int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, N - 1); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + rd = randomDestination(source, N); + } + return rd; +} + +enum eventtype { + arrival, departure, sync, timeout +}; + + +class Event { +protected: + double eventTime; + eventtype type; + + +public: + Event(eventtype type, double etime): eventTime(etime), type(type) {} + virtual ~Event(){} + + double getEventTime() { + return eventTime; + } + + eventtype getType() + { + return type; + } + +}; + +class Arrival: public Event { + static double lambda; + + int host; + +public: + Arrival(double stime, int h): Event(arrival, stime + nedt(lambda)), host(h) {} + + static void setLambda(double l) + { + lambda = l; + } + + int getHost() + { + return host; + } + +}; + +double Arrival::lambda = 0; + +class Departure: public Event { + + // shape of packet size distribution + static double mu; + + bool ack; // denotes if it is an acknowedgement packet + int source; // source host + int destination; // destination host + int packetID; // id of packet, see host class + int size; // paket size in bytes, used to determine throughput + +public: + Departure(double stime, int s, int d, int id, bool a): Event(departure, stime), ack(a), source(s), destination(d), packetID(id) + { + // if ack packet, set the time to be that size + // time already current time, so just need to add the new time. + if(ack) + { + // this shouldn't be how it works in real life + // we're supposed to scan the channel during sifs, + // then if clear set channel to busy and transmit. + // For this project TA say just add SIFS, which is easier so OK then + size = ackPktSize; + eventTime += (SIFS + transmissionTime(size)); + } + else + { + // same comment as above, except DFIS + size = dataLengthFrame(mu); + eventTime += (DIFS + transmissionTime(size)); + + } + + } + + static void setMu(double m) + { + mu = m; + } + + bool isAck() + { + return ack; + } + + int getSource() + { + return source; + } + int getDestination() + { + return destination; + } + int getPacketID() + { + return packetID; + } + int getSize() + { + return size; + } + + +}; + +double Departure::mu = 0; + +class Sync: public Event { + + static double SYNC; + +public: + Sync(double stime): Event(sync, stime + SYNC) {} + + static void setSYNC(double s) + { + SYNC = s; + } + +}; + +double Sync::SYNC = 0; + +class Timeout: public Event{ + + static double to_time; + + int host; + int timeoutID; +public: + Timeout(double stime, int h, int id): Event(timeout, stime + to_time), host(h), timeoutID(id) {} + + static void setTO(double t) + { + to_time = t; + } + + + int getHost() + { + return host; + } + + int getTimeoutID() + { + return timeoutID; + } + +}; + +double Timeout::to_time = 0; + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); // this line may not be necessary, but oh well + } + + void insert(Event *event) { + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if ((*itr)->getEventTime() > event->getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + } // insert sorted by events time + + Event* removeFirst() { + + Event *firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + +// not sure i need all this stuff yet +class Packet { + int destination; + bool isAck; // true acknowledgement, false datapacket + int ackID; // used to make sure ack makes sense and stuff + double queueTime; // time when packet first queued, used for statistics (Network delay) + + + friend class Host; + +public: + Packet(double t, int dest, bool ack, int id = 0): destination(dest), isAck(ack), ackID(id), queueTime(t){} + + +}; + +class Host { + static int NumHosts; // need to know this in order to create random destination + static int T; // maximum backoff given no retransmissions + // static array so we can implement collision avoidance + static int* backoff; // doing it in syc tics versus real time because easier for conflict avoidance + // backoff < 0 means nothing in queue (nothing to transmit) + // backoff > 0 means waiting to transmit + // backoff == 0 means either transmitting or waiting for ack + + int packetID; // the number of the packet sent. + // Not worring about overflow, and even it it does, it should still work correctly. + // Used to cordinate acks and timeouts. + // If a timeout occurs, there's a chance that there will be acks in the network + // that don't refer to the most recent transmission. + + int droppedPackets; // not necessary for our project, but i think it might be interesting to keep track of + int hostID; // position in hosts array, maybe don't need this, but might if put create packets and stuff + int tmNum; // transmission number, max tmNum = 1 + maxRTM. Max backoff = tmNum * T + + double retransmitTime; // used to calculate delay when there has been a retransmission + double delay; // total delay, used for statistics. + std::queue packetQueue; // i think its initialized implicitly + +public: + // initially set backoff to (-1) to show that nothing in queue + Host(int id): packetID(0), droppedPackets(0), hostID(id), tmNum(0), retransmitTime(0), delay(0){ + backoff[id] = -1; + } + + // initialize static variables + static void initHosts(int N, int t) + { + NumHosts = N; + backoff = new int[N]; + T = t; + } + + double getDelay() + { + return delay; + } + + int getDropedPackets() + { + return droppedPackets; + } + + void enqueueDataPacket(double stime) + { + packetQueue.push(Packet(stime, randomDestination(hostID, NumHosts), false)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet. + // in real life I don't think the first packet waits for a backoff, + // but the TAs told us to do it this way. + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + void enqueueAckPacket(double stime, int dest, int ackID) + { + + // In real life I don't think the ack goes in the back of the queue, + // But the TAs told us to do it this way. + + packetQueue.push(Packet(stime, dest, true, ackID)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + + } + + // decrements backoff value if it is larger than zero + // returns true if this act makes the value 0, and thus the Host is ready to transmit + bool decrementBackoff() + { + if (backoff[hostID] > 0) + { + --(backoff[hostID]); + if(backoff[hostID] == 0) + return true; + } + return false; + } + + + void receiveAck(int AckID) + { + // if correct ack, can pop packet from start of queue + if (AckID == packetID) + { + //std::cerr << "receive correct ack, Host: " << hostID << ", AckID: " << AckID << std::endl; + packetQueue.pop(); // pop packet from queue + packetID++; // new packet to send, so increment packetID + tmNum = 0; // need to reset TmNum because new packet to transmit. + // if no more packets in queue, indicate it by setting backoff id to -1 + if (packetQueue.empty()) + { + backoff[hostID] = -1; + } + // eles if still packet to send, set new backoff value + else + { + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + + + } + // if AckID does not match PacketID do nothing + // should never get out of order ack because can only sent 1 packet at a time + } + + void receiveTimeout(double stime, int TO_ID) + { + // if timeout refers to current packet, need to resend with larger backoff + if (TO_ID == packetID) + { + // if haven't reached maximum transmissions yet, need to retransmit it by resetting backoff value + // tmNum refers to current transmission. On transmission 3, there have been 2 retransmissions + // if MaxRTM = 3, then should be able to send another one. + // if MaxRTM = 3 and tmNum = 4, then there have already been 3 retransmissions and need to abort + if (tmNum <= maxRTM) + { + // need to reset packet queue time because should not double count delay when waiting for ack + // actually, i don't want to make it a queue of pointers so i'll do this hack instead + retransmitTime = stime; + + // need to increase mack backoff by a multiple of (tmNum + 1), + // since tmNum in incremented when departure event created, but need to use that as a multiplyer here + backoff[hostID] = generateRandomBackOff(T * (tmNum + 1), backoff, NumHosts); + } + // else need to drop packet. Do this by pretending to ack it + else + { + droppedPackets++; + receiveAck(packetID); + + } + + } + + } + + + // performs packet processing and prepares packet for departure + // returns a departure event + // not going to do error checking, so assumes that there is at least 1 packet in the queue and that hopeufully backoff == 0 + // actually, maybe will do error checking + Departure* createDeparture(double stime) + { + // i lied, error checking + if (backoff[hostID] != 0) + std::cerr << "Host creating Departure event when backoff != 0" << std::endl; + // the other one should cause runtime issues if bug, so won't check for it + // no that's stupid + if (packetQueue.empty()) + { + std::cerr << "Host creating Departure event when queue empty" << std::endl; + + return NULL; + } + + + + // get packet info + Packet p = packetQueue.front(); + + Departure* depart; // holds return value + + + //std::cerr << "creating departure with destination: " << p.destination << std::endl; + + // if an ack packet, create ack event + // since we don't need to wait for ack, can immediatley pretend we got one + if (p.isAck) + { + receiveAck(packetID); + depart = new Departure(stime, hostID, p.destination, p.ackID, true); + } + // else need to create packet and increment tmNum + else + { + depart = new Departure(stime, hostID, p.destination, packetID, false); + tmNum ++; + + + } + + // calculate delay + // if this is a retransmission (tmNum > 1), then need to use retransmitTime as a base + if (tmNum > 1) + { + delay += (depart->getEventTime() - retransmitTime); + } + // else use packet time as a base + else + { + delay += (depart->getEventTime() - p.queueTime); + } + + return depart; + + } + + Timeout* createTimeout(double stime) + { + return new Timeout(stime, hostID, packetID); + } + +}; + +int* Host::backoff = NULL; +int Host::NumHosts = 0; +int Host::T = 0; + + + +int main(int argc, char const *argv[]) +{ + +// read from command line, but given default values + double lambda = 0.01; // dexcribes shape of arrival distribution + double mu = 1; // describes shape of distribution of PktSize (r) + int N = 20; // number of hosts in network. + int T = 400; // maximum backoff value in number sync cycles. Should be larger than N I suppose. + double TO = 0.005; // for project, will take values of 5, 10, or 15 msec. + int eventsSimulated = 1000000; // the bound of for loop + +// these are variables used throught the program + double time = 0; // time simulated since start of simulation in seconds + double transmitted = 0; // number of bytes successfully transmitted (will include ack bytes) + double delay = 0; // queue + transmission delay in seconds + int packets = 0; + bool channelBusy = false; // true if channel is busy, false otherwise + +// containers + Host* *hosts; // an array of host pointers + GEL* eventList; // holds list of events + + // check if help option set (or if only 1 argument, since that would be invalid). + // If so, print help information and end program + if ((argc > 1 && std::string("-help") == argv[1]) || argc == 2) + { + std::cout << "\nThis program simulates an IEEE 802.11-Based Wireless LAN. \n" + "To set parameters of network, use the following commands.\n" + "Default values are given in parenthesis.\n\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n"<< std::endl; + + return 0; + } + + // read in command line inputs, assume all inputs come in a -var val pair + for (int i = 1; i + 1 < argc; i += 2) + { + // i probably should have made this a function, but i already did the copy paste so really no use now + if (std::string("-N") == argv[i]) + try{ + N = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -N, using default value " << N << std::endl; + } + else if (std::string("-l") == argv[i]) + try{ + lambda = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -l, using default value " << lambda << std::endl; + } + else if (std::string("-m") == argv[i]) + try{ + mu = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -m, using default value " << mu << std::endl; + } + else if (std::string("-T") == argv[i]) + try{ + T = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -T, using default value " << T << std::endl; + } + else if (std::string("-t") == argv[i]) + try{ + TO = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -t, using default value " << TO << std::endl; + } + else if (std::string("-s") == argv[i]) + try{ + eventsSimulated = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -s, using default value " << eventsSimulated << std::endl; + } + else + { + std::cout << "invalid option \"" << argv[i] <<"\". To see valid options, run \"" << argv[0] << " -help\"" << std::endl; + } + } + + /*std::cout << "checking values:\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" << std::endl; + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n" << std::endl;*/ + + + + + // Now the simulation can finally begin + + hosts = new Host*[N]; // create an array to hold all Hosts + eventList = new GEL(); // create a list of events + Event* e; // holds the event currently being manipulated + + // initialize static variables of events + Arrival::setLambda(lambda); + Departure::setMu(mu); + Sync::setSYNC(SYNC); + Host::initHosts(N, T); + Timeout::setTO(TO); + + + // initialize each host and create its initial arrival event + for (int i = 0; i < N; i++) + { + hosts[i] = new Host(i); + eventList->insert(new Arrival(time, i)); + + } + + eventList->insert(new Sync(time)); // create the first sync event + + + for(int i = 0; i < eventsSimulated; i++) + { + // pop event to handle + e = eventList->removeFirst(); + + // update time + time = e->getEventTime(); + + if (e->getType() == arrival) + { + // cast to arrival pointer + Arrival *a = static_cast(e); + + // check if cast actually worked + if (a) + { + // need to create a new arrival event for the previous arrival event's host + eventList->insert(new Arrival(time, a->getHost())); + + // following line testing behaviour of arrival event + //std::cout << "process arrival event for host: " << a->getHost() << " at time: " << a->getEventTime() << std::endl; + + // now need to put packet in queue of host. + // will generate length of packet on demand when create a departure event + // but need to indicate that it is not a ack packet + hosts[a->getHost()]->enqueueDataPacket(time); + + } + else // not actually an arrival pointer + { + std::cerr << "error: process event of arrival type that wasn't actually an arrival event" << std::endl; + } + } + + + else if (e->getType() == departure) + { + // cast to departure pointer + Departure *d = static_cast(e); + + // check if cast actually worked + if (d) + { + // keep track of bytes transmitted + transmitted += d->getSize(); + packets ++; + + + // if an ack departure, need to notify receiving host + if (d->isAck()) + { + // using an integer for packet IDs + hosts[d->getDestination()]->receiveAck(d->getPacketID()); + + } + // if a data departure, need to create ack packet in destination queue + else + { + hosts[d->getDestination()]->enqueueAckPacket(time, d->getSource(), d->getPacketID()); + } + // set channel to free + channelBusy = false; + + + } + else // not actually a departure pointer + { + std::cerr << "error: process event of departure type that wasn't actually a departure event" << std::endl; + } + + } + else if (e->getType() == sync) + { + // cast to Sync pointer + Sync *s = static_cast(e); + + // check if cast actually worked + if (s) + { + // need to create a new Sync event + eventList->insert(new Sync(time)); + + //std::cout << "process sync event at time: " << s->getEventTime() << std::endl; + + // if channel is free, go through all hosts and decrement backoff. + // if backoff reaches zero, set channel to busy and create departure event + // also continue to decrement the rest of the backoffs to help with collision avoidance + if (channelBusy == false) + { + // possible host that needs to transmit + int hostToProcess = -1; + for (int i = 0; i < N; i++) + { + // decrements backoff value, returns true if backoff becomes zero + // need to save host index if it needs to be processed + // since we provide collision detection, there should only ever be one host ready to process + if(hosts[i]->decrementBackoff()) + { + hostToProcess = i; + } + + // if a host was selected to process, need to process it + + } + if (hostToProcess >= 0) + { + // have the host create a departure event + Departure* departHelp = (hosts[hostToProcess]->createDeparture(time)); + if (departHelp) + { + eventList->insert(departHelp); + // create a timeout event tied to the host, but only if not ack + if (!departHelp->isAck()) + { + eventList->insert(hosts[hostToProcess]->createTimeout(time)); + + } + // set channel to busy + channelBusy = true; + } + } + } + + + } + else // not actually a sync pointer + { + std::cerr << "error: process event of sync type that wasn't actually a sync event" << std::endl; + } + + } + else if (e->getType() == timeout) + { + // cast to arrival pointer + Timeout *t = static_cast(e); + + // check if actually worked + if (t) + { + // tell host that timeout event occured + hosts[t->getHost()]->receiveTimeout(time, t->getTimeoutID()); + + } + else // not actually a timeout pointer + { + std::cerr << "error: process event of timeout type that wasn't actually a timeout event" << std::endl; + } + } + + // free memory of processed event + delete e; + + + } + + int drop = 0; + + for (int i = 0; i < N; i++) + { + delay += hosts[i]->getDelay(); + drop += hosts[i]->getDropedPackets(); + } + + std::cout << "lambda: " << lambda << std::endl; + std::cout << "T: " << T << std::endl; + std::cout << "N: " << N << std::endl; + + std::cout << "Throughput: " << transmitted / time << " Bps" << std::endl; + std::cout << "Average Network Delay: " << delay / transmitted << " s/B" << std::endl; // I changed this to make sense + // std::cout << "Average Network Delay: " << delay / packets << " s/packet" << std::endl; // I changed this to make sense + // std::cout << "Average Network Delay (per instructions): " << delay / (transmitted/time) << " s^2/B" << std::endl; // This is what doesn't make sense + + std::cout << "Packets Dropped: " << drop << std::endl; + std::cout << "Packets Sent: " << packets << std::endl; + + std::cout << "------------------------------------------------------" << std::endl; + + // delete dynamically allocated data + for (int i = 0; i < N; i++) + { + delete hosts[i]; + } + delete hosts; + delete eventList; + +} \ No newline at end of file diff --git a/hack.cpp b/hack.cpp new file mode 100644 index 0000000..b916f10 --- /dev/null +++ b/hack.cpp @@ -0,0 +1,42 @@ +#include +#include + + +enum type +{ + arrival, departure, sync, timeout +}; + +class foo +{ +public: + int lol; + + foo() + { + lol = 10; + } +}; + + +int main (int argc, const char** argv) +{ + + type t; + t = departure; + std::cout << "type: " << t << std::endl; + int N = 10; + for (int i = 1; i + 1 < argc; i += 2) + { + if (std::string("-N") == argv[i]) + N = std::stoi(argv[i+1]); + } + std::cout << "N = " << N << std::endl; + + foo* list = new foo[N]; + for (int i = 0; i < N; i ++) + { + std::cout << list[i].lol << std::endl; + } + +} \ No newline at end of file diff --git a/hack2.cpp b/hack2.cpp new file mode 100644 index 0000000..aa50ea8 --- /dev/null +++ b/hack2.cpp @@ -0,0 +1,44 @@ +#include +#include + + +enum type +{ + arrival, departure, sync, timeout +}; + +class foo +{ +public: + int lol; + + foo() + { + lol = 10; + } +}; + + +int main (int argc, const char** argv) +{ + + type t; + t = departure; + std::cout << "type: " << t << std::endl; + int N = 10; + for (int i = 1; i + 1 < argc; i += 2) + { + if (std::string("-N") == argv[i]) + N = std::stoi(argv[i+1]); + } + std::cout << "N = " << N << std::endl; + + foo* list = new foo[N]; + N = 10; + int list2[N]; + for (int i = 0; i < N; i ++) + { + std::cout << list[i].lol << std::endl; + } + +} \ No newline at end of file diff --git a/hack3.cpp b/hack3.cpp new file mode 100644 index 0000000..346067e --- /dev/null +++ b/hack3.cpp @@ -0,0 +1,83 @@ + +#include // random host + +#include + +using namespace std; + +int randomDestination(int source, int N) +{ + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, N - 1); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + rd = randomDestination(source, N); + } + return rd; +} + +int generateRandomBackOff(int T, const int backoff[], int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(1, T); //(inclusive, inclusive) + + int rd = idist(rgen); + + // make sure the backoff value is not already given to another node + // this is for collision avoidance as the TA told us to do, even though + // it doesn't really happen in real life. + for (int i = 0; i < N; i++) + { + if (rd == backoff[i]) + { + return generateRandomBackOff(T, backoff, N); + } + } + return rd; +} + + +int main(int argc, const char* argv[]) +{ + int N, h, T; + + cout << "enter nuber of hosts: " ; + cin >> N ; + cout << "enter maximum backoff: " ; + cin >> T ; + + int data[N]; + for (int i = 0; i < N; i++) + { + data[i] = -1; + } + + + while (true) + { + cout << "enter source host: " ; + cin >> h; + data[h] = 0; + data[h] = generateRandomBackOff(T, data, N); + + for (int i = 0; i < N; i++){ + + cout << i << ": " << data[i] << endl; + } + + } + + + + + + + +return 0; +} diff --git a/n.txt b/n.txt new file mode 100644 index 0000000..0928128 --- /dev/null +++ b/n.txt @@ -0,0 +1,366 @@ +lambda: 0.01 +T: 20 +Throughput: 308.701 Bps +Average Network Delay: 8.26926e-07 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 40 +Throughput: 31.8001 Bps +Average Network Delay: 3.12177e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 80 +Throughput: 241.501 Bps +Average Network Delay: 9.86634e-07 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 160 +Throughput: 122.1 Bps +Average Network Delay: 1.92688e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 320 +Throughput: 97.6004 Bps +Average Network Delay: 4.78762e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.01 +T: 400 +Throughput: 97.1004 Bps +Average Network Delay: 4.78138e-06 s/B +Packets Dropped: 0 +Packets Sent: 2 +------------------------------------------------------ +lambda: 0.05 +T: 20 +Throughput: 1279.03 Bps +Average Network Delay: 8.88095e-07 s/B +Average Network Delay: 0.000946561 s/packet +Average Network Delay (per instructions): 8.88073e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 40 +Throughput: 849.72 Bps +Average Network Delay: 1.14496e-06 s/B +Average Network Delay: 0.000810727 s/packet +Average Network Delay (per instructions): 1.14493e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 80 +Throughput: 812.92 Bps +Average Network Delay: 1.42929e-06 s/B +Average Network Delay: 0.000968227 s/packet +Average Network Delay (per instructions): 1.42926e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 160 +Throughput: 950.123 Bps +Average Network Delay: 1.69863e-06 s/B +Average Network Delay: 0.00134489 s/packet +Average Network Delay (per instructions): 1.69859e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 320 +Throughput: 1091.73 Bps +Average Network Delay: 3.01445e-06 s/B +Average Network Delay: 0.00274239 s/packet +Average Network Delay (per instructions): 3.01438e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.05 +T: 400 +Throughput: 419.51 Bps +Average Network Delay: 6.62425e-06 s/B +Average Network Delay: 0.00231573 s/packet +Average Network Delay (per instructions): 6.62409e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 12 +------------------------------------------------------ +lambda: 0.1 +T: 20 +Throughput: 2231.71 Bps +Average Network Delay: 9.29801e-07 s/B +Average Network Delay: 0.00086456 s/packet +Average Network Delay (per instructions): 9.29756e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 40 +Throughput: 1513.97 Bps +Average Network Delay: 1.19423e-06 s/B +Average Network Delay: 0.00075331 s/packet +Average Network Delay (per instructions): 1.19417e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 80 +Throughput: 1974.59 Bps +Average Network Delay: 1.40083e-06 s/B +Average Network Delay: 0.00115248 s/packet +Average Network Delay (per instructions): 1.40076e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 160 +Throughput: 1723.88 Bps +Average Network Delay: 1.99556e-06 s/B +Average Network Delay: 0.00143331 s/packet +Average Network Delay (per instructions): 1.99546e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 320 +Throughput: 2161.6 Bps +Average Network Delay: 2.68931e-06 s/B +Average Network Delay: 0.00242206 s/packet +Average Network Delay (per instructions): 2.68918e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.1 +T: 400 +Throughput: 2001.2 Bps +Average Network Delay: 3.08128e-06 s/B +Average Network Delay: 0.00256914 s/packet +Average Network Delay (per instructions): 3.08113e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 24 +------------------------------------------------------ +lambda: 0.3 +T: 20 +Throughput: 5703.78 Bps +Average Network Delay: 9.20996e-07 s/B +Average Network Delay: 0.000772418 s/packet +Average Network Delay (per instructions): 9.20871e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 40 +Throughput: 6070.34 Bps +Average Network Delay: 1.06254e-06 s/B +Average Network Delay: 0.000921299 s/packet +Average Network Delay (per instructions): 1.06239e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.3 +T: 80 +Throughput: 4687.34 Bps +Average Network Delay: 1.40599e-06 s/B +Average Network Delay: 0.000969035 s/packet +Average Network Delay (per instructions): 1.4058e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 160 +Throughput: 3632.19 Bps +Average Network Delay: 2.43176e-06 s/B +Average Network Delay: 0.00129874 s/packet +Average Network Delay (per instructions): 2.43143e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 68 +------------------------------------------------------ +lambda: 0.3 +T: 320 +Throughput: 6025.24 Bps +Average Network Delay: 2.72344e-06 s/B +Average Network Delay: 0.00234387 s/packet +Average Network Delay (per instructions): 2.72306e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.3 +T: 400 +Throughput: 5730.1 Bps +Average Network Delay: 3.0147e-06 s/B +Average Network Delay: 0.00246744 s/packet +Average Network Delay (per instructions): 3.01428e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 70 +------------------------------------------------------ +lambda: 0.6 +T: 20 +Throughput: 11168.7 Bps +Average Network Delay: 9.5311e-07 s/B +Average Network Delay: 0.000831432 s/packet +Average Network Delay (per instructions): 9.52867e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 128 +------------------------------------------------------ +lambda: 0.6 +T: 40 +Throughput: 9911.4 Bps +Average Network Delay: 1.10231e-06 s/B +Average Network Delay: 0.000866879 s/packet +Average Network Delay (per instructions): 1.10203e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 80 +Throughput: 10761 Bps +Average Network Delay: 1.2735e-06 s/B +Average Network Delay: 0.00108736 s/packet +Average Network Delay (per instructions): 1.27318e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 160 +Throughput: 10981.2 Bps +Average Network Delay: 1.78939e-06 s/B +Average Network Delay: 0.0015591 s/packet +Average Network Delay (per instructions): 1.78894e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 320 +Throughput: 8163.86 Bps +Average Network Delay: 3.50556e-06 s/B +Average Network Delay: 0.00227077 s/packet +Average Network Delay (per instructions): 3.50468e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 126 +------------------------------------------------------ +lambda: 0.6 +T: 400 +Throughput: 10973.4 Bps +Average Network Delay: 3.42795e-06 s/B +Average Network Delay: 0.00280644 s/packet +Average Network Delay (per instructions): 3.42704e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 134 +------------------------------------------------------ +lambda: 0.8 +T: 20 +Throughput: 14293.4 Bps +Average Network Delay: 9.2127e-07 s/B +Average Network Delay: 0.000792997 s/packet +Average Network Delay (per instructions): 9.20965e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 40 +Throughput: 15190.9 Bps +Average Network Delay: 1.03502e-06 s/B +Average Network Delay: 0.000946853 s/packet +Average Network Delay (per instructions): 1.03468e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 80 +Throughput: 11400.2 Bps +Average Network Delay: 1.45895e-06 s/B +Average Network Delay: 0.00100161 s/packet +Average Network Delay (per instructions): 1.45846e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 160 +Throughput: 14805.4 Bps +Average Network Delay: 1.81492e-06 s/B +Average Network Delay: 0.00161818 s/packet +Average Network Delay (per instructions): 1.81432e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.8 +T: 320 +Throughput: 14111.3 Bps +Average Network Delay: 2.78043e-06 s/B +Average Network Delay: 0.00233467 s/packet +Average Network Delay (per instructions): 2.7795e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 168 +------------------------------------------------------ +lambda: 0.8 +T: 400 +Throughput: 13067.2 Bps +Average Network Delay: 3.4313e-06 s/B +Average Network Delay: 0.00270017 s/packet +Average Network Delay (per instructions): 3.43016e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 166 +------------------------------------------------------ +lambda: 0.9 +T: 20 +Throughput: 14621.9 Bps +Average Network Delay: 9.75482e-07 s/B +Average Network Delay: 0.000774898 s/packet +Average Network Delay (per instructions): 9.75125e-06 s^2/B +Packets Dropped: 0 +Packets Sent: 184 +------------------------------------------------------ +lambda: 0.9 +T: 40 +Throughput: 15429.4 Bps +Average Network Delay: 1.12303e-06 s/B +Average Network Delay: 0.000951725 s/packet +Average Network Delay (per instructions): 1.12262e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 80 +Throughput: 15956.5 Bps +Average Network Delay: 1.29028e-06 s/B +Average Network Delay: 0.00113082 s/packet +Average Network Delay (per instructions): 1.28981e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 160 +Throughput: 13024.3 Bps +Average Network Delay: 1.92281e-06 s/B +Average Network Delay: 0.00139079 s/packet +Average Network Delay (per instructions): 1.92211e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 180 +------------------------------------------------------ +lambda: 0.9 +T: 320 +Throughput: 14204.8 Bps +Average Network Delay: 3.03224e-06 s/B +Average Network Delay: 0.00236575 s/packet +Average Network Delay (per instructions): 3.03114e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ +lambda: 0.9 +T: 400 +Throughput: 15867.7 Bps +Average Network Delay: 3.1339e-06 s/B +Average Network Delay: 0.0027313 s/packet +Average Network Delay (per instructions): 3.13276e-05 s^2/B +Packets Dropped: 0 +Packets Sent: 182 +------------------------------------------------------ diff --git a/nf.txt b/nf.txt new file mode 100644 index 0000000..ff0911f --- /dev/null +++ b/nf.txt @@ -0,0 +1,344 @@ +lambda: 0.01 +T: 20 +N: 20 +Throughput: 324.403 Bps +Average Network Delay: 9.48658e-07 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.01 +T: 40 +N: 20 +Throughput: 124.401 Bps +Average Network Delay: 1.46901e-06 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.01 +T: 80 +N: 20 +Throughput: 655.205 Bps +Average Network Delay: 1.03593e-06 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.01 +T: 160 +N: 20 +Throughput: 180.601 Bps +Average Network Delay: 2.82251e-06 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.01 +T: 320 +N: 20 +Throughput: 562.204 Bps +Average Network Delay: 2.07532e-06 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.01 +T: 400 +N: 20 +Throughput: 476.204 Bps +Average Network Delay: 2.61811e-06 s/B +Packets Dropped: 0 +Packets Sent: 4 +------------------------------------------------------ +lambda: 0.05 +T: 20 +N: 20 +Throughput: 1928.3 Bps +Average Network Delay: 9.58277e-07 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.05 +T: 40 +N: 20 +Throughput: 2054.61 Bps +Average Network Delay: 1.0926e-06 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.05 +T: 80 +N: 20 +Throughput: 1296.57 Bps +Average Network Delay: 1.54396e-06 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.05 +T: 160 +N: 20 +Throughput: 3187.57 Bps +Average Network Delay: 1.40985e-06 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.05 +T: 320 +N: 20 +Throughput: 1706.69 Bps +Average Network Delay: 3.32108e-06 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.05 +T: 400 +N: 20 +Throughput: 1821.69 Bps +Average Network Delay: 3.29477e-06 s/B +Packets Dropped: 0 +Packets Sent: 26 +------------------------------------------------------ +lambda: 0.1 +T: 20 +N: 20 +Throughput: 2974.27 Bps +Average Network Delay: 1.00026e-06 s/B +Packets Dropped: 0 +Packets Sent: 46 +------------------------------------------------------ +lambda: 0.1 +T: 40 +N: 20 +Throughput: 4197.99 Bps +Average Network Delay: 1.02577e-06 s/B +Packets Dropped: 0 +Packets Sent: 46 +------------------------------------------------------ +lambda: 0.1 +T: 80 +N: 20 +Throughput: 5602.42 Bps +Average Network Delay: 1.25811e-06 s/B +Packets Dropped: 0 +Packets Sent: 46 +------------------------------------------------------ +lambda: 0.1 +T: 160 +N: 20 +Throughput: 3982.27 Bps +Average Network Delay: 1.83877e-06 s/B +Packets Dropped: 0 +Packets Sent: 46 +------------------------------------------------------ +lambda: 0.1 +T: 320 +N: 20 +Throughput: 2989.98 Bps +Average Network Delay: 3.31564e-06 s/B +Packets Dropped: 0 +Packets Sent: 46 +------------------------------------------------------ +lambda: 0.1 +T: 400 +N: 20 +Throughput: 4996.87 Bps +Average Network Delay: 2.47607e-06 s/B +Packets Dropped: 0 +Packets Sent: 48 +------------------------------------------------------ +lambda: 0.3 +T: 20 +N: 20 +Throughput: 11980.9 Bps +Average Network Delay: 9.52435e-07 s/B +Packets Dropped: 0 +Packets Sent: 132 +------------------------------------------------------ +lambda: 0.3 +T: 40 +N: 20 +Throughput: 10134.3 Bps +Average Network Delay: 1.10972e-06 s/B +Packets Dropped: 0 +Packets Sent: 130 +------------------------------------------------------ +lambda: 0.3 +T: 80 +N: 20 +Throughput: 11760.3 Bps +Average Network Delay: 1.31026e-06 s/B +Packets Dropped: 0 +Packets Sent: 132 +------------------------------------------------------ +lambda: 0.3 +T: 160 +N: 20 +Throughput: 14024.6 Bps +Average Network Delay: 1.69105e-06 s/B +Packets Dropped: 0 +Packets Sent: 132 +------------------------------------------------------ +lambda: 0.3 +T: 320 +N: 20 +Throughput: 9396.27 Bps +Average Network Delay: 3.05701e-06 s/B +Packets Dropped: 0 +Packets Sent: 132 +------------------------------------------------------ +lambda: 0.3 +T: 400 +N: 20 +Throughput: 9222.6 Bps +Average Network Delay: 3.59085e-06 s/B +Packets Dropped: 0 +Packets Sent: 130 +------------------------------------------------------ +lambda: 0.6 +T: 20 +N: 20 +Throughput: 25848.1 Bps +Average Network Delay: 9.40432e-07 s/B +Packets Dropped: 0 +Packets Sent: 262 +------------------------------------------------------ +lambda: 0.6 +T: 40 +N: 20 +Throughput: 19069.9 Bps +Average Network Delay: 1.11848e-06 s/B +Packets Dropped: 0 +Packets Sent: 258 +------------------------------------------------------ +lambda: 0.6 +T: 60 +N: 20 +Throughput: 21546.9 Bps +Average Network Delay: 1.22821e-06 s/B +Packets Dropped: 0 +Packets Sent: 258 +------------------------------------------------------ +lambda: 0.6 +T: 80 +N: 20 +Throughput: 19665.9 Bps +Average Network Delay: 1.39532e-06 s/B +Packets Dropped: 0 +Packets Sent: 260 +------------------------------------------------------ +lambda: 0.6 +T: 160 +N: 20 +Throughput: 20026.2 Bps +Average Network Delay: 1.87608e-06 s/B +Packets Dropped: 0 +Packets Sent: 258 +------------------------------------------------------ +lambda: 0.6 +T: 320 +N: 20 +Throughput: 20723.6 Bps +Average Network Delay: 2.9644e-06 s/B +Packets Dropped: 0 +Packets Sent: 260 +------------------------------------------------------ +lambda: 0.6 +T: 400 +N: 20 +Throughput: 22169.4 Bps +Average Network Delay: 3.19245e-06 s/B +Packets Dropped: 0 +Packets Sent: 260 +------------------------------------------------------ +lambda: 0.8 +T: 20 +N: 20 +Throughput: 28142.1 Bps +Average Network Delay: 1.00797e-06 s/B +Packets Dropped: 0 +Packets Sent: 338 +------------------------------------------------------ +lambda: 0.8 +T: 40 +N: 20 +Throughput: 28994.4 Bps +Average Network Delay: 1.12063e-06 s/B +Packets Dropped: 0 +Packets Sent: 340 +------------------------------------------------------ +lambda: 0.8 +T: 80 +N: 20 +Throughput: 30957.9 Bps +Average Network Delay: 1.32631e-06 s/B +Packets Dropped: 0 +Packets Sent: 340 +------------------------------------------------------ +lambda: 0.8 +T: 160 +N: 20 +Throughput: 26638.7 Bps +Average Network Delay: 1.88756e-06 s/B +Packets Dropped: 0 +Packets Sent: 336 +------------------------------------------------------ +lambda: 0.8 +T: 320 +N: 20 +Throughput: 27409.5 Bps +Average Network Delay: 2.96282e-06 s/B +Packets Dropped: 0 +Packets Sent: 344 +------------------------------------------------------ +lambda: 0.8 +T: 400 +N: 20 +Throughput: 27276.6 Bps +Average Network Delay: 3.37756e-06 s/B +Packets Dropped: 0 +Packets Sent: 336 +------------------------------------------------------ +lambda: 0.9 +T: 20 +N: 20 +Throughput: 29464.3 Bps +Average Network Delay: 9.70659e-07 s/B +Packets Dropped: 0 +Packets Sent: 374 +------------------------------------------------------ +lambda: 0.9 +T: 40 +N: 20 +Throughput: 30951 Bps +Average Network Delay: 1.10313e-06 s/B +Packets Dropped: 0 +Packets Sent: 374 +------------------------------------------------------ +lambda: 0.9 +T: 80 +N: 20 +Throughput: 28762 Bps +Average Network Delay: 1.38112e-06 s/B +Packets Dropped: 0 +Packets Sent: 378 +------------------------------------------------------ +lambda: 0.9 +T: 160 +N: 20 +Throughput: 29654.2 Bps +Average Network Delay: 1.80931e-06 s/B +Packets Dropped: 0 +Packets Sent: 372 +------------------------------------------------------ +lambda: 0.9 +T: 320 +N: 20 +Throughput: 32499.1 Bps +Average Network Delay: 2.6638e-06 s/B +Packets Dropped: 0 +Packets Sent: 376 +------------------------------------------------------ +lambda: 0.9 +T: 400 +N: 20 +Throughput: 30616 Bps +Average Network Delay: 3.2058e-06 s/B +Packets Dropped: 0 +Packets Sent: 372 +------------------------------------------------------ diff --git a/simulator2.cpp b/simulator2.cpp new file mode 100644 index 0000000..56b3759 --- /dev/null +++ b/simulator2.cpp @@ -0,0 +1,288 @@ +#include +#include +#include +#include // max +#include +#include + + + +class Event { +protected: + double eventTime; + +public: + Event(double etime): eventTime(etime) {} + + double getEventTime() { + return eventTime; + } +}; + +class Arrival: public Event { + +}; + +class Departure: public Event { + +}; + +class Sync: public Event { + +}; + +class Timeout: public Event{ + +}; + + + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); // this may not be necessary, but oh well + } + + void insert(Event *event) { + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if ((*itr)->getEventTime() > event->getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + } // insert sorted by events time + + Event* removeFirst() { + + Event *firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + +int main(int argc, char const *argv[]) +{ +// read from command line, but given default values + double lambda = 0.1; // dexcribes shape of arrival distribution + double mu = 1; // describes shape of distribution of PktSize (r) + int N = 10; // number of hosts in network. + int T = 400; // maximum backoff value in number sync cycles. Should be larger than N I suppose. + double timeout = 0.005; // for project, will take values of 5, 10, or 15 msec. + +// these should be constant for our project, but I'll define them here + double maxRTM = 3; // maximum number of retransmissions + int maxPktSize = 1544; // maximum size of a packet in bytes + int ackPktSize = 64; // acknowledgement packet size in bytes + double channelCapacity = 11000000.0; // 11 Mbps (bits) + double SIFS = 0.00005; // 0.05 msec, delay before ack + double DIFS = 0.0001; // 0.1 msec, delay before send + double SYNC = 0.00001; // 0.01 msec + +// these are variables used throught the program + double time = 0; // time simulated since start of simulation in seconds + double transmitted = 0; // number of bytes successfully transmitted (will include ack bytes) + double delay = 0; // queue + transmission delay in seconds + + // check if help option set (or if only 1 argument, since that would be invalid). + // If so, print help information and end program + if ((argc > 1 && std::string("-help") == argv[1]) || argc == 2) + { + std::cout << "\nThis program simulates an IEEE 802.11-Based Wireless LAN. \n" + "To set parameters of network, use the following commands.\n" + "Default values are given in parenthesis.\n\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << timeout << "), given in msec\n" << std::endl; + + return 0; + } + + // read in command line inputs, assume all inputs come in a -var val pair + for (int i = 1; i + 1 < argc; i += 2) + { + if (std::string("-N") == argv[i]) + try{ + N = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -N, using default value " << N << std::endl; + } + else if (std::string("-l") == argv[i]) + try{ + lambda = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -l, using default value " << lambda << std::endl; + } + else if (std::string("-m") == argv[i]) + try{ + mu = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -m, using default value " << mu << std::endl; + } + else if (std::string("-T") == argv[i]) + try{ + T = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -T, using default value " << T << std::endl; + } + else if (std::string("-t") == argv[i]) + try{ + timeout = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -t, using default value " << timeout << std::endl; + } + else + { + std::cout << "invalid option \"" << argv[i] <<"\". To see valid options, run \"" << argv[0] << " -help\"" << std::endl; + } + } + + /*std::cout << "checking values:\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << timeout << "), given in msec\n" << std::endl;*/ + + + // create an array of Hosts + Host* *hosts = new Host*[N]; + + + + +/* + + + Event e = Event(time + pareto(lambda), true); + GEL eventList = GEL(); + eventList.insert(e); + + //cerr << "hello 1" << endl; + + // for 100000 events + // process event + // just going by the number given + + for (int i = 0; i < 100000; i++) + { + // get closest event and update time + e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getIsArrival()) + { + //cerr << "is Arrival, i: " << i << endl; + // insert new arrival event + eventList.insert(Event(time + pareto(lambda), true)); + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, false)); + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, false)); + } + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +}*/ + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*std::log(1-u)); +} + diff --git a/weird.txt b/weird.txt new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/weird.txt @@ -0,0 +1 @@ +hello diff --git a/wlan.cpp b/wlan.cpp new file mode 100644 index 0000000..2b5583e --- /dev/null +++ b/wlan.cpp @@ -0,0 +1,371 @@ +#include // random generators +#include +#include +#include +#include +#include +#include // max + +using namespace std; + + +double nedt(double rate); // randomly calculates negative-exponenetially-distributed-time +double generateRandomBackOff(double t); +double randomDestination(int source); +double dataLengthFrame(double rate); +double transmissionTime(double r); + +class Packet { + int source; + int destination; + int packet_length; + bool isAck; // true acknowledgement, false datapacket + +public: + Packet(int s, int dest, int packet_bytes, bool ack) { + source = s; + destination = dest; + packet_length = packet_bytes; + isAck = ack; + } +}; + +class Host { +public: + double backoff; + int hostId; + std::queue hostQueue; + + Host(); + Host(int id, double randomBackoffValue) { + backoff = randomBackoffValue; + hostQueue = std::queue(); + hostId = id; + } + + double getBackOff() { + return backoff; + } +}; + +enum eventtype { + arrival = 0, departure = 1, syncEvent = 2, timeout = 3 +}; + +class Event { + double eventTime; + bool isArrival; + eventtype eventType; + int eventHostId; + +public: + Event(double etime, eventtype event, int hostId) { + eventTime = etime; + eventType = event; + eventHostId = hostId; + } + + double getEventTime() { + return eventTime; + } + + int getHost() { + return eventHostId; + } + + // bool getIsArrival() { + // return arrival; + // } + + eventtype getEventType() { + return eventType; + } + + bool operator==(const Event &rhs) const { + return rhs.eventTime == eventTime; + } + + bool operator>=(const Event &rhs) const { + return rhs.eventTime >= eventTime; + } + + bool operator>(const Event &rhs) const { + return rhs.eventTime > eventTime; + } +}; + + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); + } + + void insert(Event event) { + + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if (itr->getEventTime() > event.getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + } // insert sorted by events time + + Event removeFirst() { + + Event firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + + +int main(int argc, char const *argv[]) +{ + // should be read in from command line + double lambda; + double mu; + double maxbuffer; + double sync; + double T; + double timeoutTime; + // double timeout; // 5 10 15 + + //std::cout << "lambda: "; + std::cin >> lambda; + //std::cout << "mu: "; + std::cin >> mu; + //std::cout << "Buffer Size: "; + std::cin >> maxbuffer; + std::cin >> sync; + std::cin >> T; + std::cin >> timeoutTime; + + // variables + int length = 0; + int dropNum = 0; + double sumLength = 0; + double time = 0; + double busy = 0; + double packet = 0; + + bool channelBusy = false; // false free, busy true + double r = 0; // data-length-frame + int N = 10; + int packetDestination = 0; + int packetTransmissionTime = 0; + int n = 0; // transmission count + + int acknowledgementTime = 0; + int sendingTime = 0; + int sifs = .05 * pow(10, 3); + int difs = .1 * pow(10, 3); + + + // initalization + GEL eventList = GEL(); + + // Host *hosts = new Host[N]; + std::vector hosts; + + for (int i = 0; i < N; ++i) + { + hosts.push_back( Host(i, generateRandomBackOff(T)) ); + } + + for(int i = 0; i < N; i++) + { + eventList.insert(Event(time + nedt(lambda), arrival, i)); + } + eventList.insert(Event(time + nedt(sync), syncEvent, -1)); // sync events do not have host, code -1 + + for (int i = 0; i < 100000; i++) + { + // get closest event and update time + Event e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getEventType() == arrival) + { + // generate new arrival event + eventList.insert(Event(time + nedt(lambda), arrival, e.getHost())); // arrival + + r = dataLengthFrame(mu); + + packetDestination = randomDestination(e.getHost()); + Packet p = Packet(e.getHost(), packetDestination, r, false); // data packet for arrivals + + // insert packet to queue + hosts[e.getHost()].hostQueue.push(p); + + // if server is free, schedule a departure event, and update length + if (length == 0 || hosts[0].hostQueue.size() == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, departure, e.getHost())); // departure + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else if (e.getEventType() == departure) + { + channelBusy = false; // free the channel + + packetDestination = randomDestination(e.getHost()); + Packet ap = Packet(e.getHost(), packetDestination, 64, true); // acknowledgement packet for depatures + + hosts[e.getHost()].hostQueue.push(ap); + + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, departure, e.getHost())); // departure + } + } + + else if (e.getEventType() == syncEvent) + { + // decreament counter for free channel + if (channelBusy == false) { + + hosts[e.getHost()].backoff--; + + if (hosts[e.getHost()].getBackOff() == 0) { // create departure event + eventList.insert(Event(time + packet, departure, e.getHost())); // departure event + channelBusy = true; + + eventList.insert(Event(time + packet, timeout, e.getHost())); // timeout event while transmiting + hosts[e.getHost()].backoff = generateRandomBackOff(T); // generate new random backoff value + } + } + + eventList.insert(Event(time + packet, syncEvent, e.getHost())); // next synchrinization event + sync += (.01 * pow(10, 3)); // msec to sec + } + + else if (e.getEventType() == timeout) + { + eventList.insert(Event(time + timeout, departure, e.getHost())); // initial departure + + + acknowledgementTime = e.getEventTime() + transmissionTime(64) + sifs; + // sendingTime = time + transmissionTime(r) + difs; + + // failed transmission : resend the packet, increase transmission count n + n++; + hosts[e.getHost()].backoff = generateRandomBackOff(T * n); + } + + else { + cerr << "Error : event type is not known!"; + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +} + +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*log(1-u)); +} + +double generateRandomBackOff(double t) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + std::random_device rd; //Will be used to obtain a seed for the random number engine + std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() + std::uniform_real_distribution<> dis(0, 1); + return int(t * dis(gen)); +} + +double randomDestination(int source) +{ + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, 9); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + rd = randomDestination(source); + } + return rd; +} + +double dataLengthFrame(double rate) +{ + // http://en.cppreference.com/w/cpp/numeric/random/exponential_distribution + std::random_device rd; + std::mt19937 gen(rd()); + + std::exponential_distribution<> d(1); // generate nedt between 0 and 1 + + return int(1544 * d(gen)); +} + +double transmissionTime(double r) +{ + return (r * 8) / (11 * pow(10,6)); +} \ No newline at end of file diff --git a/wlan2.cpp b/wlan2.cpp new file mode 100644 index 0000000..71beb52 --- /dev/null +++ b/wlan2.cpp @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include // max + +using namespace std; + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate); + + +enum eventtype { + arrival = 0, departure = 1, syncEvent = 2, timeout = 3 +}; + +class Event { + double eventTime; + bool isArrival; // type 0 + // enum { + // arrival = 0, departure = 1, syncEvent = 2, timeout = 3 + // } eventtype; + eventtype eventType; + +public: + Event(double etime, eventtype event) { + eventTime = etime; + + eventType = event; + } + + double getEventTime() { + return eventTime; + } + + bool getIsArrival() { + return isArrival; + } + + bool operator==(const Event &rhs) const { + return rhs.eventTime == eventTime; + } + + bool operator>=(const Event &rhs) const { + return rhs.eventTime >= eventTime; + } + + bool operator>(const Event &rhs) const { + return rhs.eventTime > eventTime; + } +}; + + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); + } + void insert(Event event) { + //cerr << "begin insert" << endl; + + //cerr << "insert event.isArrival: " << event.getIsArrival() << endl; + //cerr << "size = " << GlobalEventList.size() << endl; + + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if (itr->getEventTime() > event.getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + //cerr << "end insert " << endl; + + } // insert sorted by events time + + Event removeFirst() { + + //cerr << "begin removeFirst" << endl; + Event firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + //cerr << "end removeFirst" << endl; + + return firstElement; + } +}; + +int main(int argc, char const *argv[]) +{ + // should be read in from command line + double lambda; + double mu; + double maxbuffer; + double sync; + + //std::cout << "lambda: "; + std::cin >> lambda; + + //std::cout << "mu: "; + std::cin >> mu; + + //std::cout << "Buffer Size: "; + std::cin >> maxbuffer; + + std::cin >> sync; + + // variables + int length = 0; + int dropNum = 0; + double sumLength = 0; + double time = 0; + double busy = 0; + double packet = 0; + double r = 0; // data-length-frame + + // initalization + GEL eventList = GEL(); + for(int i = 0; i < 10; i++) + { + eventList.insert(Event(time + nedt(lambda), arrival)); + } + // synchrinzation enum 2 + eventList.insert(Event(time + nedt(sync), syncEvent)); + + + for (int i = 0; i < 100000; i++) + { + // get closest event and update time + Event e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getIsArrival()) + { + //cerr << "is Arrival, i: " << i << endl; + // insert new arrival event + eventList.insert(Event(time + nedt(lambda), arrival)); // arrival + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, departure)); // departure + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, departure)); // departure + } + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + + + return 0; +} + +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*log(1-u)); +} \ No newline at end of file diff --git a/wlan3.cpp b/wlan3.cpp new file mode 100644 index 0000000..c9a05fe --- /dev/null +++ b/wlan3.cpp @@ -0,0 +1,326 @@ +#include // random host +#include +#include +#include +#include +#include +#include // max + +using namespace std; + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate); +double generateRandomBackOff(double t); +double randomDestination(int source); +double dataLengthFrame(double rate); +double transmissionTime(double r); + +class Packet { + int source; + int destination; + int packet_length; + bool isAck; // true acknowledgement, false datapacket + +public: + Packet(int s, int dest, int packet_bytes, bool ack) { + source = s; + destination = dest; + packet_length = packet_bytes; + isAck = ack; + } +}; + +class Host { + double backoff; + int hostId; + std::queue hostsQueue; + +public: + Host(); + Host(int id, double randomBackoffValue) { + backoff = randomBackoffValue; + hostsQueue = std::queue(); + hostId = id; + } + + double getBackOff() { + return backoff; + } +}; + +enum eventtype { + arrival = 0, departure = 1, syncEvent = 2, timeout = 3 +}; + +class Event { + double eventTime; + bool isArrival; + eventtype eventType; + +public: + Event(double etime, eventtype event) { + eventTime = etime; + eventType = event; + } + + double getEventTime() { + return eventTime; + } + + // bool getIsArrival() { + // return arrival; + // } + + eventtype getEventType() { + return eventType; + } + + bool operator==(const Event &rhs) const { + return rhs.eventTime == eventTime; + } + + bool operator>=(const Event &rhs) const { + return rhs.eventTime >= eventTime; + } + + bool operator>(const Event &rhs) const { + return rhs.eventTime > eventTime; + } +}; + + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); + } + + void insert(Event event) { + + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if (itr->getEventTime() > event.getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + } // insert sorted by events time + + Event removeFirst() { + + //cerr << "begin removeFirst" << endl; + Event firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + //cerr << "end removeFirst" << endl; + + return firstElement; + } +}; + + +int main(int argc, char const *argv[]) +{ + // should be read in from command line + double lambda; + double mu; + double maxbuffer; + double sync; + double T; + + //std::cout << "lambda: "; + std::cin >> lambda; + //std::cout << "mu: "; + std::cin >> mu; + //std::cout << "Buffer Size: "; + std::cin >> maxbuffer; + std::cin >> sync; + std::cin >> T; + + // variables + int length = 0; + int dropNum = 0; + double sumLength = 0; + double time = 0; + double busy = 0; + double packet = 0; + + double r = 0; // data-length-frame + int N = 10; + int packetDestination = 0; + int packetTransmissionTime = 0; + // initalization + GEL eventList = GEL(); + //Host *hosts = new Host[10]; + + Host h = Host(0, 3); // id index of hosts array + cout << h.getBackOff(); + + std::queue hostsQueue = std::queue(); + + // how to determine destination of packet? choose another random host + // 0 index in hosts array + packetDestination = randomDestination(1); + r = dataLengthFrame(mu); + Packet p = Packet(0, packetDestination, r, false); + hostsQueue.push(p); + packetTransmissionTime = transmissionTime(r); + + for(int i = 0; i < N; i++) + { + eventList.insert(Event(time + nedt(lambda), arrival)); + } + eventList.insert(Event(time + nedt(sync), syncEvent)); + + + for (int i = 0; i < 100000; i++) + { + // get closest event and update time + Event e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getEventType() == arrival) + { + // generate new arrival event + eventList.insert(Event(time + nedt(lambda), arrival)); // arrival + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, departure)); // departure + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else if (e.getEventType() == departure) + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, departure)); // departure + } + } + + else if (e.getEventType() == syncEvent) + { + eventList.insert(Event(time + packet, syncEvent)); + } + + else if (e.getEventType() == timeout) + { + + } + + else { + cerr << "Error : event type is not known!"; + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +} + +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*log(1-u)); +} + +double generateRandomBackOff(double t) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + std::random_device rd; //Will be used to obtain a seed for the random number engine + std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() + std::uniform_real_distribution<> dis(0, 1); + return int(t * dis(gen)); +} + +double randomDestination(int source) +{ + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, 9); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + randomDestination(source); // should be rd = no? + } + return rd; +} + +double dataLengthFrame(double rate) +{ + // how? multiple by 1544 and round integer after calling nedt? + // what is this time? for 1544 byte packet, (1544 × 8) / (11 × 106) = 1.12 msec + + return int(1544 * nedt(rate)); // prob wrong [0, 1544] +} + +double transmissionTime(double r) +{ + return (r * 8) / (11 * pow(10,6)); +} \ No newline at end of file diff --git a/wlanAllen.cpp b/wlanAllen.cpp new file mode 100644 index 0000000..85e3467 --- /dev/null +++ b/wlanAllen.cpp @@ -0,0 +1,383 @@ +#include +#include +#include +#include +#include // max +#include +#include + + + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*std::log(1-u)); +} + + +enum eventtype { + arrival, departure, syncEvent, timeout +}; + +class Event { +protected: + double eventTime; + eventtype type; + int source; + int dest; + +public: + Event(double etime, eventtype type): eventTime(etime), type(type) {} + + double getEventTime() { + return eventTime; + } + + eventtype getType() + { + return type; + } +}; + + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); // this line may not be necessary, but oh well + } + + void insert(Event *event) { + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if ((*itr)->getEventTime() > event->getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + } // insert sorted by events time + + Event* removeFirst() { + + Event *firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + +// not sure i need all this stuff yet +class Packet { + int source; + int destination; + int packet_length; + bool isAck; // true acknowledgement, false datapacket + +public: + Packet(int s, int dest, int packet_bytes, bool ack) { + source = s; + destination = dest; + packet_length = packet_bytes; + isAck = ack; + } +}; + +class Host { + int backoff; // doing it in syc tics versus real time because easier for conflict avoidance + int hostId; // position in hosts array, maybe don't need this, but might if put create packets and stuff + int tmNum; // transmission number, max tmNum = 1 + maxRTM. Max backoff = tmNum * T + std::queue hostsQueue; + +public: + Host(){}; + Host(int id, double randomBackoffValue) { + backoff = randomBackoffValue; + hostsQueue = std::queue(); + hostId = id; + tmNum = 1; + } + + double getBackOff() { + return backoff; + } +}; + + + +int main(int argc, char const *argv[]) +{ + +// read from command line, but given default values + double lambda = 0.1; // dexcribes shape of arrival distribution + double mu = 1; // describes shape of distribution of PktSize (r) + int N = 10; // number of hosts in network. + int T = 400; // maximum backoff value in number sync cycles. Should be larger than N I suppose. + double timeout = 0.005; // for project, will take values of 5, 10, or 15 msec. + int eventsSimulated = 100000; // the bound of for loop + +// these should be constant for our project, but I'll define them here + double maxRTM = 3; // maximum number of retransmissions + int maxPktSize = 1544; // maximum size of a packet in bytes + int ackPktSize = 64; // acknowledgement packet size in bytes + double channelCapacity = 11000000.0; // 11 Mbps (bits) + double SIFS = 0.00005; // 0.05 msec, delay before ack + double DIFS = 0.0001; // 0.1 msec, delay before send + double SYNC = 0.00001; // 0.01 msec + +// these are variables used throught the program + double time = 0; // time simulated since start of simulation in seconds + double transmitted = 0; // number of bytes successfully transmitted (will include ack bytes) + double delay = 0; // queue + transmission delay in seconds + bool channelBusy = false; // true if channel is busy, false otherwise + +// containers + Host* *hosts; // an array of host pointers + GEL* eventList; // holds list of events + + // check if help option set (or if only 1 argument, since that would be invalid). + // If so, print help information and end program + if ((argc > 1 && std::string("-help") == argv[1]) || argc == 2) + { + std::cout << "\nThis program simulates an IEEE 802.11-Based Wireless LAN. \n" + "To set parameters of network, use the following commands.\n" + "Default values are given in parenthesis.\n\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << timeout << "), given in msec\n" + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n"<< std::endl; + + return 0; + } + + // read in command line inputs, assume all inputs come in a -var val pair + for (int i = 1; i + 1 < argc; i += 2) + { + // i probably should have made this a function, but i already did the copy paste so really no use now + if (std::string("-N") == argv[i]) + try{ + N = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -N, using default value " << N << std::endl; + } + else if (std::string("-l") == argv[i]) + try{ + lambda = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -l, using default value " << lambda << std::endl; + } + else if (std::string("-m") == argv[i]) + try{ + mu = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -m, using default value " << mu << std::endl; + } + else if (std::string("-T") == argv[i]) + try{ + T = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -T, using default value " << T << std::endl; + } + else if (std::string("-t") == argv[i]) + try{ + timeout = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -t, using default value " << timeout << std::endl; + } + else if (std::string("-s") == argv[i]) + try{ + eventsSimulated = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -s, using default value " << eventsSimulated << std::endl; + } + else + { + std::cout << "invalid option \"" << argv[i] <<"\". To see valid options, run \"" << argv[0] << " -help\"" << std::endl; + } + } + + /*std::cout << "checking values:\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << timeout << "), given in msec\n" << std::endl; + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n" << std::endl;*/ + + + + + // Now the simulation can finally begin + + hosts = new Host*[N]; // create an array to hold all Hosts + eventList = new GEL(); // create a list of events + + + // initialize each host and create its initial arrival event + for (int i = 0; i < N; i++) + { + hosts[i] = new Host(); + eventList->insert(new Arrival(time + nedt(lambda), i)); + + } + + eventList->insert(new Sync(time + SYNC)); // create the first sync event + + + for(int i = 0; i < eventsSimulated; i++) + { + Event* e = eventList->removeFirst(); + + + } + + + + + // delete dynamically allocated data + for (int i = 0; i < N; i++) + { + delete hosts[i]; + } + delete hosts; + delete eventList; + + + +} + + + + +/* + + + Event e = Event(time + pareto(lambda), true); + GEL eventList = GEL(); + eventList.insert(e); + + //cerr << "hello 1" << endl; + + // for 100000 events + // process event + // just going by the number given + + for (int i = 0; i < eventsSimulated; i++) + { + // get closest event and update time + e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getIsArrival()) + { + //cerr << "is Arrival, i: " << i << endl; + // insert new arrival event + eventList.insert(Event(time + pareto(lambda), true)); + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, false)); + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, false)); + } + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +}*/ + + + diff --git a/wlanAllen2.cpp b/wlanAllen2.cpp new file mode 100644 index 0000000..fe80d3c --- /dev/null +++ b/wlanAllen2.cpp @@ -0,0 +1,939 @@ +#include +#include +#include +#include +#include // max +#include +#include +#include // for hooman random stuff + + +// these should be constant for our project + const double maxRTM = 3; // maximum number of retransmissions + const int maxPktSize = 1544; // maximum size of a packet in bytes + const int ackPktSize = 64; // acknowledgement packet size in bytes + const double channelCapacity = 11000000.0; // 11 Mbps (bits) + const double SIFS = 0.00005; // 0.05 msec, delay before ack + const double DIFS = 0.0001; // 0.1 msec, delay before send + const double SYNC = 0.00001; // 0.01 msec + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*std::log(1-u)); +} + +double dataLengthFrame(double rate) +{ + // http://en.cppreference.com/w/cpp/numeric/random/exponential_distribution + std::random_device rd; + std::mt19937 gen(rd()); + + std::exponential_distribution<> d(1); // generate nedt between 0 and 1 + + return int(maxPktSize * d(gen)); +} + +double transmissionTime(int bytes) +{ + return (bytes * 8) / (channelCapacity); +} + +// generate a random backoff value less than or equal to T that is not currently in the backoff list +int generateRandomBackOff(int T, const int backoff[], int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(1, T); //(inclusive, inclusive) + + int rd = idist(rgen); + + // make sure the backoff value is not already given to another node + // this is for collision avoidance as the TA told us to do, even though + // it doesn't really happen in real life. + for (int i = 0; i < N; i++) + { + if (rd == backoff[i]) + { + return generateRandomBackOff(T, backoff, N); + } + } + return rd; +} + +int randomDestination(int source, int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, N - 1); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + rd = randomDestination(source, N); + } + return rd; +} + +enum eventtype { + arrival, departure, sync, timeout +}; + + +class Event { +protected: + double eventTime; + eventtype type; + + +public: + Event(eventtype type, double etime): eventTime(etime), type(type) {} + virtual ~Event(){} + + double getEventTime() { + return eventTime; + } + + eventtype getType() + { + return type; + } + +}; + +class Arrival: public Event { + static double lambda; + + int host; + +public: + Arrival(double stime, int h): Event(arrival, stime + nedt(lambda)), host(h) {} + + static void setLambda(double l) + { + lambda = l; + } + + int getHost() + { + return host; + } + +}; + +double Arrival::lambda = 0; + +class Departure: public Event { + + // shape of packet size distribution + static double mu; + + bool ack; // denotes if it is an acknowedgement packet + int source; // source host + int destination; // destination host + int packetID; // id of packet, see host class + int size; // paket size in bytes, used to determine throughput + +public: + Departure(double stime, int s, int d, int id, bool a): Event(departure, stime), ack(a), source(s), destination(d), packetID(id) + { + // if ack packet, set the time to be that size + // time already current time, so just need to add the new time. + if(ack) + { + // this shouldn't be how it works in real life + // we're supposed to scan the channel during sifs, + // then if clear set channel to busy and transmit. + // For this project TA say just add SIFS, which is easier so OK then + size = ackPktSize; + eventTime += (SIFS + transmissionTime(size)); + } + else + { + // same comment as above, except DFIS + size = dataLengthFrame(mu); + eventTime += (DIFS + transmissionTime(size)); + + } + + } + + static void setMu(double m) + { + mu = m; + } + + bool isAck() + { + return ack; + } + + int getSource() + { + return source; + } + int getDestination() + { + return destination; + } + int getPacketID() + { + return packetID; + } + int getSize() + { + return size; + } + + +}; + +double Departure::mu = 0; + +class Sync: public Event { + + static double SYNC; + +public: + Sync(double stime): Event(sync, stime + SYNC) {} + + static void setSYNC(double s) + { + SYNC = s; + } + +}; + +double Sync::SYNC = 0; + +class Timeout: public Event{ + + static double to_time; + + int host; + int timeoutID; +public: + Timeout(double stime, int h, int id): Event(timeout, stime + to_time), host(h), timeoutID(id) {} + + static void setTO(double t) + { + to_time = t; + } + + + int getHost() + { + return host; + } + + int getTimeoutID() + { + return timeoutID; + } + +}; + +double Timeout::to_time = 0; + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); // this line may not be necessary, but oh well + } + + void insert(Event *event) { + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if ((*itr)->getEventTime() > event->getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + } // insert sorted by events time + + Event* removeFirst() { + + Event *firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + +// not sure i need all this stuff yet +class Packet { + int destination; + bool isAck; // true acknowledgement, false datapacket + int ackID; // used to make sure ack makes sense and stuff + double queueTime; // time when packet first queued, used for statistics (Network delay) + + + friend class Host; + +public: + Packet(double t, int dest, bool ack, int id = 0): destination(dest), isAck(ack), ackID(id), queueTime(t){} + + +}; + +class Host { + static int NumHosts; // need to know this in order to create random destination + static int T; // maximum backoff given no retransmissions + // static array so we can implement collision avoidance + static int* backoff; // doing it in syc tics versus real time because easier for conflict avoidance + // backoff < 0 means nothing in queue (nothing to transmit) + // backoff > 0 means waiting to transmit + // backoff == 0 means either transmitting or waiting for ack + + int packetID; // the number of the packet sent. + // Not worring about overflow, and even it it does, it should still work correctly. + // Used to cordinate acks and timeouts. + // If a timeout occurs, there's a chance that there will be acks in the network + // that don't refer to the most recent transmission. + + int droppedPackets; // not necessary for our project, but i think it might be interesting to keep track of + int hostID; // position in hosts array, maybe don't need this, but might if put create packets and stuff + int tmNum; // transmission number, max tmNum = 1 + maxRTM. Max backoff = tmNum * T + + double retransmitTime; // used to calculate delay when there has been a retransmission + double delay; // total delay, used for statistics. + std::queue packetQueue; // i think its initialized implicitly + +public: + // initially set backoff to (-1) to show that nothing in queue + Host(int id): packetID(0), droppedPackets(0), hostID(id), tmNum(0), retransmitTime(0), delay(0){ + backoff[id] = -1; + } + + // initialize static variables + static void initHosts(int N, int t) + { + NumHosts = N; + backoff = new int[N]; + T = t; + } + + double getDelay() + { + return delay; + } + + int getDropedPackets() + { + return droppedPackets; + } + + void enqueueDataPacket(double stime) + { + packetQueue.push(Packet(stime, randomDestination(hostID, NumHosts), false)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet. + // in real life I don't think the first packet waits for a backoff, + // but the TAs told us to do it this way. + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + void enqueueAckPacket(double stime, int dest, int ackID) + { + + // In real life I don't think the ack goes in the back of the queue, + // But the TAs told us to do it this way. + + packetQueue.push(Packet(stime, dest, true, ackID)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + + } + + // decrements backoff value if it is larger than zero + // returns true if this act makes the value 0, and thus the Host is ready to transmit + bool decrementBackoff() + { + if (backoff[hostID] > 0) + { + --(backoff[hostID]); + if(backoff[hostID] == 0) + return true; + } + return false; + } + + + void receiveAck(int AckID) + { + // if correct ack, can pop packet from start of queue + if (AckID == packetID) + { + packetQueue.pop(); // pop packet from queue + packetID++; // new packet to send, so increment packetID + tmNum = 0; // need to reset TmNum because new packet to transmit. + // if no more packets in queue, indicate it by setting backoff id to -1 + if (packetQueue.empty()) + { + backoff[hostID] = -1; + } + // eles if still packet to send, set new backoff value + else + { + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + + + } + // if AckID does not match PacketID do nothing + // should never get out of order ack because can only sent 1 packet at a time + } + + void receiveTimeout(double stime, int TO_ID) + { + // if timeout refers to current packet, need to resend with larger backoff + if (TO_ID == packetID) + { + // if haven't reached maximum transmissions yet, need to retransmit it by resetting backoff value + // tmNum refers to current transmission. On transmission 3, there have been 2 retransmissions + // if MaxRTM = 3, then should be able to send another one. + // if MaxRTM = 3 and tmNum = 4, then there have already been 3 retransmissions and need to abort + if (tmNum <= maxRTM) + { + // need to reset packet queue time because should not double count delay when waiting for ack + // actually, i don't want to make it a queue of pointers so i'll do this hack instead + retransmitTime = stime; + + // need to increase mack backoff by a multiple of (tmNum + 1), + // since tmNum in incremented when departure event created, but need to use that as a multiplyer here + backoff[hostID] = generateRandomBackOff(T * (tmNum + 1), backoff, NumHosts); + } + // else need to drop packet. Do this by pretending to ack it + else + { + droppedPackets++; + receiveAck(packetID); + + } + + } + + } + + + // performs packet processing and prepares packet for departure + // returns a departure event + // not going to do error checking, so assumes that there is at least 1 packet in the queue and that hopeufully backoff == 0 + // actually, maybe will do error checking + Departure* createDeparture(double stime) + { + // i lied, error checking + if (backoff[hostID] != 0) + std::cerr << "Host creating Departure event when backoff != 0" << std::endl; + // the other one should cause runtime issues if bug, so won't check for it + // no that's stupid + if (packetQueue.empty()) + { + std::cerr << "Host creating Departure event when queue empty" << std::endl; + + return NULL; + } + + + + // get packet info + Packet p = packetQueue.front(); + + Departure* depart; // holds return value + + + //std::cerr << "creating departure with destination: " << p.destination << std::endl; + + // if an ack packet, create ack event + // since we don't need to wait for ack, can immediatley pretend we got one + if (p.isAck) + { + receiveAck(packetID); + depart = new Departure(stime, hostID, p.destination, p.ackID, true); + } + // else need to create packet and increment tmNum + else + { + tmNum ++; + depart = new Departure(stime, hostID, p.destination, hostID, false); + + } + + // calculate delay + // if this is a retransmission (tmNum > 1), then need to use retransmitTime as a base + if (tmNum > 1) + { + delay += (depart->getEventTime() - retransmitTime); + } + // else use packet time as a base + else + { + delay += (depart->getEventTime() - p.queueTime); + } + + return depart; + + } + + Timeout* createTimeout(double stime) + { + return new Timeout(stime, hostID, packetID); + } + +}; + +int* Host::backoff = NULL; +int Host::NumHosts = 0; +int Host::T = 0; + + + +int main(int argc, char const *argv[]) +{ + +// read from command line, but given default values + double lambda = 0.1; // dexcribes shape of arrival distribution + double mu = 1; // describes shape of distribution of PktSize (r) + int N = 10; // number of hosts in network. + int T = 400; // maximum backoff value in number sync cycles. Should be larger than N I suppose. + double TO = 0.005; // for project, will take values of 5, 10, or 15 msec. + int eventsSimulated = 100000; // the bound of for loop + +// these are variables used throught the program + double time = 0; // time simulated since start of simulation in seconds + double transmitted = 0; // number of bytes successfully transmitted (will include ack bytes) + double delay = 0; // queue + transmission delay in seconds + int packets = 0; + bool channelBusy = false; // true if channel is busy, false otherwise + +// containers + Host* *hosts; // an array of host pointers + GEL* eventList; // holds list of events + + // check if help option set (or if only 1 argument, since that would be invalid). + // If so, print help information and end program + if ((argc > 1 && std::string("-help") == argv[1]) || argc == 2) + { + std::cout << "\nThis program simulates an IEEE 802.11-Based Wireless LAN. \n" + "To set parameters of network, use the following commands.\n" + "Default values are given in parenthesis.\n\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n"<< std::endl; + + return 0; + } + + // read in command line inputs, assume all inputs come in a -var val pair + for (int i = 1; i + 1 < argc; i += 2) + { + // i probably should have made this a function, but i already did the copy paste so really no use now + if (std::string("-N") == argv[i]) + try{ + N = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -N, using default value " << N << std::endl; + } + else if (std::string("-l") == argv[i]) + try{ + lambda = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -l, using default value " << lambda << std::endl; + } + else if (std::string("-m") == argv[i]) + try{ + mu = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -m, using default value " << mu << std::endl; + } + else if (std::string("-T") == argv[i]) + try{ + T = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -T, using default value " << T << std::endl; + } + else if (std::string("-t") == argv[i]) + try{ + TO = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -t, using default value " << TO << std::endl; + } + else if (std::string("-s") == argv[i]) + try{ + eventsSimulated = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -s, using default value " << eventsSimulated << std::endl; + } + else + { + std::cout << "invalid option \"" << argv[i] <<"\". To see valid options, run \"" << argv[0] << " -help\"" << std::endl; + } + } + + /*std::cout << "checking values:\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" << std::endl; + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n" << std::endl;*/ + + + + + // Now the simulation can finally begin + + hosts = new Host*[N]; // create an array to hold all Hosts + eventList = new GEL(); // create a list of events + Event* e; // holds the event currently being manipulated + + // initialize static variables of events + Arrival::setLambda(lambda); + Departure::setMu(mu); + Sync::setSYNC(SYNC); + Host::initHosts(N, T); + Timeout::setTO(TO); + + + // initialize each host and create its initial arrival event + for (int i = 0; i < N; i++) + { + hosts[i] = new Host(i); + eventList->insert(new Arrival(time, i)); + + } + + eventList->insert(new Sync(time)); // create the first sync event + + + for(int i = 0; i < eventsSimulated; i++) + { + // pop event to handle + e = eventList->removeFirst(); + + // update time + time = e->getEventTime(); + + if (e->getType() == arrival) + { + // cast to arrival pointer + Arrival *a = static_cast(e); + + // check if cast actually worked + if (a) + { + // need to create a new arrival event for the previous arrival event's host + eventList->insert(new Arrival(time, a->getHost())); + + // following line testing behaviour of arrival event + //std::cout << "process arrival event for host: " << a->getHost() << " at time: " << a->getEventTime() << std::endl; + + // now need to put packet in queue of host. + // will generate length of packet on demand when create a departure event + // but need to indicate that it is not a ack packet + hosts[a->getHost()]->enqueueDataPacket(time); + + } + else // not actually an arrival pointer + { + std::cerr << "error: process event of arrival type that wasn't actually an arrival event" << std::endl; + } + } + + + else if (e->getType() == departure) + { + // cast to departure pointer + Departure *d = static_cast(e); + + // check if cast actually worked + if (d) + { + // keep track of bytes transmitted + transmitted += d->getSize(); + packets ++; + + + // if an ack departure, need to notify receiving host + if (d->isAck()) + { + // using an integer for packet IDs + hosts[d->getDestination()]->receiveAck(d->getPacketID()); + + } + // if a data departure, need to create ack packet in destination queue + else + { + hosts[d->getDestination()]->enqueueAckPacket(time, d->getSource(), d->getPacketID()); + } + // set channel to free + channelBusy = false; + + + } + else // not actually a departure pointer + { + std::cerr << "error: process event of departure type that wasn't actually a departure event" << std::endl; + } + + } + else if (e->getType() == sync) + { + // cast to Sync pointer + Sync *s = static_cast(e); + + // check if cast actually worked + if (s) + { + // need to create a new Sync event + eventList->insert(new Sync(time)); + + //std::cout << "process sync event at time: " << s->getEventTime() << std::endl; + + // if channel is free, go through all hosts and decrement backoff. + // if backoff reaches zero, set channel to busy and create departure event + // also continue to decrement the rest of the backoffs to help with collision avoidance + if (channelBusy == false) + { + // possible host that needs to transmit + int hostToProcess = -1; + for (int i = 0; i < N; i++) + { + // decrements backoff value, returns true if backoff becomes zero + // need to save host index if it needs to be processed + // since we provide collision detection, there should only ever be one host ready to process + if(hosts[i]->decrementBackoff()) + { + hostToProcess = i; + } + + // if a host was selected to process, need to process it + + } + if (hostToProcess >= 0) + { + // have the host create a departure event + Departure* departHelp = (hosts[hostToProcess]->createDeparture(time)); + if (departHelp) + { + eventList->insert(departHelp); + // create a timeout event tied to the host, but only if not ack + if (!departHelp->isAck()) + { + eventList->insert(hosts[hostToProcess]->createTimeout(time)); + + } + // set channel to busy + channelBusy = true; + } + } + } + + + } + else // not actually a sync pointer + { + std::cerr << "error: process event of sync type that wasn't actually a sync event" << std::endl; + } + + } + else if (e->getType() == timeout) + { + // cast to arrival pointer + Timeout *t = static_cast(e); + + // check if actually worked + if (t) + { + // tell host that timeout event occured + hosts[t->getHost()]->receiveTimeout(time, t->getTimeoutID()); + + } + else // not actually a timeout pointer + { + std::cerr << "error: process event of timeout type that wasn't actually a timeout event" << std::endl; + } + } + + // free memory of processed event + delete e; + + + } + + + + int drop = 0; + + for (int i = 0; i < N; i++) + { + delay += hosts[i]->getDelay(); + drop += hosts[i]->getDropedPackets(); + } + + + std::cout << "Throughput: " << transmitted / time << " Bps" << std::endl; + std::cout << "Average Network Delay: " << delay / transmitted << " s/B" << std::endl; // I changed this to make sense + std::cout << "Average Network Delay: " << delay / packets << " s/packet" << std::endl; // I changed this to make sense + std::cout << "Average Network Delay (per instructions): " << delay / (transmitted/time) << " s^2/B" << std::endl; // This is what doesn't make sense + + std::cout << "Packets Dropped: " << drop << std::endl; + + + + // delete dynamically allocated data + for (int i = 0; i < N; i++) + { + delete hosts[i]; + } + delete hosts; + delete eventList; + + + +} + + + + +/* + + + Event e = Event(time + pareto(lambda), true); + GEL eventList = GEL(); + eventList.insert(e); + + //cerr << "hello 1" << endl; + + // for 100000 events + // process event + // just going by the number given + + for (int i = 0; i < eventsSimulated; i++) + { + // get closest event and update time + e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getIsArrival()) + { + //cerr << "is Arrival, i: " << i << endl; + // insert new arrival event + eventList.insert(Event(time + pareto(lambda), true)); + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, false)); + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, false)); + } + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +}*/ + + + diff --git a/wlanAllen3.cpp b/wlanAllen3.cpp new file mode 100644 index 0000000..05911e9 --- /dev/null +++ b/wlanAllen3.cpp @@ -0,0 +1,942 @@ +#include +#include +#include +#include +#include // max +#include +#include +#include // for hooman random stuff + + +// these should be constant for our project + const double maxRTM = 3; // maximum number of retransmissions + const int maxPktSize = 1544; // maximum size of a packet in bytes + const int ackPktSize = 64; // acknowledgement packet size in bytes + const double channelCapacity = 11000000.0; // 11 Mbps (bits) + const double SIFS = 0.00005; // 0.05 msec, delay before ack + const double DIFS = 0.0001; // 0.1 msec, delay before send + const double SYNC = 0.00001; // 0.01 msec + + +// randomly calculates negative-exponenetially-distributed-time +double nedt(double rate) +{ + double u; + u = drand48(); + return ((-1/rate)*std::log(1-u)); +} + +double dataLengthFrame(double rate) +{ + // http://en.cppreference.com/w/cpp/numeric/random/exponential_distribution + std::random_device rd; + std::mt19937 gen(rd()); + + std::exponential_distribution<> d(1); // generate nedt between 0 and 1 + + return int(maxPktSize * d(gen)); +} + +double transmissionTime(int bytes) +{ + return (bytes * 8) / (channelCapacity); +} + +// generate a random backoff value less than or equal to T that is not currently in the backoff list +int generateRandomBackOff(int T, const int backoff[], int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(1, T); //(inclusive, inclusive) + + int rd = idist(rgen); + + // make sure the backoff value is not already given to another node + // this is for collision avoidance as the TA told us to do, even though + // it doesn't really happen in real life. + for (int i = 0; i < N; i++) + { + if (rd == backoff[i]) + { + return generateRandomBackOff(T, backoff, N); + } + } + return rd; +} + +int randomDestination(int source, int N) +{ + // cited http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + + std::random_device rdev; + std::mt19937 rgen(rdev()); + std::uniform_int_distribution idist(0, N - 1); //(inclusive, inclusive) + + int rd = idist(rgen); + // if random destination and source are same, recursively call the function!? + if (rd == source) { + rd = randomDestination(source, N); + } + return rd; +} + +enum eventtype { + arrival, departure, sync, timeout +}; + + +class Event { +protected: + double eventTime; + eventtype type; + + +public: + Event(eventtype type, double etime): eventTime(etime), type(type) {} + virtual ~Event(){} + + double getEventTime() { + return eventTime; + } + + eventtype getType() + { + return type; + } + +}; + +class Arrival: public Event { + static double lambda; + + int host; + +public: + Arrival(double stime, int h): Event(arrival, stime + nedt(lambda)), host(h) {} + + static void setLambda(double l) + { + lambda = l; + } + + int getHost() + { + return host; + } + +}; + +double Arrival::lambda = 0; + +class Departure: public Event { + + // shape of packet size distribution + static double mu; + + bool ack; // denotes if it is an acknowedgement packet + int source; // source host + int destination; // destination host + int packetID; // id of packet, see host class + int size; // paket size in bytes, used to determine throughput + +public: + Departure(double stime, int s, int d, int id, bool a): Event(departure, stime), ack(a), source(s), destination(d), packetID(id) + { + // if ack packet, set the time to be that size + // time already current time, so just need to add the new time. + if(ack) + { + // this shouldn't be how it works in real life + // we're supposed to scan the channel during sifs, + // then if clear set channel to busy and transmit. + // For this project TA say just add SIFS, which is easier so OK then + size = ackPktSize; + eventTime += (SIFS + transmissionTime(size)); + } + else + { + // same comment as above, except DFIS + size = dataLengthFrame(mu); + eventTime += (DIFS + transmissionTime(size)); + + } + + } + + static void setMu(double m) + { + mu = m; + } + + bool isAck() + { + return ack; + } + + int getSource() + { + return source; + } + int getDestination() + { + return destination; + } + int getPacketID() + { + return packetID; + } + int getSize() + { + return size; + } + + +}; + +double Departure::mu = 0; + +class Sync: public Event { + + static double SYNC; + +public: + Sync(double stime): Event(sync, stime + SYNC) {} + + static void setSYNC(double s) + { + SYNC = s; + } + +}; + +double Sync::SYNC = 0; + +class Timeout: public Event{ + + static double to_time; + + int host; + int timeoutID; +public: + Timeout(double stime, int h, int id): Event(timeout, stime + to_time), host(h), timeoutID(id) {} + + static void setTO(double t) + { + to_time = t; + } + + + int getHost() + { + return host; + } + + int getTimeoutID() + { + return timeoutID; + } + +}; + +double Timeout::to_time = 0; + +class GEL { // Global Event List + + std::list GlobalEventList; + +public: + GEL() { + GlobalEventList = std::list(); // this line may not be necessary, but oh well + } + + void insert(Event *event) { + if (GlobalEventList.size() == 0) { + GlobalEventList.push_front(event); + return; + } + + for (std::list::iterator itr = GlobalEventList.begin(); itr != GlobalEventList.end(); itr++) { + if ((*itr)->getEventTime() > event->getEventTime()) { + GlobalEventList.insert(itr, event); + return; + } + } + + GlobalEventList.push_back(event); + + + } // insert sorted by events time + + Event* removeFirst() { + + Event *firstElement = GlobalEventList.front(); + GlobalEventList.pop_front(); + + return firstElement; + } +}; + +// not sure i need all this stuff yet +class Packet { + int destination; + bool isAck; // true acknowledgement, false datapacket + int ackID; // used to make sure ack makes sense and stuff + double queueTime; // time when packet first queued, used for statistics (Network delay) + + + friend class Host; + +public: + Packet(double t, int dest, bool ack, int id = 0): destination(dest), isAck(ack), ackID(id), queueTime(t){} + + +}; + +class Host { + static int NumHosts; // need to know this in order to create random destination + static int T; // maximum backoff given no retransmissions + // static array so we can implement collision avoidance + static int* backoff; // doing it in syc tics versus real time because easier for conflict avoidance + // backoff < 0 means nothing in queue (nothing to transmit) + // backoff > 0 means waiting to transmit + // backoff == 0 means either transmitting or waiting for ack + + int packetID; // the number of the packet sent. + // Not worring about overflow, and even it it does, it should still work correctly. + // Used to cordinate acks and timeouts. + // If a timeout occurs, there's a chance that there will be acks in the network + // that don't refer to the most recent transmission. + + int droppedPackets; // not necessary for our project, but i think it might be interesting to keep track of + int hostID; // position in hosts array, maybe don't need this, but might if put create packets and stuff + int tmNum; // transmission number, max tmNum = 1 + maxRTM. Max backoff = tmNum * T + + double retransmitTime; // used to calculate delay when there has been a retransmission + double delay; // total delay, used for statistics. + std::queue packetQueue; // i think its initialized implicitly + +public: + // initially set backoff to (-1) to show that nothing in queue + Host(int id): packetID(0), droppedPackets(0), hostID(id), tmNum(0), retransmitTime(0), delay(0){ + backoff[id] = -1; + } + + // initialize static variables + static void initHosts(int N, int t) + { + NumHosts = N; + backoff = new int[N]; + T = t; + } + + double getDelay() + { + return delay; + } + + int getDropedPackets() + { + return droppedPackets; + } + + void enqueueDataPacket(double stime) + { + packetQueue.push(Packet(stime, randomDestination(hostID, NumHosts), false)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet. + // in real life I don't think the first packet waits for a backoff, + // but the TAs told us to do it this way. + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + void enqueueAckPacket(double stime, int dest, int ackID) + { + + // In real life I don't think the ack goes in the back of the queue, + // But the TAs told us to do it this way. + + packetQueue.push(Packet(stime, dest, true, ackID)); + // if nothing ready to transmit, as denoted by a negative backoff value + // then need to set a new backoff value for this packet + if (backoff[hostID] < 0) + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + + } + + // decrements backoff value if it is larger than zero + // returns true if this act makes the value 0, and thus the Host is ready to transmit + bool decrementBackoff() + { + if (backoff[hostID] > 0) + { + --(backoff[hostID]); + if(backoff[hostID] == 0) + return true; + } + return false; + } + + + void receiveAck(int AckID) + { + // if correct ack, can pop packet from start of queue + if (AckID == packetID) + { + //std::cerr << "receive correct ack, Host: " << hostID << ", AckID: " << AckID << std::endl; + packetQueue.pop(); // pop packet from queue + packetID++; // new packet to send, so increment packetID + tmNum = 0; // need to reset TmNum because new packet to transmit. + // if no more packets in queue, indicate it by setting backoff id to -1 + if (packetQueue.empty()) + { + backoff[hostID] = -1; + } + // eles if still packet to send, set new backoff value + else + { + backoff[hostID] = generateRandomBackOff(T, backoff, NumHosts); + } + + + } + // if AckID does not match PacketID do nothing + // should never get out of order ack because can only sent 1 packet at a time + } + + void receiveTimeout(double stime, int TO_ID) + { + // if timeout refers to current packet, need to resend with larger backoff + if (TO_ID == packetID) + { + // if haven't reached maximum transmissions yet, need to retransmit it by resetting backoff value + // tmNum refers to current transmission. On transmission 3, there have been 2 retransmissions + // if MaxRTM = 3, then should be able to send another one. + // if MaxRTM = 3 and tmNum = 4, then there have already been 3 retransmissions and need to abort + if (tmNum <= maxRTM) + { + // need to reset packet queue time because should not double count delay when waiting for ack + // actually, i don't want to make it a queue of pointers so i'll do this hack instead + retransmitTime = stime; + + // need to increase mack backoff by a multiple of (tmNum + 1), + // since tmNum in incremented when departure event created, but need to use that as a multiplyer here + backoff[hostID] = generateRandomBackOff(T * (tmNum + 1), backoff, NumHosts); + } + // else need to drop packet. Do this by pretending to ack it + else + { + droppedPackets++; + receiveAck(packetID); + + } + + } + + } + + + // performs packet processing and prepares packet for departure + // returns a departure event + // not going to do error checking, so assumes that there is at least 1 packet in the queue and that hopeufully backoff == 0 + // actually, maybe will do error checking + Departure* createDeparture(double stime) + { + // i lied, error checking + if (backoff[hostID] != 0) + std::cerr << "Host creating Departure event when backoff != 0" << std::endl; + // the other one should cause runtime issues if bug, so won't check for it + // no that's stupid + if (packetQueue.empty()) + { + std::cerr << "Host creating Departure event when queue empty" << std::endl; + + return NULL; + } + + + + // get packet info + Packet p = packetQueue.front(); + + Departure* depart; // holds return value + + + //std::cerr << "creating departure with destination: " << p.destination << std::endl; + + // if an ack packet, create ack event + // since we don't need to wait for ack, can immediatley pretend we got one + if (p.isAck) + { + receiveAck(packetID); + depart = new Departure(stime, hostID, p.destination, p.ackID, true); + } + // else need to create packet and increment tmNum + else + { + depart = new Departure(stime, hostID, p.destination, packetID, false); + tmNum ++; + + + } + + // calculate delay + // if this is a retransmission (tmNum > 1), then need to use retransmitTime as a base + if (tmNum > 1) + { + delay += (depart->getEventTime() - retransmitTime); + } + // else use packet time as a base + else + { + delay += (depart->getEventTime() - p.queueTime); + } + + return depart; + + } + + Timeout* createTimeout(double stime) + { + return new Timeout(stime, hostID, packetID); + } + +}; + +int* Host::backoff = NULL; +int Host::NumHosts = 0; +int Host::T = 0; + + + +int main(int argc, char const *argv[]) +{ + +// read from command line, but given default values + double lambda = 0.1; // dexcribes shape of arrival distribution + double mu = 1; // describes shape of distribution of PktSize (r) + int N = 10; // number of hosts in network. + int T = 400; // maximum backoff value in number sync cycles. Should be larger than N I suppose. + double TO = 0.005; // for project, will take values of 5, 10, or 15 msec. + int eventsSimulated = 100000; // the bound of for loop + +// these are variables used throught the program + double time = 0; // time simulated since start of simulation in seconds + double transmitted = 0; // number of bytes successfully transmitted (will include ack bytes) + double delay = 0; // queue + transmission delay in seconds + int packets = 0; + bool channelBusy = false; // true if channel is busy, false otherwise + +// containers + Host* *hosts; // an array of host pointers + GEL* eventList; // holds list of events + + // check if help option set (or if only 1 argument, since that would be invalid). + // If so, print help information and end program + if ((argc > 1 && std::string("-help") == argv[1]) || argc == 2) + { + std::cout << "\nThis program simulates an IEEE 802.11-Based Wireless LAN. \n" + "To set parameters of network, use the following commands.\n" + "Default values are given in parenthesis.\n\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n"<< std::endl; + + return 0; + } + + // read in command line inputs, assume all inputs come in a -var val pair + for (int i = 1; i + 1 < argc; i += 2) + { + // i probably should have made this a function, but i already did the copy paste so really no use now + if (std::string("-N") == argv[i]) + try{ + N = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -N, using default value " << N << std::endl; + } + else if (std::string("-l") == argv[i]) + try{ + lambda = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -l, using default value " << lambda << std::endl; + } + else if (std::string("-m") == argv[i]) + try{ + mu = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -m, using default value " << mu << std::endl; + } + else if (std::string("-T") == argv[i]) + try{ + T = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -T, using default value " << T << std::endl; + } + else if (std::string("-t") == argv[i]) + try{ + TO = std::stod(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -t, using default value " << TO << std::endl; + } + else if (std::string("-s") == argv[i]) + try{ + eventsSimulated = std::stoi(argv[i+1]); + + } + catch(std::exception e) + { + std::cerr << "invalid input for -s, using default value " << eventsSimulated << std::endl; + } + else + { + std::cout << "invalid option \"" << argv[i] <<"\". To see valid options, run \"" << argv[0] << " -help\"" << std::endl; + } + } + + /*std::cout << "checking values:\n" + "-l: lambda(" << lambda << "), shape of arrival distribution\n" + "-m: mu(" << mu << "), shape of packet size distribution\n" + "-N: N(" << N << "), number of hosts on LAN\n" + "-T: T(" << T << "), maximum backoff time in sync cycles\n" + "-t: timeout(" << TO << "), given in msec\n" << std::endl; + "-s: eventsSimulated(" << eventsSimulated << "), controls length of simulation\n" << std::endl;*/ + + + + + // Now the simulation can finally begin + + hosts = new Host*[N]; // create an array to hold all Hosts + eventList = new GEL(); // create a list of events + Event* e; // holds the event currently being manipulated + + // initialize static variables of events + Arrival::setLambda(lambda); + Departure::setMu(mu); + Sync::setSYNC(SYNC); + Host::initHosts(N, T); + Timeout::setTO(TO); + + + // initialize each host and create its initial arrival event + for (int i = 0; i < N; i++) + { + hosts[i] = new Host(i); + eventList->insert(new Arrival(time, i)); + + } + + eventList->insert(new Sync(time)); // create the first sync event + + + for(int i = 0; i < eventsSimulated; i++) + { + // pop event to handle + e = eventList->removeFirst(); + + // update time + time = e->getEventTime(); + + if (e->getType() == arrival) + { + // cast to arrival pointer + Arrival *a = static_cast(e); + + // check if cast actually worked + if (a) + { + // need to create a new arrival event for the previous arrival event's host + eventList->insert(new Arrival(time, a->getHost())); + + // following line testing behaviour of arrival event + //std::cout << "process arrival event for host: " << a->getHost() << " at time: " << a->getEventTime() << std::endl; + + // now need to put packet in queue of host. + // will generate length of packet on demand when create a departure event + // but need to indicate that it is not a ack packet + hosts[a->getHost()]->enqueueDataPacket(time); + + } + else // not actually an arrival pointer + { + std::cerr << "error: process event of arrival type that wasn't actually an arrival event" << std::endl; + } + } + + + else if (e->getType() == departure) + { + // cast to departure pointer + Departure *d = static_cast(e); + + // check if cast actually worked + if (d) + { + // keep track of bytes transmitted + transmitted += d->getSize(); + packets ++; + + + // if an ack departure, need to notify receiving host + if (d->isAck()) + { + // using an integer for packet IDs + hosts[d->getDestination()]->receiveAck(d->getPacketID()); + + } + // if a data departure, need to create ack packet in destination queue + else + { + hosts[d->getDestination()]->enqueueAckPacket(time, d->getSource(), d->getPacketID()); + } + // set channel to free + channelBusy = false; + + + } + else // not actually a departure pointer + { + std::cerr << "error: process event of departure type that wasn't actually a departure event" << std::endl; + } + + } + else if (e->getType() == sync) + { + // cast to Sync pointer + Sync *s = static_cast(e); + + // check if cast actually worked + if (s) + { + // need to create a new Sync event + eventList->insert(new Sync(time)); + + //std::cout << "process sync event at time: " << s->getEventTime() << std::endl; + + // if channel is free, go through all hosts and decrement backoff. + // if backoff reaches zero, set channel to busy and create departure event + // also continue to decrement the rest of the backoffs to help with collision avoidance + if (channelBusy == false) + { + // possible host that needs to transmit + int hostToProcess = -1; + for (int i = 0; i < N; i++) + { + // decrements backoff value, returns true if backoff becomes zero + // need to save host index if it needs to be processed + // since we provide collision detection, there should only ever be one host ready to process + if(hosts[i]->decrementBackoff()) + { + hostToProcess = i; + } + + // if a host was selected to process, need to process it + + } + if (hostToProcess >= 0) + { + // have the host create a departure event + Departure* departHelp = (hosts[hostToProcess]->createDeparture(time)); + if (departHelp) + { + eventList->insert(departHelp); + // create a timeout event tied to the host, but only if not ack + if (!departHelp->isAck()) + { + eventList->insert(hosts[hostToProcess]->createTimeout(time)); + + } + // set channel to busy + channelBusy = true; + } + } + } + + + } + else // not actually a sync pointer + { + std::cerr << "error: process event of sync type that wasn't actually a sync event" << std::endl; + } + + } + else if (e->getType() == timeout) + { + // cast to arrival pointer + Timeout *t = static_cast(e); + + // check if actually worked + if (t) + { + // tell host that timeout event occured + hosts[t->getHost()]->receiveTimeout(time, t->getTimeoutID()); + + } + else // not actually a timeout pointer + { + std::cerr << "error: process event of timeout type that wasn't actually a timeout event" << std::endl; + } + } + + // free memory of processed event + delete e; + + + } + + + + int drop = 0; + + for (int i = 0; i < N; i++) + { + delay += hosts[i]->getDelay(); + drop += hosts[i]->getDropedPackets(); + } + + + std::cout << "Throughput: " << transmitted / time << " Bps" << std::endl; + std::cout << "Average Network Delay: " << delay / transmitted << " s/B" << std::endl; // I changed this to make sense + std::cout << "Average Network Delay: " << delay / packets << " s/packet" << std::endl; // I changed this to make sense + std::cout << "Average Network Delay (per instructions): " << delay / (transmitted/time) << " s^2/B" << std::endl; // This is what doesn't make sense + + std::cout << "Packets Dropped: " << drop << std::endl; + std::cout << "Packets Sent: " << packets << std::endl; + + + + // delete dynamically allocated data + for (int i = 0; i < N; i++) + { + delete hosts[i]; + } + delete hosts; + delete eventList; + + + +} + + + + +/* + + + Event e = Event(time + pareto(lambda), true); + GEL eventList = GEL(); + eventList.insert(e); + + //cerr << "hello 1" << endl; + + // for 100000 events + // process event + // just going by the number given + + for (int i = 0; i < eventsSimulated; i++) + { + // get closest event and update time + e = eventList.removeFirst(); + + // sums length by multiplying length by elapsed time + // since length = 1 could still be considered empty queue + // may want to chech it should be length, not length - 1 + sumLength += max(0, length - 1) * (e.getEventTime() - time); + //cerr << "prev time: " << time << " event time: " << e.getEventTime() << endl; + + // updates time + time = e.getEventTime(); + + // handles Arrival event + if (e.getIsArrival()) + { + //cerr << "is Arrival, i: " << i << endl; + // insert new arrival event + eventList.insert(Event(time + pareto(lambda), true)); + + //cerr << "length: " << length << endl; + + // if server is free, schedule a departure event, and update length + if (length == 0) + { + //cerr << "hello from length = 0" << endl; + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + busy += packet; + eventList.insert(Event(time + packet, false)); + length ++; + // this assumes maxbuffer is at least one, + // which is a good assumption because no buffer + // would have max buffer equal to 1 + } + // else if room in buffer + // maxbuffer = -1 denotes infinite buffer + else if (maxbuffer == -1 || length - 1 < maxbuffer) + { + length ++; + // handles generating of service time when departure event created + } + else // no room in buffer + { + dropNum ++; + } + } + + // handles departure event + else + { + //cerr << "is departure" << endl; + length --; + + // if packet still in queue, create a departure event + if (length > 0) + { + packet = nedt(mu); + //cerr << "packet: " << packet << endl; + + busy += packet; + eventList.insert(Event(time + packet, false)); + } + } + + } + + std::cout << "lambda: "; + std::cout << lambda << endl; + + std::cout << "mu: "; + std::cout << mu << endl; + + std::cout << "Buffer Size: "; + std::cout << maxbuffer << endl; + + cout << "Utilization: " << busy / time << endl; + cout << "Mean queue length: " << sumLength / time << endl; + cout << "Number of packets dropped: " << dropNum << endl << endl << endl; + + + return 0; +}*/ + + +