├── .gitignore ├── LICENCE.txt ├── Makefile.am ├── README.md ├── configure.ac ├── coresim ├── debug.cpp ├── debug.h ├── event.cpp ├── event.h ├── flow.cpp ├── flow.h ├── main.cpp ├── node.cpp ├── node.h ├── packet.cpp ├── packet.h ├── queue.cpp ├── queue.h ├── random_variable.cpp ├── random_variable.h ├── topology.cpp └── topology.h ├── ext ├── capabilityflow.cpp ├── capabilityflow.h ├── capabilityhost.cpp ├── capabilityhost.h ├── custompriorityqueue.h ├── dctcpFlow.cpp ├── dctcpFlow.h ├── dctcpPacket.h ├── dctcpQueue.cpp ├── dctcpQueue.h ├── factory.cpp ├── factory.h ├── fastpassTopology.cpp ├── fastpassTopology.h ├── fastpassflow.cpp ├── fastpassflow.h ├── fastpasshost.cpp ├── fastpasshost.h ├── fountainflow.cpp ├── fountainflow.h ├── ideal.cpp ├── ideal.h ├── magicflow.cpp ├── magicflow.h ├── magichost.cpp ├── magichost.h ├── pfabricflow.cpp ├── pfabricflow.h ├── pfabricqueue.cpp ├── pfabricqueue.h ├── schedulinghost.cpp ├── schedulinghost.h ├── tcpflow.cpp └── tcpflow.h ├── py ├── CDF_aditya.txt ├── CDF_datamining.txt ├── CDF_dctcp.txt └── run_experiments.py ├── run ├── experiment.cpp ├── flow_generator.cpp ├── flow_generator.h ├── params.cpp ├── params.h ├── stats.cpp └── stats.h └── yaps-mascot.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | Makefile 3 | Makefile.in 4 | aclocal.m4 5 | autom4te.cache 6 | compile 7 | confdefs.h 8 | config.* 9 | configure 10 | depcomp 11 | missing 12 | install-sh 13 | *.deps* 14 | *.dirstamp* 15 | simulator 16 | simdebug 17 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, University of California Berkeley. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the organization nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | bin_PROGRAMS = simulator simdebug 4 | 5 | simulator_SOURCES = \ 6 | coresim/main.cpp \ 7 | coresim/debug.cpp \ 8 | coresim/node.cpp \ 9 | coresim/queue.cpp \ 10 | coresim/packet.cpp \ 11 | coresim/event.cpp \ 12 | coresim/topology.cpp \ 13 | coresim/flow.cpp \ 14 | coresim/random_variable.cpp \ 15 | ext/factory.cpp \ 16 | ext/pfabricqueue.cpp \ 17 | ext/pfabricflow.cpp \ 18 | ext/schedulinghost.cpp \ 19 | ext/fountainflow.cpp \ 20 | ext/magichost.cpp \ 21 | ext/magicflow.cpp \ 22 | ext/capabilityflow.cpp \ 23 | ext/capabilityhost.cpp \ 24 | ext/fastpassflow.cpp \ 25 | ext/fastpasshost.cpp \ 26 | ext/fastpassTopology.cpp \ 27 | ext/tcpflow.cpp \ 28 | ext/dctcpQueue.cpp \ 29 | ext/dctcpFlow.cpp \ 30 | ext/ideal.cpp \ 31 | run/params.cpp \ 32 | run/stats.cpp \ 33 | run/flow_generator.cpp \ 34 | run/experiment.cpp 35 | 36 | simulator_CXXFLAGS = -g -O3 -gdwarf-2 -Wall -std=c++0x 37 | 38 | simdebug_SOURCES = $(simulator_SOURCES) 39 | 40 | simdebug_CXXFLAGS = -g -O0 -gdwarf-2 -Wall -std=c++0x 41 | 42 | #CFLAGS = -g -O3 -gdwarf-2 -Wall -std=c++0x 43 | #CXXFLAGS = -g -O3 -gdwarf-2 -Wall -std=c++0x 44 | 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | YAPS = Yet Another Packet Simulator 2 | ================================== 3 | 4 | Core stuff is in `coresim/` 5 | --------------------------- 6 | Normally these files shouldn't change. This directory includes implementations of the following: 7 | * Main event loop and related helper functions, global variables, main() function to determine which experiment to run: `main.cpp` 8 | * Note: deciding which experiment to run will eventually be moved to the `run/` directory, probably to `experiment.cpp`. 9 | * Core event implementations (`Event`, `FlowArrivalEvent`, `FlowFinishedEvent`, etc): `event.cpp`. 10 | * Representation of the topology: `node.cpp`, `topology.cpp` 11 | * Queueing behavior. This is a basis for extension; the default implementation is FIFO-dropTail: `queue.cpp`. 12 | * Flows and packets. This is also a basis for extension; default is TCP: `packet.cpp` and `flow.cpp`. 13 | * Random variables used in flow generation. Used as a library by the flow generation code: `random_variable.cpp`. 14 | 15 | Extensions are in `ext/` 16 | ----------------------- 17 | This is where you implement your favorite protocol. 18 | * Generally extensions are created by subclassing one or more aspects of classes defined in `coresim/`. 19 | * Once an extension is defined, it should be added to `factory.cpp` so it can be run. 20 | * Currently, `factory.cpp` supports changing the flow, queue, and host-scheduling implementations. 21 | * Methods in `coresim/` call the `get_...` methods in `factory.cpp` to initialize the simulation with the correct implementation. 22 | * Which implementation to use from `factory.cpp` is determined by the config file, parsed by `run/params.cpp`. 23 | * You should give your extension an identifier in `factory.h` so it can be uniquely identified in the config file. 24 | 25 | Stuff related to actually running the simulator is in `run/` 26 | ------------------------------------------------------------ 27 | * Experiment setup, running, and post-analysis: `experiment.cpp` 28 | * Flow generation models: `flow_generator.cpp` 29 | * Parsing of config file: `params.cpp` 30 | * Configuration parameters for your extension should be added to `params.h` and `params.cpp`. 31 | * These can then be accessed with `params.` 32 | 33 | Helper scripts to run experiments are in `py/` 34 | --------------------------------------------- 35 | This can be useful if: 36 | * You are running many experiments in parallel. 37 | * You want to easily generate configuration files. 38 | 39 | To compile, the Automake and Autoconf files are included: `configure.ac` and `Makefile.am`. The makefile will produce two targets: `simulator` and `simdebug`. 40 | `simdebug` is equivalent to `simulator`, except compiler optimzations are turned off to make debugging easier. 41 | 42 | Authors 43 | ------- 44 | 45 | * Gautam Kumar 46 | * Akshay Narayan 47 | * Peter Gao 48 | 49 | ![Our Project Mascot](yaps-mascot.png) 50 | 51 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_INIT([simulator], [1.1], [akshay.narayan@berkeley.edu]) 5 | AC_PREREQ([2.69]) 6 | AC_CONFIG_SRCDIR([coresim/main.cpp]) 7 | 8 | AM_INIT_AUTOMAKE([subdir-objects]) 9 | AC_CONFIG_FILES([Makefile]) 10 | 11 | # Checks for programs. 12 | AC_PROG_CXX 13 | AC_PROG_CC 14 | 15 | # Checks for libraries. 16 | 17 | # Checks for header files. 18 | AC_CHECK_HEADERS([stdint.h stdlib.h]) 19 | 20 | # Checks for typedefs, structures, and compiler characteristics. 21 | AC_CHECK_HEADER_STDBOOL 22 | AC_TYPE_UINT32_T 23 | AC_TYPE_UINT64_T 24 | 25 | # Checks for library functions. 26 | AC_CHECK_FUNCS([pow sqrt]) 27 | 28 | 29 | AC_OUTPUT 30 | 31 | -------------------------------------------------------------------------------- /coresim/debug.cpp: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | #include 3 | 4 | extern double get_current_time(); 5 | 6 | bool debug_mode = true; 7 | bool print_flow = true; 8 | double debug_start_time = 0; 9 | 10 | bool debug_all_flows = false; 11 | std::set flows_to_debug_set = {}; 12 | bool debug_all_queues = false; 13 | std::set queues_to_debug_set = {}; 14 | bool debug_all_hosts = false; 15 | std::set hosts_to_debug_set = {}; 16 | 17 | bool debug_flow(uint32_t fid){ 18 | return false; 19 | //return debug_mode && get_current_time() >= debug_start_time?(debug_all_flows||flows_to_debug_set.count(fid)):false; 20 | } 21 | 22 | 23 | bool debug_queue(uint32_t qid){ 24 | return debug_mode && get_current_time() >= debug_start_time?(debug_all_queues||queues_to_debug_set.count(qid)):false; 25 | } 26 | 27 | bool debug_host(uint32_t qid){ 28 | return debug_mode && get_current_time() >= debug_start_time?(debug_all_hosts||hosts_to_debug_set.count(qid)):false; 29 | } 30 | 31 | bool debug(){ 32 | return debug_mode && get_current_time() >= debug_start_time; 33 | } 34 | 35 | bool print_flow_result(){ 36 | return print_flow; 37 | } 38 | -------------------------------------------------------------------------------- /coresim/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include 5 | 6 | bool debug_flow(uint32_t fid); 7 | bool debug_queue(uint32_t fid); 8 | bool debug_host(uint32_t fid); 9 | bool debug(); 10 | bool print_flow_result(); 11 | #endif 12 | -------------------------------------------------------------------------------- /coresim/event.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // event.cpp 3 | // TurboCpp 4 | // 5 | // Created by Gautam Kumar on 3/9/14. 6 | // 7 | // 8 | 9 | #include 10 | 11 | #include "event.h" 12 | #include "packet.h" 13 | #include "topology.h" 14 | #include "debug.h" 15 | 16 | #include "../ext/factory.h" 17 | 18 | #include "../run/params.h" 19 | 20 | extern Topology* topology; 21 | extern std::priority_queue, EventComparator> event_queue; 22 | extern double current_time; 23 | extern DCExpParams params; 24 | extern std::deque flow_arrivals; 25 | extern std::deque flows_to_schedule; 26 | 27 | extern uint32_t num_outstanding_packets; 28 | extern uint32_t max_outstanding_packets; 29 | 30 | extern uint32_t num_outstanding_packets_at_50; 31 | extern uint32_t num_outstanding_packets_at_100; 32 | extern uint32_t arrival_packets_at_50; 33 | extern uint32_t arrival_packets_at_100; 34 | extern uint32_t arrival_packets_count; 35 | extern uint32_t total_finished_flows; 36 | 37 | extern uint32_t backlog3; 38 | extern uint32_t backlog4; 39 | extern uint32_t duplicated_packets_received; 40 | extern uint32_t duplicated_packets; 41 | extern uint32_t injected_packets; 42 | extern uint32_t completed_packets; 43 | extern uint32_t total_completed_packets; 44 | extern uint32_t dead_packets; 45 | extern uint32_t sent_packets; 46 | 47 | extern EmpiricalRandomVariable *nv_bytes; 48 | 49 | extern double get_current_time(); 50 | extern void add_to_event_queue(Event *); 51 | extern int get_event_queue_size(); 52 | 53 | uint32_t Event::instance_count = 0; 54 | 55 | Event::Event(uint32_t type, double time) { 56 | this->type = type; 57 | this->time = time; 58 | this->cancelled = false; 59 | this->unique_id = Event::instance_count++; 60 | } 61 | 62 | Event::~Event() { 63 | } 64 | 65 | 66 | /* Flow Arrival */ 67 | FlowCreationForInitializationEvent::FlowCreationForInitializationEvent( 68 | double time, 69 | Host *src, 70 | Host *dst, 71 | EmpiricalRandomVariable *nv_bytes, 72 | RandomVariable *nv_intarr 73 | ) : Event(FLOW_CREATION_EVENT, time) { 74 | this->src = src; 75 | this->dst = dst; 76 | this->nv_bytes = nv_bytes; 77 | this->nv_intarr = nv_intarr; 78 | } 79 | 80 | FlowCreationForInitializationEvent::~FlowCreationForInitializationEvent() {} 81 | 82 | void FlowCreationForInitializationEvent::process_event() { 83 | uint32_t nvVal, size; 84 | uint32_t id = flows_to_schedule.size(); 85 | if (params.bytes_mode) { 86 | nvVal = nv_bytes->value(); 87 | size = (uint32_t) nvVal; 88 | } else { 89 | nvVal = (nv_bytes->value() + 0.5); // truncate(val + 0.5) equivalent to round to nearest int 90 | if (nvVal > 2500000) { 91 | std::cout << "Giant Flow! event.cpp::FlowCreation:" << 1000000.0 * time << " Generating new flow " << id << " of size " << (nvVal*1460) << " between " << src->id << " " << dst->id << "\n"; 92 | nvVal = 2500000; 93 | } 94 | size = (uint32_t) nvVal * 1460; 95 | } 96 | 97 | if (size != 0) { 98 | flows_to_schedule.push_back(Factory::get_flow(id, time, size, src, dst, params.flow_type)); 99 | } 100 | 101 | double tnext = time + nv_intarr->value(); 102 | // std::cout << "event.cpp::FlowCreation:" << 1000000.0 * time << " Generating new flow " << id << " of size " 103 | // << size << " between " << src->id << " " << dst->id << " " << (tnext - get_current_time())*1e6 << "\n"; 104 | 105 | add_to_event_queue( 106 | new FlowCreationForInitializationEvent( 107 | tnext, 108 | src, 109 | dst, 110 | nv_bytes, 111 | nv_intarr 112 | ) 113 | ); 114 | } 115 | 116 | 117 | /* Flow Arrival */ 118 | int flow_arrival_count = 0; 119 | 120 | FlowArrivalEvent::FlowArrivalEvent(double time, Flow* flow) : Event(FLOW_ARRIVAL, time) { 121 | this->flow = flow; 122 | } 123 | 124 | FlowArrivalEvent::~FlowArrivalEvent() { 125 | } 126 | 127 | void FlowArrivalEvent::process_event() { 128 | //Flows start at line rate; so schedule a packet to be transmitted 129 | //First packet scheduled to be queued 130 | 131 | num_outstanding_packets += (this->flow->size / this->flow->mss); 132 | arrival_packets_count += this->flow->size_in_pkt; 133 | if (num_outstanding_packets > max_outstanding_packets) { 134 | max_outstanding_packets = num_outstanding_packets; 135 | } 136 | this->flow->start_flow(); 137 | flow_arrival_count++; 138 | if (flow_arrivals.size() > 0) { 139 | add_to_event_queue(flow_arrivals.front()); 140 | flow_arrivals.pop_front(); 141 | } 142 | 143 | if(params.num_flows_to_run > 10 && flow_arrival_count % 100000 == 0){ 144 | double curr_time = get_current_time(); 145 | uint32_t num_unfinished_flows = 0; 146 | for (uint32_t i = 0; i < flows_to_schedule.size(); i++) { 147 | Flow *f = flows_to_schedule[i]; 148 | if (f->start_time < curr_time) { 149 | if (!f->finished) { 150 | num_unfinished_flows ++; 151 | } 152 | } 153 | } 154 | if(flow_arrival_count == (int)(params.num_flows_to_run * 0.5)) 155 | { 156 | arrival_packets_at_50 = arrival_packets_count; 157 | num_outstanding_packets_at_50 = num_outstanding_packets; 158 | } 159 | if(flow_arrival_count == params.num_flows_to_run) 160 | { 161 | arrival_packets_at_100 = arrival_packets_count; 162 | num_outstanding_packets_at_100 = num_outstanding_packets; 163 | } 164 | std::cout << "## " << current_time << " NumPacketOutstanding " << num_outstanding_packets 165 | << " NumUnfinishedFlows " << num_unfinished_flows << " StartedFlows " << flow_arrival_count 166 | << " StartedPkts " << arrival_packets_count << "\n"; 167 | } 168 | } 169 | 170 | 171 | /* Packet Queuing */ 172 | PacketQueuingEvent::PacketQueuingEvent(double time, Packet *packet, 173 | Queue *queue) : Event(PACKET_QUEUING, time) { 174 | this->packet = packet; 175 | this->queue = queue; 176 | } 177 | 178 | PacketQueuingEvent::~PacketQueuingEvent() { 179 | } 180 | 181 | void PacketQueuingEvent::process_event() { 182 | if (!queue->busy) { 183 | queue->queue_proc_event = new QueueProcessingEvent(get_current_time(), queue); 184 | add_to_event_queue(queue->queue_proc_event); 185 | queue->busy = true; 186 | queue->packet_transmitting = packet; 187 | } 188 | else if( params.preemptive_queue && this->packet->pf_priority < queue->packet_transmitting->pf_priority) { 189 | double remaining_percentage = (queue->queue_proc_event->time - get_current_time()) / queue->get_transmission_delay(queue->packet_transmitting->size); 190 | 191 | if(remaining_percentage > 0.01){ 192 | queue->preempt_current_transmission(); 193 | 194 | queue->queue_proc_event = new QueueProcessingEvent(get_current_time(), queue); 195 | add_to_event_queue(queue->queue_proc_event); 196 | queue->busy = true; 197 | queue->packet_transmitting = packet; 198 | } 199 | } 200 | 201 | queue->enque(packet); 202 | } 203 | 204 | /* Packet Arrival */ 205 | PacketArrivalEvent::PacketArrivalEvent(double time, Packet *packet) 206 | : Event(PACKET_ARRIVAL, time) { 207 | this->packet = packet; 208 | } 209 | 210 | PacketArrivalEvent::~PacketArrivalEvent() { 211 | } 212 | 213 | void PacketArrivalEvent::process_event() { 214 | if (packet->type == NORMAL_PACKET) { 215 | completed_packets++; 216 | } 217 | 218 | packet->flow->receive(packet); 219 | } 220 | 221 | 222 | /* Queue Processing */ 223 | QueueProcessingEvent::QueueProcessingEvent(double time, Queue *queue) 224 | : Event(QUEUE_PROCESSING, time) { 225 | this->queue = queue; 226 | } 227 | 228 | QueueProcessingEvent::~QueueProcessingEvent() { 229 | if (queue->queue_proc_event == this) { 230 | queue->queue_proc_event = NULL; 231 | queue->busy = false; //TODO is this ok?? 232 | } 233 | } 234 | 235 | void QueueProcessingEvent::process_event() { 236 | Packet *packet = queue->deque(); 237 | if (packet) { 238 | queue->busy = true; 239 | queue->busy_events.clear(); 240 | queue->packet_transmitting = packet; 241 | Queue *next_hop = topology->get_next_hop(packet, queue); 242 | double td = queue->get_transmission_delay(packet->size); 243 | double pd = queue->propagation_delay; 244 | //double additional_delay = 1e-10; 245 | queue->queue_proc_event = new QueueProcessingEvent(time + td, queue); 246 | add_to_event_queue(queue->queue_proc_event); 247 | queue->busy_events.push_back(queue->queue_proc_event); 248 | if (next_hop == NULL) { 249 | Event* arrival_evt = new PacketArrivalEvent(time + td + pd, packet); 250 | add_to_event_queue(arrival_evt); 251 | queue->busy_events.push_back(arrival_evt); 252 | } else { 253 | Event* queuing_evt = NULL; 254 | if (params.cut_through == 1) { 255 | double cut_through_delay = 256 | queue->get_transmission_delay(packet->flow->hdr_size); 257 | queuing_evt = new PacketQueuingEvent(time + cut_through_delay + pd, packet, next_hop); 258 | } else { 259 | queuing_evt = new PacketQueuingEvent(time + td + pd, packet, next_hop); 260 | } 261 | 262 | add_to_event_queue(queuing_evt); 263 | queue->busy_events.push_back(queuing_evt); 264 | } 265 | } else { 266 | queue->busy = false; 267 | queue->busy_events.clear(); 268 | queue->packet_transmitting = NULL; 269 | queue->queue_proc_event = NULL; 270 | } 271 | } 272 | 273 | 274 | LoggingEvent::LoggingEvent(double time) : Event(LOGGING, time){ 275 | this->ttl = 1e10; 276 | } 277 | 278 | LoggingEvent::LoggingEvent(double time, double ttl) : Event(LOGGING, time){ 279 | this->ttl = ttl; 280 | } 281 | 282 | LoggingEvent::~LoggingEvent() { 283 | } 284 | 285 | void LoggingEvent::process_event() { 286 | double current_time = get_current_time(); 287 | // can log simulator statistics here. 288 | } 289 | 290 | 291 | /* Flow Finished */ 292 | FlowFinishedEvent::FlowFinishedEvent(double time, Flow *flow) 293 | : Event(FLOW_FINISHED, time) { 294 | this->flow = flow; 295 | } 296 | 297 | FlowFinishedEvent::~FlowFinishedEvent() {} 298 | 299 | void FlowFinishedEvent::process_event() { 300 | this->flow->finished = true; 301 | this->flow->finish_time = get_current_time(); 302 | this->flow->flow_completion_time = this->flow->finish_time - this->flow->start_time; 303 | total_finished_flows++; 304 | auto slowdown = 1000000 * flow->flow_completion_time / topology->get_oracle_fct(flow); 305 | if (slowdown < 1.0 && slowdown > 0.9999) { 306 | slowdown = 1.0; 307 | } 308 | if (slowdown < 1.0) { 309 | std::cout << "bad slowdown " << 1e6 * flow->flow_completion_time << " " << topology->get_oracle_fct(flow) << " " << slowdown << "\n"; 310 | } 311 | assert(slowdown >= 1.0); 312 | 313 | if (print_flow_result()) { 314 | std::cout << std::setprecision(4) << std::fixed ; 315 | std::cout 316 | << flow->id << " " 317 | << flow->size << " " 318 | << flow->src->id << " " 319 | << flow->dst->id << " " 320 | << 1000000 * flow->start_time << " " 321 | << 1000000 * flow->finish_time << " " 322 | << 1000000.0 * flow->flow_completion_time << " " 323 | << topology->get_oracle_fct(flow) << " " 324 | << slowdown << " " 325 | << flow->total_pkt_sent << "/" << (flow->size/flow->mss) << "//" << flow->received_count << " " 326 | << flow->data_pkt_drop << "/" << flow->ack_pkt_drop << "/" << flow->pkt_drop << " " 327 | << 1000000 * (flow->first_byte_send_time - flow->start_time) << " " 328 | << std::endl; 329 | std::cout << std::setprecision(9) << std::fixed; 330 | } 331 | } 332 | 333 | 334 | /* Flow Processing */ 335 | FlowProcessingEvent::FlowProcessingEvent(double time, Flow *flow) 336 | : Event(FLOW_PROCESSING, time) { 337 | this->flow = flow; 338 | } 339 | 340 | FlowProcessingEvent::~FlowProcessingEvent() { 341 | if (flow->flow_proc_event == this) { 342 | flow->flow_proc_event = NULL; 343 | } 344 | } 345 | 346 | void FlowProcessingEvent::process_event() { 347 | this->flow->send_pending_data(); 348 | } 349 | 350 | 351 | /* Retx Timeout */ 352 | RetxTimeoutEvent::RetxTimeoutEvent(double time, Flow *flow) 353 | : Event(RETX_TIMEOUT, time) { 354 | this->flow = flow; 355 | } 356 | 357 | RetxTimeoutEvent::~RetxTimeoutEvent() { 358 | if (flow->retx_event == this) { 359 | flow->retx_event = NULL; 360 | } 361 | } 362 | 363 | void RetxTimeoutEvent::process_event() { 364 | flow->handle_timeout(); 365 | } 366 | 367 | -------------------------------------------------------------------------------- /coresim/event.h: -------------------------------------------------------------------------------- 1 | // 2 | // event.h 3 | // TurboCpp 4 | // 5 | // Created by Gautam Kumar on 3/9/14. 6 | // 7 | // 8 | 9 | #ifndef EVENT_H 10 | #define EVENT_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "node.h" 16 | #include "queue.h" 17 | #include "flow.h" 18 | #include "random_variable.h" 19 | 20 | //TODO import globals 21 | 22 | #define FLOW_ARRIVAL 0 23 | #define PACKET_QUEUING 1 24 | #define PACKET_ARRIVAL 2 25 | #define QUEUE_PROCESSING 3 26 | #define RETX_TIMEOUT 5 27 | #define FLOW_FINISHED 6 28 | #define FLOW_PROCESSING 7 29 | #define FLOW_CREATION_EVENT 8 30 | #define LOGGING 9 31 | 32 | class Event { 33 | public: 34 | Event(uint32_t type, double time); 35 | virtual ~Event(); 36 | bool operator == (const Event& e) const { 37 | return (time == e.time && type == e.type); 38 | } 39 | bool operator < (const Event& e) const { 40 | if (time < e.time) return true; 41 | else if (time == e.time && type < e.type) return true; 42 | else return false; 43 | } 44 | bool operator > (const Event& e) const { 45 | if (time > e.time) return true; 46 | else if (time == e.time && type > e.type) return true; 47 | else return false; 48 | } 49 | 50 | virtual void process_event() = 0; 51 | 52 | uint32_t unique_id; 53 | static uint32_t instance_count; 54 | 55 | uint32_t type; 56 | double time; 57 | bool cancelled; 58 | }; 59 | 60 | struct EventComparator 61 | { 62 | bool operator() (Event *a, Event *b) { 63 | if (fabs(a->time - b->time) < 1e-15) { 64 | return a->type > b->type; 65 | } else { 66 | return a->time > b->time; 67 | } 68 | } 69 | }; 70 | 71 | //A flow arrival event Only used for FlowCreation 72 | class FlowCreationForInitializationEvent : public Event { 73 | public: 74 | FlowCreationForInitializationEvent( 75 | double time, 76 | Host *src, 77 | Host *dst, 78 | EmpiricalRandomVariable *nv_bytes, 79 | RandomVariable *nv_intarr 80 | ); 81 | ~FlowCreationForInitializationEvent(); 82 | void process_event(); 83 | Host *src; 84 | Host *dst; 85 | EmpiricalRandomVariable *nv_bytes; 86 | RandomVariable *nv_intarr; 87 | }; 88 | 89 | //A flow arrival event 90 | class FlowArrivalEvent : public Event { 91 | public: 92 | FlowArrivalEvent(double time, Flow *flow); 93 | ~FlowArrivalEvent(); 94 | void process_event(); 95 | Flow *flow; 96 | }; 97 | 98 | // packet gets queued 99 | class PacketQueuingEvent : public Event { 100 | public: 101 | PacketQueuingEvent(double time, Packet *packet, Queue *queue); 102 | ~PacketQueuingEvent(); 103 | void process_event(); 104 | Packet *packet; 105 | Queue *queue; 106 | }; 107 | 108 | // packet arrival 109 | class PacketArrivalEvent : public Event { 110 | public: 111 | PacketArrivalEvent(double time, Packet *packet); 112 | ~PacketArrivalEvent(); 113 | void process_event(); 114 | Packet *packet; 115 | }; 116 | 117 | class QueueProcessingEvent : public Event { 118 | public: 119 | QueueProcessingEvent(double time, Queue *queue); 120 | ~QueueProcessingEvent(); 121 | void process_event(); 122 | Queue *queue; 123 | }; 124 | 125 | class LoggingEvent : public Event { 126 | public: 127 | LoggingEvent(double time); 128 | LoggingEvent(double time, double ttl); 129 | ~LoggingEvent(); 130 | void process_event(); 131 | double ttl; 132 | }; 133 | 134 | //A flow finished event 135 | class FlowFinishedEvent : public Event { 136 | public: 137 | FlowFinishedEvent(double time, Flow *flow); 138 | ~FlowFinishedEvent(); 139 | void process_event(); 140 | Flow *flow; 141 | }; 142 | 143 | //A flow processing event 144 | class FlowProcessingEvent : public Event { 145 | public: 146 | FlowProcessingEvent(double time, Flow *flow); 147 | ~FlowProcessingEvent(); 148 | 149 | void process_event(); 150 | Flow *flow; 151 | }; 152 | 153 | class RetxTimeoutEvent : public Event { 154 | public: 155 | RetxTimeoutEvent(double time, Flow *flow); 156 | ~RetxTimeoutEvent(); 157 | void process_event(); 158 | Flow *flow; 159 | }; 160 | 161 | #endif /* defined(EVENT_H) */ 162 | 163 | -------------------------------------------------------------------------------- /coresim/flow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flow.h" 6 | #include "packet.h" 7 | #include "event.h" 8 | 9 | #include "../run/params.h" 10 | 11 | extern double get_current_time(); 12 | extern void add_to_event_queue(Event *); 13 | extern int get_event_queue_size(); 14 | extern DCExpParams params; 15 | extern uint32_t num_outstanding_packets; 16 | extern uint32_t max_outstanding_packets; 17 | extern uint32_t duplicated_packets_received; 18 | 19 | Flow::Flow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) { 20 | this->id = id; 21 | this->start_time = start_time; 22 | this->finish_time = 0; 23 | this->size = size; 24 | this->src = s; 25 | this->dst = d; 26 | 27 | this->next_seq_no = 0; 28 | this->last_unacked_seq = 0; 29 | this->retx_event = NULL; 30 | this->flow_proc_event = NULL; 31 | 32 | this->received_bytes = 0; 33 | this->recv_till = 0; 34 | this->max_seq_no_recv = 0; 35 | this->cwnd_mss = params.initial_cwnd; 36 | this->max_cwnd = params.max_cwnd; 37 | this->finished = false; 38 | 39 | //SACK 40 | this->scoreboard_sack_bytes = 0; 41 | 42 | this->retx_timeout = params.retx_timeout_value; 43 | this->mss = params.mss; 44 | this->hdr_size = params.hdr_size; 45 | this->total_pkt_sent = 0; 46 | this->size_in_pkt = (int)ceil((double)size/mss); 47 | 48 | this->pkt_drop = 0; 49 | this->data_pkt_drop = 0; 50 | this->ack_pkt_drop = 0; 51 | this->flow_priority = 0; 52 | this->first_byte_send_time = -1; 53 | this->first_byte_receive_time = -1; 54 | this->first_hop_departure = 0; 55 | this->last_hop_departure = 0; 56 | } 57 | 58 | Flow::~Flow() { 59 | // packets.clear(); 60 | } 61 | 62 | void Flow::start_flow() { 63 | send_pending_data(); 64 | } 65 | 66 | void Flow::send_pending_data() { 67 | if (received_bytes < size) { 68 | uint32_t seq = next_seq_no; 69 | uint32_t window = cwnd_mss * mss + scoreboard_sack_bytes; 70 | while ( 71 | (seq + mss <= last_unacked_seq + window) && 72 | ((seq + mss <= size) || (seq != size && (size - seq < mss))) 73 | ) { 74 | // TODO Make it explicit through the SACK list 75 | if (received.count(seq) == 0) { 76 | send(seq); 77 | } 78 | 79 | if (seq + mss < size) { 80 | next_seq_no = seq + mss; 81 | seq += mss; 82 | } else { 83 | next_seq_no = size; 84 | seq = size; 85 | } 86 | 87 | if (retx_event == NULL) { 88 | set_timeout(get_current_time() + retx_timeout); 89 | } 90 | } 91 | } 92 | } 93 | 94 | Packet *Flow::send(uint32_t seq) { 95 | Packet *p = NULL; 96 | 97 | uint32_t pkt_size; 98 | if (seq + mss > this->size) { 99 | pkt_size = this->size - seq + hdr_size; 100 | } else { 101 | pkt_size = mss + hdr_size; 102 | } 103 | 104 | uint32_t priority = get_priority(seq); 105 | p = new Packet( 106 | get_current_time(), 107 | this, 108 | seq, 109 | priority, 110 | pkt_size, 111 | src, 112 | dst 113 | ); 114 | this->total_pkt_sent++; 115 | 116 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, src->queue)); 117 | return p; 118 | } 119 | 120 | void Flow::send_ack(uint32_t seq, std::vector sack_list) { 121 | Packet *p = new Ack(this, seq, sack_list, hdr_size, dst, src); //Acks are dst->src 122 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, dst->queue)); 123 | } 124 | 125 | void Flow::receive_ack(uint32_t ack, std::vector sack_list) { 126 | this->scoreboard_sack_bytes = sack_list.size() * mss; 127 | 128 | // On timeouts; next_seq_no is updated to the last_unacked_seq; 129 | // In such cases, the ack can be greater than next_seq_no; update it 130 | if (next_seq_no < ack) { 131 | next_seq_no = ack; 132 | } 133 | 134 | // New ack! 135 | if (ack > last_unacked_seq) { 136 | // Update the last unacked seq 137 | last_unacked_seq = ack; 138 | 139 | // Adjust cwnd 140 | increase_cwnd(); 141 | 142 | // Send the remaining data 143 | send_pending_data(); 144 | 145 | // Update the retx timer 146 | if (retx_event != NULL) { // Try to move 147 | cancel_retx_event(); 148 | if (last_unacked_seq < size) { 149 | // Move the timeout to last_unacked_seq 150 | double timeout = get_current_time() + retx_timeout; 151 | set_timeout(timeout); 152 | } 153 | } 154 | 155 | } 156 | 157 | if (ack == size && !finished) { 158 | finished = true; 159 | received.clear(); 160 | finish_time = get_current_time(); 161 | flow_completion_time = finish_time - start_time; 162 | FlowFinishedEvent *ev = new FlowFinishedEvent(get_current_time(), this); 163 | add_to_event_queue(ev); 164 | } 165 | } 166 | 167 | 168 | void Flow::receive(Packet *p) { 169 | if (finished) { 170 | delete p; 171 | return; 172 | } 173 | 174 | if (p->type == ACK_PACKET) { 175 | Ack *a = (Ack *) p; 176 | receive_ack(a->seq_no, a->sack_list); 177 | } 178 | else if(p->type == NORMAL_PACKET) { 179 | if (this->first_byte_receive_time == -1) { 180 | this->first_byte_receive_time = get_current_time(); 181 | } 182 | this->receive_data_pkt(p); 183 | } 184 | else { 185 | assert(false); 186 | } 187 | 188 | delete p; 189 | } 190 | 191 | void Flow::receive_data_pkt(Packet* p) { 192 | received_count++; 193 | total_queuing_time += p->total_queuing_delay; 194 | 195 | if (received.count(p->seq_no) == 0) { 196 | received[p->seq_no] = true; 197 | if(num_outstanding_packets >= ((p->size - hdr_size) / (mss))) 198 | num_outstanding_packets -= ((p->size - hdr_size) / (mss)); 199 | else 200 | num_outstanding_packets = 0; 201 | received_bytes += (p->size - hdr_size); 202 | } else { 203 | duplicated_packets_received += 1; 204 | } 205 | if (p->seq_no > max_seq_no_recv) { 206 | max_seq_no_recv = p->seq_no; 207 | } 208 | // Determing which ack to send 209 | uint32_t s = recv_till; 210 | bool in_sequence = true; 211 | std::vector sack_list; 212 | while (s <= max_seq_no_recv) { 213 | if (received.count(s) > 0) { 214 | if (in_sequence) { 215 | if (recv_till + mss > this->size) { 216 | recv_till = this->size; 217 | } else { 218 | recv_till += mss; 219 | } 220 | } else { 221 | sack_list.push_back(s); 222 | } 223 | } else { 224 | in_sequence = false; 225 | } 226 | s += mss; 227 | } 228 | 229 | send_ack(recv_till, sack_list); // Cumulative Ack 230 | } 231 | 232 | void Flow::set_timeout(double time) { 233 | if (last_unacked_seq < size) { 234 | RetxTimeoutEvent *ev = new RetxTimeoutEvent(time, this); 235 | add_to_event_queue(ev); 236 | retx_event = ev; 237 | } 238 | } 239 | 240 | 241 | void Flow::handle_timeout() { 242 | next_seq_no = last_unacked_seq; 243 | //Reset congestion window to 1 244 | cwnd_mss = 1; 245 | send_pending_data(); //TODO Send again 246 | set_timeout(get_current_time() + retx_timeout); // TODO 247 | } 248 | 249 | 250 | void Flow::cancel_retx_event() { 251 | if (retx_event) { 252 | retx_event->cancelled = true; 253 | } 254 | retx_event = NULL; 255 | } 256 | 257 | 258 | uint32_t Flow::get_priority(uint32_t seq) { 259 | if (params.flow_type == 1) { 260 | return 1; 261 | } 262 | if(params.deadline && params.schedule_by_deadline) 263 | { 264 | return (int)(this->deadline * 1000000); 265 | } 266 | else{ 267 | return (size - last_unacked_seq - scoreboard_sack_bytes); 268 | } 269 | } 270 | 271 | 272 | void Flow::increase_cwnd() { 273 | cwnd_mss += 1; 274 | if (cwnd_mss > max_cwnd) { 275 | cwnd_mss = max_cwnd; 276 | } 277 | } 278 | 279 | double Flow::get_avg_queuing_delay_in_us() 280 | { 281 | return total_queuing_time/received_count * 1000000; 282 | } 283 | 284 | -------------------------------------------------------------------------------- /coresim/flow.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOW_H 2 | #define FLOW_H 3 | 4 | #include 5 | #include "node.h" 6 | 7 | class Packet; 8 | class Ack; 9 | class Probe; 10 | class RetxTimeoutEvent; 11 | class FlowProcessingEvent; 12 | 13 | class Flow { 14 | public: 15 | Flow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 16 | 17 | ~Flow(); // Destructor 18 | 19 | virtual void start_flow(); 20 | virtual void send_pending_data(); 21 | virtual Packet *send(uint32_t seq); 22 | virtual void send_ack(uint32_t seq, std::vector sack_list); 23 | virtual void receive_ack(uint32_t ack, std::vector sack_list); 24 | void receive_data_pkt(Packet* p); 25 | virtual void receive(Packet *p); 26 | 27 | // Only sets the timeout if needed; i.e., flow hasn't finished 28 | virtual void set_timeout(double time); 29 | virtual void handle_timeout(); 30 | virtual void cancel_retx_event(); 31 | 32 | virtual uint32_t get_priority(uint32_t seq); 33 | virtual void increase_cwnd(); 34 | virtual double get_avg_queuing_delay_in_us(); 35 | 36 | uint32_t id; 37 | double start_time; 38 | double finish_time; 39 | uint32_t size; 40 | Host *src; 41 | Host *dst; 42 | uint32_t cwnd_mss; 43 | uint32_t max_cwnd; 44 | double retx_timeout; 45 | uint32_t mss; 46 | uint32_t hdr_size; 47 | 48 | // Sender variables 49 | uint32_t next_seq_no; 50 | uint32_t last_unacked_seq; 51 | RetxTimeoutEvent *retx_event; 52 | FlowProcessingEvent *flow_proc_event; 53 | 54 | // std::unordered_map packets; 55 | 56 | // Receiver variables 57 | std::unordered_map received; 58 | uint32_t received_bytes; 59 | uint32_t recv_till; 60 | uint32_t max_seq_no_recv; 61 | 62 | uint32_t total_pkt_sent; 63 | int size_in_pkt; 64 | int pkt_drop; 65 | int data_pkt_drop; 66 | int ack_pkt_drop; 67 | int first_hop_departure; 68 | int last_hop_departure; 69 | uint32_t received_count; 70 | // Sack 71 | uint32_t scoreboard_sack_bytes; 72 | // finished variables 73 | bool finished; 74 | double flow_completion_time; 75 | double total_queuing_time; 76 | double first_byte_send_time; 77 | double first_byte_receive_time; 78 | 79 | uint32_t flow_priority; 80 | double deadline; 81 | }; 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /coresim/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "assert.h" 9 | 10 | #include "flow.h" 11 | #include "packet.h" 12 | #include "node.h" 13 | #include "event.h" 14 | #include "topology.h" 15 | #include "queue.h" 16 | #include "random_variable.h" 17 | 18 | #include "../ext/factory.h" 19 | //#include "../ext/fastpasshost.h" 20 | 21 | #include "../run/params.h" 22 | 23 | using namespace std; 24 | 25 | Topology* topology; 26 | double current_time = 0; 27 | std::priority_queue, EventComparator> event_queue; 28 | std::deque flows_to_schedule; 29 | std::deque flow_arrivals; 30 | 31 | uint32_t num_outstanding_packets = 0; 32 | uint32_t max_outstanding_packets = 0; 33 | uint32_t num_outstanding_packets_at_50 = 0; 34 | uint32_t num_outstanding_packets_at_100 = 0; 35 | uint32_t arrival_packets_at_50 = 0; 36 | uint32_t arrival_packets_at_100 = 0; 37 | uint32_t arrival_packets_count = 0; 38 | uint32_t total_finished_flows = 0; 39 | uint32_t duplicated_packets_received = 0; 40 | 41 | uint32_t injected_packets = 0; 42 | uint32_t duplicated_packets = 0; 43 | uint32_t dead_packets = 0; 44 | uint32_t completed_packets = 0; 45 | uint32_t backlog3 = 0; 46 | uint32_t backlog4 = 0; 47 | uint32_t total_completed_packets = 0; 48 | uint32_t sent_packets = 0; 49 | 50 | extern DCExpParams params; 51 | double start_time = -1; 52 | 53 | const std::string currentDateTime() { 54 | time_t now = time(0); 55 | struct tm tstruct; 56 | char buf[80]; 57 | tstruct = *localtime(&now); 58 | // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime 59 | // for more information about date/time format 60 | strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct); 61 | 62 | return buf; 63 | } 64 | 65 | void add_to_event_queue(Event* ev) { 66 | event_queue.push(ev); 67 | } 68 | 69 | int get_event_queue_size() { 70 | return event_queue.size(); 71 | } 72 | 73 | double get_current_time() { 74 | return current_time; // in us 75 | } 76 | 77 | /* Runs a initialized scenario */ 78 | void run_scenario() { 79 | // Flow Arrivals create new flow arrivals 80 | // Add the first flow arrival 81 | if (flow_arrivals.size() > 0) { 82 | add_to_event_queue(flow_arrivals.front()); 83 | flow_arrivals.pop_front(); 84 | } 85 | int last_evt_type = -1; 86 | int same_evt_count = 0; 87 | while (event_queue.size() > 0) { 88 | Event *ev = event_queue.top(); 89 | event_queue.pop(); 90 | current_time = ev->time; 91 | if (start_time < 0) { 92 | start_time = current_time; 93 | } 94 | if (ev->cancelled) { 95 | delete ev; //TODO: Smarter 96 | continue; 97 | } 98 | ev->process_event(); 99 | 100 | if(last_evt_type == ev->type && last_evt_type != 9) 101 | same_evt_count++; 102 | else 103 | same_evt_count = 0; 104 | 105 | last_evt_type = ev->type; 106 | 107 | if(same_evt_count > 100000){ 108 | std::cout << "Ended event dead loop. Type:" << last_evt_type << "\n"; 109 | break; 110 | } 111 | 112 | delete ev; 113 | } 114 | } 115 | 116 | extern void run_experiment(int argc, char** argv, uint32_t exp_type); 117 | 118 | int main (int argc, char ** argv) { 119 | time_t start_time; 120 | time(&start_time); 121 | 122 | //srand(time(NULL)); 123 | srand(0); 124 | std::cout.precision(15); 125 | 126 | uint32_t exp_type = atoi(argv[1]); 127 | switch (exp_type) { 128 | case GEN_ONLY: 129 | case DEFAULT_EXP: 130 | run_experiment(argc, argv, exp_type); 131 | break; 132 | default: 133 | assert(false); 134 | } 135 | 136 | time_t end_time; 137 | time(&end_time); 138 | double duration = difftime(end_time, start_time); 139 | cout << currentDateTime() << " Simulator ended. Execution time: " << duration << " seconds\n"; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /coresim/node.cpp: -------------------------------------------------------------------------------- 1 | #include "packet.h" 2 | #include "flow.h" 3 | 4 | #include "../ext/factory.h" 5 | 6 | #include "../run/params.h" 7 | 8 | extern DCExpParams params; 9 | 10 | bool FlowComparator::operator() (Flow *a, Flow *b) { 11 | return a->flow_priority > b->flow_priority; 12 | // if(a->flow_priority > b->flow_priority) 13 | // return true; 14 | // else if(a->flow_priority == b->flow_priority) 15 | // return a->id > b->id; 16 | // else 17 | // return false; 18 | } 19 | 20 | Node::Node(uint32_t id, uint32_t type) { 21 | this->id = id; 22 | this->type = type; 23 | } 24 | 25 | // TODO FIX superclass constructor 26 | Host::Host(uint32_t id, double rate, uint32_t queue_type, uint32_t host_type) : Node(id, HOST) { 27 | queue = Factory::get_queue(id, rate, params.queue_size, queue_type, 0, 0); 28 | this->host_type = host_type; 29 | } 30 | 31 | // TODO FIX superclass constructor 32 | Switch::Switch(uint32_t id, uint32_t switch_type) : Node(id, SWITCH) { 33 | this->switch_type = switch_type; 34 | } 35 | 36 | CoreSwitch::CoreSwitch(uint32_t id, uint32_t nq, double rate, uint32_t type) : Switch(id, CORE_SWITCH) { 37 | for (uint32_t i = 0; i < nq; i++) { 38 | queues.push_back(Factory::get_queue(i, rate, params.queue_size, type, 0, 2)); 39 | } 40 | } 41 | 42 | //nq1: # host switch, nq2: # core switch 43 | AggSwitch::AggSwitch( 44 | uint32_t id, 45 | uint32_t nq1, 46 | double r1, 47 | uint32_t nq2, 48 | double r2, 49 | uint32_t type 50 | ) : Switch(id, AGG_SWITCH) { 51 | for (uint32_t i = 0; i < nq1; i++) { 52 | queues.push_back(Factory::get_queue(i, r1, params.queue_size, type, 0, 3)); 53 | } 54 | for (uint32_t i = 0; i < nq2; i++) { 55 | queues.push_back(Factory::get_queue(i, r2, params.queue_size, type, 0, 1)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /coresim/node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | #define NODE_H 3 | 4 | #include 5 | #include 6 | #include "queue.h" 7 | 8 | 9 | #define HOST 0 10 | #define SWITCH 1 11 | 12 | #define CORE_SWITCH 10 13 | #define AGG_SWITCH 11 14 | 15 | #define CPU 0 16 | #define MEM 1 17 | #define DISK 2 18 | 19 | class Packet; 20 | class Flow; 21 | 22 | 23 | class FlowComparator{ 24 | public: 25 | bool operator() (Flow *a, Flow *b); 26 | }; 27 | 28 | 29 | class Node { 30 | public: 31 | Node(uint32_t id, uint32_t type); 32 | uint32_t id; 33 | uint32_t type; 34 | }; 35 | 36 | class Host : public Node { 37 | public: 38 | Host(uint32_t id, double rate, uint32_t queue_type, uint32_t host_type); 39 | Queue *queue; 40 | int host_type; 41 | }; 42 | 43 | class Switch : public Node { 44 | public: 45 | Switch(uint32_t id, uint32_t switch_type); 46 | uint32_t switch_type; 47 | std::vector queues; 48 | }; 49 | 50 | class CoreSwitch : public Switch { 51 | public: 52 | //All queues have same rate 53 | CoreSwitch(uint32_t id, uint32_t nq, double rate, uint32_t queue_type); 54 | }; 55 | 56 | class AggSwitch : public Switch { 57 | public: 58 | // Different Rates 59 | AggSwitch(uint32_t id, uint32_t nq1, double r1, uint32_t nq2, double r2, uint32_t queue_type); 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /coresim/packet.cpp: -------------------------------------------------------------------------------- 1 | #include "packet.h" 2 | #include "../run/params.h" 3 | 4 | extern DCExpParams params; 5 | uint32_t Packet::instance_count = 0; 6 | 7 | Packet::Packet( 8 | double sending_time, 9 | Flow *flow, 10 | uint32_t seq_no, 11 | uint32_t pf_priority, 12 | uint32_t size, 13 | Host *src, 14 | Host *dst 15 | ) { 16 | this->sending_time = sending_time; 17 | this->flow = flow; 18 | this->seq_no = seq_no; 19 | this->pf_priority = pf_priority; 20 | this->size = size; 21 | this->src = src; 22 | this->dst = dst; 23 | 24 | this->type = NORMAL_PACKET; 25 | this->unique_id = Packet::instance_count++; 26 | this->total_queuing_delay = 0; 27 | } 28 | 29 | PlainAck::PlainAck(Flow *flow, uint32_t seq_no_acked, uint32_t size, Host* src, Host *dst) : Packet(0, flow, seq_no_acked, 0, size, src, dst) { 30 | this->type = ACK_PACKET; 31 | } 32 | 33 | Ack::Ack(Flow *flow, uint32_t seq_no_acked, std::vector sack_list, uint32_t size, Host* src, Host *dst) : Packet(0, flow, seq_no_acked, 0, size, src, dst) { 34 | this->type = ACK_PACKET; 35 | this->sack_list = sack_list; 36 | } 37 | 38 | RTSCTS::RTSCTS(bool type, double sending_time, Flow *f, uint32_t size, Host *src, Host *dst) : Packet(sending_time, f, 0, 0, f->hdr_size, src, dst) { 39 | if (type) { 40 | this->type = RTS_PACKET; 41 | } 42 | else { 43 | this->type = CTS_PACKET; 44 | } 45 | } 46 | 47 | RTS::RTS(Flow *flow, Host *src, Host *dst, double delay, int iter) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 48 | this->type = RTS_PACKET; 49 | this->delay = delay; 50 | this->iter = iter; 51 | } 52 | 53 | 54 | OfferPkt::OfferPkt(Flow *flow, Host *src, Host *dst, bool is_free, int iter) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 55 | this->type = OFFER_PACKET; 56 | this->is_free = is_free; 57 | this->iter = iter; 58 | } 59 | 60 | DecisionPkt::DecisionPkt(Flow *flow, Host *src, Host *dst, bool accept) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 61 | this->type = DECISION_PACKET; 62 | this->accept = accept; 63 | } 64 | 65 | CTS::CTS(Flow *flow, Host *src, Host *dst) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 66 | this->type = CTS_PACKET; 67 | } 68 | 69 | CapabilityPkt::CapabilityPkt(Flow *flow, Host *src, Host *dst, double ttl, int remaining, int cap_seq_num, int data_seq_num) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 70 | this->type = CAPABILITY_PACKET; 71 | this->ttl = ttl; 72 | this->remaining_sz = remaining; 73 | this->cap_seq_num = cap_seq_num; 74 | this->data_seq_num = data_seq_num; 75 | } 76 | 77 | StatusPkt::StatusPkt(Flow *flow, Host *src, Host *dst, int num_flows_at_sender) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 78 | this->type = STATUS_PACKET; 79 | this->num_flows_at_sender = num_flows_at_sender; 80 | } 81 | 82 | 83 | FastpassRTS::FastpassRTS(Flow *flow, Host *src, Host *dst, int remaining_pkt) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 84 | this->type = FASTPASS_RTS; 85 | this->remaining_num_pkts = remaining_pkt; 86 | } 87 | 88 | FastpassSchedulePkt::FastpassSchedulePkt(Flow *flow, Host *src, Host *dst, FastpassEpochSchedule* schd) : Packet(0, flow, 0, 0, params.hdr_size, src, dst) { 89 | this->type = FASTPASS_SCHEDULE; 90 | this->schedule = schd; 91 | } 92 | 93 | -------------------------------------------------------------------------------- /coresim/packet.h: -------------------------------------------------------------------------------- 1 | #ifndef PACKET_H 2 | #define PACKET_H 3 | 4 | #include "flow.h" 5 | #include "node.h" 6 | #include 7 | // TODO: Change to Enum 8 | #define NORMAL_PACKET 0 9 | #define ACK_PACKET 1 10 | 11 | #define RTS_PACKET 3 12 | #define CTS_PACKET 4 13 | #define OFFER_PACKET 5 14 | #define DECISION_PACKET 6 15 | #define CAPABILITY_PACKET 7 16 | #define STATUS_PACKET 8 17 | #define FASTPASS_RTS 9 18 | #define FASTPASS_SCHEDULE 10 19 | 20 | class FastpassEpochSchedule; 21 | 22 | class Packet { 23 | 24 | public: 25 | Packet(double sending_time, Flow *flow, uint32_t seq_no, uint32_t pf_priority, 26 | uint32_t size, Host *src, Host *dst); 27 | 28 | double sending_time; 29 | Flow *flow; 30 | uint32_t seq_no; 31 | uint32_t pf_priority; 32 | uint32_t size; 33 | Host *src; 34 | Host *dst; 35 | uint32_t unique_id; 36 | static uint32_t instance_count; 37 | int remaining_pkts_in_batch; 38 | int capability_seq_num_in_data; 39 | 40 | uint32_t type; // Normal or Ack packet 41 | double total_queuing_delay; 42 | double last_enque_time; 43 | 44 | int capa_data_seq; 45 | }; 46 | 47 | class PlainAck : public Packet { 48 | public: 49 | PlainAck(Flow *flow, uint32_t seq_no_acked, uint32_t size, Host* src, Host* dst); 50 | }; 51 | 52 | class Ack : public Packet { 53 | public: 54 | Ack(Flow *flow, uint32_t seq_no_acked, std::vector sack_list, 55 | uint32_t size, 56 | Host* src, Host *dst); 57 | uint32_t sack_bytes; 58 | std::vector sack_list; 59 | }; 60 | 61 | class RTSCTS : public Packet { 62 | public: 63 | //type: true if RTS, false if CTS 64 | RTSCTS(bool type, double sending_time, Flow *f, uint32_t size, Host *src, Host *dst); 65 | }; 66 | 67 | class RTS : public Packet{ 68 | public: 69 | RTS(Flow *flow, Host *src, Host *dst, double delay, int iter); 70 | double delay; 71 | int iter; 72 | }; 73 | 74 | class OfferPkt : public Packet{ 75 | public: 76 | OfferPkt(Flow *flow, Host *src, Host *dst, bool is_free, int iter); 77 | bool is_free; 78 | int iter; 79 | }; 80 | 81 | class DecisionPkt : public Packet{ 82 | public: 83 | DecisionPkt(Flow *flow, Host *src, Host *dst, bool accept); 84 | bool accept; 85 | }; 86 | 87 | class CTS : public Packet{ 88 | public: 89 | CTS(Flow *flow, Host *src, Host *dst); 90 | }; 91 | 92 | class CapabilityPkt : public Packet{ 93 | public: 94 | CapabilityPkt(Flow *flow, Host *src, Host *dst, double ttl, int remaining, int cap_seq_num, int data_seq_num); 95 | double ttl; 96 | int remaining_sz; 97 | int cap_seq_num; 98 | int data_seq_num; 99 | }; 100 | 101 | class StatusPkt : public Packet{ 102 | public: 103 | StatusPkt(Flow *flow, Host *src, Host *dst, int num_flows_at_sender); 104 | double ttl; 105 | bool num_flows_at_sender; 106 | }; 107 | 108 | 109 | class FastpassRTS : public Packet 110 | { 111 | public: 112 | FastpassRTS(Flow *flow, Host *src, Host *dst, int remaining_pkt); 113 | int remaining_num_pkts; 114 | }; 115 | 116 | class FastpassSchedulePkt : public Packet 117 | { 118 | public: 119 | FastpassSchedulePkt(Flow *flow, Host *src, Host *dst, FastpassEpochSchedule* schd); 120 | FastpassEpochSchedule* schedule; 121 | }; 122 | 123 | #endif 124 | 125 | -------------------------------------------------------------------------------- /coresim/queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "assert.h" 5 | 6 | #include "queue.h" 7 | #include "packet.h" 8 | #include "event.h" 9 | #include "debug.h" 10 | 11 | #include "../run/params.h" 12 | 13 | extern double get_current_time(); // TODOm 14 | extern void add_to_event_queue(Event* ev); 15 | extern uint32_t dead_packets; 16 | extern DCExpParams params; 17 | 18 | uint32_t Queue::instance_count = 0; 19 | 20 | /* Queues */ 21 | Queue::Queue(uint32_t id, double rate, uint32_t limit_bytes, int location) { 22 | this->id = id; 23 | this->unique_id = Queue::instance_count++; 24 | this->rate = rate; // in bps 25 | this->limit_bytes = limit_bytes; 26 | this->bytes_in_queue = 0; 27 | this->busy = false; 28 | this->queue_proc_event = NULL; 29 | //this->packet_propagation_event = NULL; 30 | this->location = location; 31 | 32 | if (params.ddc != 0) { 33 | if (location == 0) { 34 | this->propagation_delay = 10e-9; 35 | } 36 | else if (location == 1 || location == 2) { 37 | this->propagation_delay = 400e-9; 38 | } 39 | else if (location == 3) { 40 | this->propagation_delay = 210e-9; 41 | } 42 | else { 43 | assert(false); 44 | } 45 | } 46 | else { 47 | this->propagation_delay = params.propagation_delay; 48 | } 49 | this->p_arrivals = 0; this->p_departures = 0; 50 | this->b_arrivals = 0; this->b_departures = 0; 51 | 52 | this->pkt_drop = 0; 53 | this->spray_counter=std::rand(); 54 | this->packet_transmitting = NULL; 55 | } 56 | 57 | void Queue::set_src_dst(Node *src, Node *dst) { 58 | this->src = src; 59 | this->dst = dst; 60 | } 61 | 62 | void Queue::enque(Packet *packet) { 63 | p_arrivals += 1; 64 | b_arrivals += packet->size; 65 | if (bytes_in_queue + packet->size <= limit_bytes) { 66 | packets.push_back(packet); 67 | bytes_in_queue += packet->size; 68 | } else { 69 | pkt_drop++; 70 | drop(packet); 71 | } 72 | } 73 | 74 | Packet *Queue::deque() { 75 | if (bytes_in_queue > 0) { 76 | Packet *p = packets.front(); 77 | packets.pop_front(); 78 | bytes_in_queue -= p->size; 79 | p_departures += 1; 80 | b_departures += p->size; 81 | return p; 82 | } 83 | return NULL; 84 | } 85 | 86 | void Queue::drop(Packet *packet) { 87 | packet->flow->pkt_drop++; 88 | if(packet->seq_no < packet->flow->size){ 89 | packet->flow->data_pkt_drop++; 90 | } 91 | if(packet->type == ACK_PACKET) 92 | packet->flow->ack_pkt_drop++; 93 | 94 | if (location != 0 && packet->type == NORMAL_PACKET) { 95 | dead_packets += 1; 96 | } 97 | 98 | if(debug_flow(packet->flow->id)) 99 | std::cout << get_current_time() << " pkt drop. flow:" << packet->flow->id 100 | << " type:" << packet->type << " seq:" << packet->seq_no 101 | << " at queue id:" << this->id << " loc:" << this->location << "\n"; 102 | 103 | delete packet; 104 | } 105 | 106 | double Queue::get_transmission_delay(uint32_t size) { 107 | return size * 8.0 / rate; 108 | } 109 | 110 | void Queue::preempt_current_transmission() { 111 | if(params.preemptive_queue && busy){ 112 | this->queue_proc_event->cancelled = true; 113 | assert(this->packet_transmitting); 114 | 115 | uint delete_index; 116 | bool found = false; 117 | for (delete_index = 0; delete_index < packets.size(); delete_index++) { 118 | if (packets[delete_index] == this->packet_transmitting) { 119 | found = true; 120 | break; 121 | } 122 | } 123 | if(found){ 124 | bytes_in_queue -= packet_transmitting->size; 125 | packets.erase(packets.begin() + delete_index); 126 | } 127 | 128 | for(uint i = 0; i < busy_events.size(); i++){ 129 | busy_events[i]->cancelled = true; 130 | } 131 | busy_events.clear(); 132 | //drop(packet_transmitting);//TODO: should be put back to queue 133 | enque(packet_transmitting); 134 | packet_transmitting = NULL; 135 | queue_proc_event = NULL; 136 | busy = false; 137 | } 138 | } 139 | 140 | /* Implementation for probabilistically dropping queue */ 141 | ProbDropQueue::ProbDropQueue(uint32_t id, double rate, uint32_t limit_bytes, 142 | double drop_prob, int location) 143 | : Queue(id, rate, limit_bytes, location) { 144 | this->drop_prob = drop_prob; 145 | } 146 | 147 | void ProbDropQueue::enque(Packet *packet) { 148 | p_arrivals += 1; 149 | b_arrivals += packet->size; 150 | 151 | if (bytes_in_queue + packet->size <= limit_bytes) { 152 | double r = (1.0 * rand()) / (1.0 * RAND_MAX); 153 | if (r < drop_prob) { 154 | return; 155 | } 156 | packets.push_back(packet); 157 | bytes_in_queue += packet->size; 158 | if (!busy) { 159 | add_to_event_queue(new QueueProcessingEvent(get_current_time(), this)); 160 | this->busy = true; 161 | //if(this->id == 7) std::cout << "!!!!!queue.cpp:189\n"; 162 | this->packet_transmitting = packet; 163 | } 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /coresim/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_H 2 | #define QUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define DROPTAIL_QUEUE 1 9 | 10 | class Node; 11 | class Packet; 12 | class Event; 13 | 14 | class QueueProcessingEvent; 15 | class PacketPropagationEvent; 16 | 17 | class Queue { 18 | public: 19 | Queue(uint32_t id, double rate, uint32_t limit_bytes, int location); 20 | void set_src_dst(Node *src, Node *dst); 21 | virtual void enque(Packet *packet); 22 | virtual Packet *deque(); 23 | virtual void drop(Packet *packet); 24 | double get_transmission_delay(uint32_t size); 25 | void preempt_current_transmission(); 26 | 27 | // Members 28 | uint32_t id; 29 | uint32_t unique_id; 30 | static uint32_t instance_count; 31 | double rate; 32 | uint32_t limit_bytes; 33 | std::deque packets; 34 | uint32_t bytes_in_queue; 35 | bool busy; 36 | QueueProcessingEvent *queue_proc_event; 37 | 38 | std::vector busy_events; 39 | Packet* packet_transmitting; 40 | 41 | Node *src; 42 | Node *dst; 43 | 44 | uint64_t b_arrivals, b_departures; 45 | uint64_t p_arrivals, p_departures; 46 | 47 | double propagation_delay; 48 | bool interested; 49 | 50 | uint64_t pkt_drop; 51 | uint64_t spray_counter; 52 | 53 | int location; 54 | }; 55 | 56 | 57 | class ProbDropQueue : public Queue { 58 | public: 59 | ProbDropQueue( 60 | uint32_t id, 61 | double rate, 62 | uint32_t limit_bytes, 63 | double drop_prob, 64 | int location 65 | ); 66 | virtual void enque(Packet *packet); 67 | 68 | double drop_prob; 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /coresim/random_variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "random_variable.h" 12 | 13 | using namespace std; 14 | 15 | /* Uniform Random Variable 16 | */ 17 | UniformRandomVariable::UniformRandomVariable() { 18 | min_ = 0.0; 19 | max_ = 1.0; 20 | } 21 | 22 | UniformRandomVariable::UniformRandomVariable(double min, double max) { 23 | min_ = min; 24 | max_ = max; 25 | } 26 | 27 | double UniformRandomVariable::value() { // never return 0 28 | //double unif0_1 = (1.0 * rand() + 1.0) / (RAND_MAX* 1.0 + 1.0); 29 | double unif0_1 = (1.0 * rand()) / (RAND_MAX * 1.0); 30 | return min_ + (max_ - min_) * unif0_1; 31 | } 32 | 33 | 34 | 35 | /* Exponential Random Variable 36 | */ 37 | ExponentialRandomVariable::ExponentialRandomVariable(double avg) { 38 | avg_ = avg; 39 | urv = UniformRandomVariable(); 40 | 41 | } 42 | 43 | double ExponentialRandomVariable::value() { 44 | return -1.0 * avg_ * log(urv.value()); 45 | } 46 | 47 | 48 | 49 | 50 | /* Empirical Random Variable with random interpolation 51 | * Ported from NS2 52 | */ 53 | EmpiricalRandomVariable::EmpiricalRandomVariable(std::string filename, bool smooth) { 54 | this->smooth = smooth; 55 | minCDF_ = 0; 56 | maxCDF_ = 1; 57 | maxEntry_ = 65536; 58 | table_ = new CDFentry[maxEntry_]; 59 | if(filename != "") 60 | loadCDF(filename); 61 | } 62 | 63 | double EmpiricalRandomVariable::value() { 64 | if (numEntry_ <= 0) 65 | return 0; 66 | double u = (1.0 * rand()) / RAND_MAX; 67 | int mid = lookup(u); 68 | if (mid && u < table_[mid].cdf_) 69 | return interpolate(u, table_[mid-1].cdf_, table_[mid-1].val_, 70 | table_[mid].cdf_, table_[mid].val_); 71 | return table_[mid].val_; 72 | } 73 | 74 | double EmpiricalRandomVariable::interpolate(double x, double x1, double y1, 75 | double x2, double y2) { 76 | double value = y1 + (x - x1) * (y2 - y1) / (x2 - x1); 77 | return value; 78 | } 79 | 80 | int EmpiricalRandomVariable::lookup(double u) { 81 | // always return an index whose value is >= u 82 | int lo, hi, mid; 83 | if (u <= table_[0].cdf_) 84 | return 0; 85 | for (lo=1, hi=numEntry_-1; lo < hi; ) { 86 | mid = (lo + hi) / 2; 87 | if (u > table_[mid].cdf_) 88 | lo = mid + 1; 89 | else 90 | hi = mid; 91 | } 92 | return lo; 93 | } 94 | 95 | int EmpiricalRandomVariable::loadCDF(std::string filename) { 96 | assert(false); 97 | std::string line; 98 | std::ifstream myfile(filename); 99 | assert(myfile.good()); 100 | numEntry_ = 0; 101 | double prev_cd = 0; 102 | int prev_sz = 1; 103 | double w_sum = 0; 104 | while (std::getline(myfile, line)) 105 | { 106 | std::istringstream is(line); 107 | is >> table_[numEntry_].val_; 108 | is >> table_[numEntry_].cdf_; 109 | is >> table_[numEntry_].cdf_; 110 | 111 | double freq = table_[numEntry_].cdf_ - prev_cd; 112 | double flow_sz = this->smooth?(table_[numEntry_].val_ + prev_sz)/2.0:table_[numEntry_].val_; 113 | assert(freq >= 0); 114 | w_sum += freq * flow_sz; 115 | prev_cd = table_[numEntry_].cdf_; 116 | prev_sz = table_[numEntry_].val_; 117 | numEntry_ ++; 118 | } 119 | this->mean_flow_size = w_sum * 1460.0; 120 | //std::cout << "Mean flow size derived from CDF file:" << this->mean_flow_size << " smooth = " << this->smooth << "\n"; 121 | //std::cout << "Number of lines in text file: " << numEntry_ << "\n"; 122 | if (myfile.is_open()) { 123 | myfile.close(); 124 | } 125 | return numEntry_; 126 | } 127 | 128 | 129 | EmpiricalBytesRandomVariable::EmpiricalBytesRandomVariable(std::string filename, bool smooth) : EmpiricalRandomVariable("", smooth) { 130 | if(filename != "") 131 | loadCDF(filename); 132 | } 133 | 134 | int EmpiricalBytesRandomVariable::loadCDF(std::string filename) { 135 | std::string line; 136 | std::ifstream myfile(filename); 137 | assert(myfile.good()); 138 | numEntry_ = 0; 139 | double prev_cd = 0; 140 | int prev_sz = 1; 141 | double w_sum = 0; 142 | this->sizeWithHeader = 0.0; 143 | while (std::getline(myfile, line)) { 144 | std::istringstream is(line); 145 | is >> table_[numEntry_].val_; 146 | is >> table_[numEntry_].cdf_; 147 | is >> table_[numEntry_].cdf_; 148 | 149 | double freq = table_[numEntry_].cdf_ - prev_cd; 150 | double flow_sz = this->smooth?(table_[numEntry_].val_ + prev_sz)/2.0:table_[numEntry_].val_; 151 | assert(freq >= 0); 152 | double num_pkts = std::ceil(flow_sz / 1460); 153 | double tot = 40 * num_pkts + flow_sz; 154 | sizeWithHeader += freq * tot; 155 | w_sum += freq * flow_sz; 156 | prev_cd = table_[numEntry_].cdf_; 157 | prev_sz = table_[numEntry_].val_; 158 | numEntry_ ++; 159 | } 160 | this->mean_flow_size = w_sum; 161 | if (myfile.is_open()) { 162 | myfile.close(); 163 | } 164 | return numEntry_; 165 | } 166 | 167 | 168 | NAryRandomVariable::NAryRandomVariable(std::string filename) 169 | : EmpiricalRandomVariable(filename) { 170 | loadSizes(filename); 171 | } 172 | 173 | int NAryRandomVariable::loadSizes(std::string filename) { 174 | std::string line; 175 | std::ifstream myfile(filename); 176 | double temp; 177 | while (std::getline(myfile, line)) { 178 | std::istringstream is(line); 179 | is >> temp; 180 | this->flowSizes.push_back(temp); 181 | } 182 | return this->flowSizes.size(); 183 | } 184 | 185 | double NAryRandomVariable::value() { 186 | return this->flowSizes[rand() % this->flowSizes.size()]; 187 | } 188 | 189 | CDFRandomVariable::CDFRandomVariable(std::string filename) 190 | : EmpiricalRandomVariable(filename, false) {} 191 | 192 | double CDFRandomVariable::value() { 193 | double val = static_cast (rand()) / static_cast (RAND_MAX); 194 | // std::cout << "randval " << val << " "; 195 | for (int i = 0; i < numEntry_; i++) { 196 | // std::cout << " cdf " << table_[i].cdf_ << " " << table_[i].val_ << " "; 197 | if (val <= table_[i].cdf_) { 198 | // std::cout << " found\n"; 199 | return table_[i].val_; 200 | } 201 | } 202 | // std::cout << " notfound " << table_[numEntry_-1].cdf_ << " " << table_[numEntry_-1].val_ << "\n"; 203 | return table_[numEntry_-1].val_; 204 | } 205 | 206 | 207 | ConstantVariable::ConstantVariable(double value) : EmpiricalRandomVariable("", false) 208 | { 209 | this->v = value; 210 | } 211 | 212 | double ConstantVariable::value() 213 | { 214 | return v; 215 | } 216 | 217 | GaussianRandomVariable::GaussianRandomVariable(double avg, double std) { 218 | this->avg = avg; 219 | this->std = std; 220 | 221 | distribution = new std::normal_distribution(avg,std); 222 | } 223 | 224 | double GaussianRandomVariable::value() { 225 | return (*distribution)(generator); 226 | } 227 | -------------------------------------------------------------------------------- /coresim/random_variable.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_VARIABLE_H 2 | #define RANDOM_VARIABLE_H 3 | 4 | #include 5 | #include 6 | 7 | class RandomVariable { 8 | public: 9 | virtual double value() = 0; 10 | }; 11 | 12 | class UniformRandomVariable : public RandomVariable { 13 | public: 14 | virtual double value(); 15 | UniformRandomVariable(); 16 | UniformRandomVariable(double min, double max); 17 | double min_; 18 | double max_; 19 | }; 20 | 21 | 22 | class ExponentialRandomVariable : public RandomVariable { 23 | public: 24 | virtual double value(); 25 | ExponentialRandomVariable(double avg); 26 | double avg_; 27 | UniformRandomVariable urv; 28 | }; 29 | 30 | 31 | 32 | struct CDFentry { 33 | double cdf_; 34 | double val_; 35 | }; 36 | 37 | 38 | // READ VALUE IN PACKETS!! 39 | class EmpiricalRandomVariable : public RandomVariable { 40 | public: 41 | virtual double value(); 42 | double interpolate(double u, double x1, double y1, double x2, double y2); 43 | 44 | EmpiricalRandomVariable(std::string filename, bool smooth = true); 45 | int loadCDF(std::string filename); 46 | 47 | double mean_flow_size; 48 | 49 | bool smooth; 50 | 51 | protected: 52 | int lookup(double u); 53 | 54 | double minCDF_; // min value of the CDF (default to 0) 55 | double maxCDF_; // max value of the CDF (default to 1) 56 | int numEntry_; // number of entries in the CDF table 57 | int maxEntry_; // size of the CDF table (mem allocation) 58 | CDFentry* table_; // CDF table of (val_, cdf_) 59 | }; 60 | 61 | // READ VALUE IN BYTES 62 | class EmpiricalBytesRandomVariable : public EmpiricalRandomVariable { 63 | public: 64 | EmpiricalBytesRandomVariable(std::string filename, bool smooth = true); 65 | int loadCDF(std::string filename); 66 | 67 | double sizeWithHeader; 68 | }; 69 | 70 | /* 71 | Inherits from EmpricialRandomVariable since they both do flow sizes 72 | This one doesn't interpolate and does uniform/bimodal/trimodal/etc 73 | distributions. 74 | Nice thing about inheriting is you don't have to rewrite 75 | FlowCreationForInitializationEvent to accept this. 76 | */ 77 | class NAryRandomVariable : public EmpiricalRandomVariable { 78 | public: 79 | virtual double value(); 80 | NAryRandomVariable(std::string filename); 81 | int loadSizes(std::string filename); 82 | 83 | protected: 84 | std::vector flowSizes; 85 | }; 86 | 87 | class CDFRandomVariable : public EmpiricalRandomVariable { 88 | public: 89 | CDFRandomVariable(std::string filename); 90 | virtual double value(); 91 | }; 92 | 93 | class ConstantVariable : public EmpiricalRandomVariable { 94 | public: 95 | double v; 96 | ConstantVariable(double value); 97 | double value(); 98 | }; 99 | 100 | class GaussianRandomVariable{ 101 | public: 102 | double value(); 103 | GaussianRandomVariable(double avg, double std); 104 | double avg; 105 | double std; 106 | 107 | std::default_random_engine generator; 108 | std::normal_distribution *distribution; 109 | }; 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /coresim/topology.cpp: -------------------------------------------------------------------------------- 1 | #include "topology.h" 2 | 3 | extern DCExpParams params; 4 | 5 | /* 6 | uint32_t num_hosts = 144; 7 | uint32_t num_agg_switches = 9; 8 | uint32_t num_core_switches = 4; 9 | */ 10 | Topology::Topology() {} 11 | 12 | /* 13 | * PFabric topology with 144 hosts (16, 9, 4) 14 | */ 15 | PFabricTopology::PFabricTopology( 16 | uint32_t num_hosts, 17 | uint32_t num_agg_switches, 18 | uint32_t num_core_switches, 19 | double bandwidth, 20 | uint32_t queue_type 21 | ) : Topology () { 22 | uint32_t hosts_per_agg_switch = num_hosts / num_agg_switches; 23 | 24 | this->num_hosts = num_hosts; 25 | this->num_agg_switches = num_agg_switches; 26 | this->num_core_switches = num_core_switches; 27 | 28 | //Capacities 29 | double c1 = bandwidth; 30 | double c2 = hosts_per_agg_switch * bandwidth / num_core_switches; 31 | 32 | // Create Hosts 33 | for (uint32_t i = 0; i < num_hosts; i++) { 34 | hosts.push_back(Factory::get_host(i, c1, queue_type, params.host_type)); 35 | } 36 | 37 | // Create Switches 38 | for (uint32_t i = 0; i < num_agg_switches; i++) { 39 | AggSwitch* sw = new AggSwitch(i, hosts_per_agg_switch, c1, num_core_switches, c2, queue_type); 40 | agg_switches.push_back(sw); // TODO make generic 41 | switches.push_back(sw); 42 | } 43 | for (uint32_t i = 0; i < num_core_switches; i++) { 44 | CoreSwitch* sw = new CoreSwitch(i + num_agg_switches, num_agg_switches, c2, queue_type); 45 | core_switches.push_back(sw); 46 | switches.push_back(sw); 47 | } 48 | 49 | //Connect host queues 50 | for (uint32_t i = 0; i < num_hosts; i++) { 51 | hosts[i]->queue->set_src_dst(hosts[i], agg_switches[i/16]); 52 | //std::cout << "Linking Host " << i << " to Agg " << i/16 << "\n"; 53 | } 54 | 55 | // For agg switches -- REMAINING 56 | for (uint32_t i = 0; i < num_agg_switches; i++) { 57 | // Queues to Hosts 58 | for (uint32_t j = 0; j < hosts_per_agg_switch; j++) { // TODO make generic 59 | Queue *q = agg_switches[i]->queues[j]; 60 | q->set_src_dst(agg_switches[i], hosts[i * 16 + j]); 61 | //std::cout << "Linking Agg " << i << " to Host" << i * 16 + j << "\n"; 62 | } 63 | // Queues to Core 64 | for (uint32_t j = 0; j < num_core_switches; j++) { 65 | Queue *q = agg_switches[i]->queues[j + 16]; 66 | q->set_src_dst(agg_switches[i], core_switches[j]); 67 | //std::cout << "Linking Agg " << i << " to Core" << j << "\n"; 68 | } 69 | } 70 | 71 | //For core switches -- PERFECT 72 | for (uint32_t i = 0; i < num_core_switches; i++) { 73 | for (uint32_t j = 0; j < num_agg_switches; j++) { 74 | Queue *q = core_switches[i]->queues[j]; 75 | q->set_src_dst(core_switches[i], agg_switches[j]); 76 | //std::cout << "Linking Core " << i << " to Agg" << j << "\n"; 77 | } 78 | } 79 | } 80 | 81 | 82 | Queue *PFabricTopology::get_next_hop(Packet *p, Queue *q) { 83 | if (q->dst->type == HOST) { 84 | return NULL; // Packet Arrival 85 | } 86 | 87 | // At host level 88 | if (q->src->type == HOST) { // Same Rack or not 89 | assert (p->src->id == q->src->id); 90 | 91 | if (p->src->id / 16 == p->dst->id / 16) { 92 | return ((Switch *) q->dst)->queues[p->dst->id % 16]; 93 | } 94 | else { 95 | uint32_t hash_port = 0; 96 | if(params.load_balancing == 0) 97 | hash_port = q->spray_counter++%4; 98 | else if(params.load_balancing == 1) 99 | hash_port = (p->src->id + p->dst->id + p->flow->id) % 4; 100 | return ((Switch *) q->dst)->queues[16 + hash_port]; 101 | } 102 | } 103 | 104 | // At switch level 105 | if (q->src->type == SWITCH) { 106 | if (((Switch *) q->src)->switch_type == AGG_SWITCH) { 107 | return ((Switch *) q->dst)->queues[p->dst->id / 16]; 108 | } 109 | if (((Switch *) q->src)->switch_type == CORE_SWITCH) { 110 | return ((Switch *) q->dst)->queues[p->dst->id % 16]; 111 | } 112 | } 113 | 114 | assert(false); 115 | } 116 | 117 | 118 | double PFabricTopology::get_oracle_fct(Flow *f) { 119 | int num_hops = 4; 120 | if (f->src->id/16 == f->dst->id/16) { 121 | num_hops = 2; 122 | } 123 | double propagation_delay; 124 | if (params.ddc != 0) { 125 | if (num_hops == 2) { 126 | propagation_delay = 0.440; 127 | } 128 | if (num_hops == 4) { 129 | propagation_delay = 2.040; 130 | } 131 | } 132 | else { 133 | propagation_delay = 2 * 1000000.0 * num_hops * f->src->queue->propagation_delay; //us 134 | } 135 | 136 | double pkts = (double) f->size / params.mss; 137 | uint32_t np = floor(pkts); 138 | uint32_t leftover = (pkts - np) * params.mss; 139 | double incl_overhead_bytes = (params.mss + f->hdr_size) * np + (leftover + f->hdr_size); 140 | 141 | double bandwidth = f->src->queue->rate / 1000000.0; // For us 142 | double transmission_delay; 143 | if (params.cut_through) { 144 | transmission_delay = 145 | ( 146 | np * (params.mss + params.hdr_size) 147 | + 1 * params.hdr_size 148 | + 2.0 * params.hdr_size // ACK has to travel two hops 149 | ) * 8.0 / bandwidth; 150 | if (num_hops == 4) { 151 | //1 packet and 1 ack 152 | transmission_delay += 2 * (2*params.hdr_size) * 8.0 / (4 * bandwidth); 153 | } 154 | //std::cout << "pd: " << propagation_delay << " td: " << transmission_delay << std::endl; 155 | } 156 | else { 157 | transmission_delay = (incl_overhead_bytes + 2.0 * f->hdr_size) * 8.0 / bandwidth; 158 | if (num_hops == 4) { 159 | // 1 packet and 1 ack 160 | if (np == 0) { 161 | // less than mss sized flow. the 1 packet is leftover sized. 162 | transmission_delay += 2 * (leftover + 2*params.hdr_size) * 8.0 / (4 * bandwidth); 163 | 164 | } else { 165 | // 1 packet is full sized 166 | transmission_delay += 2 * (params.mss + 2*params.hdr_size) * 8.0 / (4 * bandwidth); 167 | } 168 | } 169 | //transmission_delay = 170 | // ( 171 | // (np + 1) * (params.mss + params.hdr_size) + (leftover + params.hdr_size) 172 | // + 2.0 * params.hdr_size // ACK has to travel two hops 173 | // ) * 8.0 / bandwidth; 174 | //if (num_hops == 4) { 175 | // //1 packet and 1 ack 176 | // transmission_delay += 2 * (params.mss + 2*params.hdr_size) * 8.0 / (4 * bandwidth); //TODO: 4 * bw is not right. 177 | //} 178 | } 179 | return (propagation_delay + transmission_delay); //us 180 | } 181 | 182 | 183 | /* 184 | *BigSwitchTopology with 144 hosts 185 | */ 186 | BigSwitchTopology::BigSwitchTopology( 187 | uint32_t num_hosts, 188 | double bandwidth, 189 | uint32_t queue_type 190 | ) : Topology () { 191 | this->num_hosts = num_hosts; 192 | double c1 = bandwidth; 193 | 194 | // Create Hosts 195 | for (uint32_t i = 0; i < num_hosts; i++) { 196 | hosts.push_back(Factory::get_host(i, c1, queue_type, params.host_type)); 197 | } 198 | 199 | the_switch = new CoreSwitch(0, num_hosts, c1, queue_type); 200 | this->switches.push_back(the_switch); 201 | 202 | assert(this->switches.size() == 1); 203 | 204 | //Connect host queues 205 | for (uint32_t i = 0; i < num_hosts; i++) { 206 | hosts[i]->queue->set_src_dst(hosts[i], the_switch); 207 | Queue *q = the_switch->queues[i]; 208 | q->set_src_dst(the_switch, hosts[i]); 209 | } 210 | } 211 | 212 | Queue* BigSwitchTopology::get_next_hop(Packet *p, Queue *q) { 213 | if (q->dst->type == HOST) { 214 | assert(p->dst->id == q->dst->id); 215 | return NULL; // Packet Arrival 216 | } 217 | 218 | // At host level 219 | if (q->src->type == HOST) { // Same Rack or not 220 | assert (p->src->id == q->src->id); 221 | return the_switch->queues[p->dst->id]; 222 | } 223 | 224 | assert(false); 225 | } 226 | 227 | double BigSwitchTopology::get_oracle_fct(Flow *f) { 228 | double propagation_delay = 2 * 1000000.0 * 2 * f->src->queue->propagation_delay; //us 229 | 230 | uint32_t np = ceil(f->size / params.mss); // TODO: Must be a multiple of 1460 231 | double bandwidth = f->src->queue->rate / 1000000.0; // For us 232 | double transmission_delay; 233 | if (params.cut_through) { 234 | transmission_delay = 235 | ( 236 | np * (params.mss + params.hdr_size) 237 | + 1 * params.hdr_size 238 | + 2.0 * params.hdr_size // ACK has to travel two hops 239 | ) * 8.0 / bandwidth; 240 | } 241 | else { 242 | transmission_delay = ((np + 1) * (params.mss + params.hdr_size) 243 | + 2.0 * params.hdr_size) // ACK has to travel two hops 244 | * 8.0 / bandwidth; 245 | } 246 | return (propagation_delay + transmission_delay); //us 247 | } 248 | 249 | -------------------------------------------------------------------------------- /coresim/topology.h: -------------------------------------------------------------------------------- 1 | #ifndef TOPOLOGY_H 2 | #define TOPOLOGY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "node.h" 10 | #include "assert.h" 11 | #include "packet.h" 12 | #include "queue.h" 13 | 14 | #include "../ext/factory.h" 15 | 16 | #include "../run/params.h" 17 | 18 | class Topology { 19 | public: 20 | Topology(); 21 | virtual Queue *get_next_hop(Packet *p, Queue *q) = 0; 22 | virtual double get_oracle_fct(Flow* f) = 0; 23 | 24 | uint32_t num_hosts; 25 | 26 | std::vector hosts; 27 | std::vector switches; 28 | }; 29 | 30 | class PFabricTopology : public Topology { 31 | public: 32 | PFabricTopology( 33 | uint32_t num_hosts, 34 | uint32_t num_agg_switches, 35 | uint32_t num_core_switches, 36 | double bandwidth, 37 | uint32_t queue_type 38 | ); 39 | 40 | virtual Queue* get_next_hop(Packet *p, Queue *q); 41 | virtual double get_oracle_fct(Flow* f); 42 | 43 | uint32_t num_agg_switches; 44 | uint32_t num_core_switches; 45 | 46 | std::vector agg_switches; 47 | std::vector core_switches; 48 | }; 49 | 50 | 51 | class BigSwitchTopology : public Topology { 52 | public: 53 | BigSwitchTopology(uint32_t num_hosts, double bandwidth, uint32_t queue_type); 54 | virtual Queue *get_next_hop(Packet *p, Queue *q); 55 | virtual double get_oracle_fct(Flow* f); 56 | 57 | CoreSwitch* the_switch; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /ext/capabilityflow.cpp: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | 3 | #include "../coresim/event.h" 4 | #include "../coresim/packet.h" 5 | #include "../coresim/debug.h" 6 | 7 | #include "capabilityhost.h" 8 | #include "capabilityflow.h" 9 | 10 | #include "../run/params.h" 11 | 12 | extern double get_current_time(); 13 | extern void add_to_event_queue(Event*); 14 | extern DCExpParams params; 15 | extern uint32_t num_outstanding_packets; 16 | 17 | bool CapabilityComparator::operator() (Capability* a, Capability* b) 18 | { 19 | return a->timeout > b->timeout; 20 | } 21 | 22 | 23 | CapabilityFlow::CapabilityFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) 24 | : FountainFlow(id, start_time, size, s, d) { 25 | this->finished_at_receiver = false; 26 | this->capability_count = 0; 27 | this->redundancy_ctrl_timeout = -1; 28 | this->capability_goal = (int)(std::ceil(this->size_in_pkt * 1.00)); 29 | this->remaining_pkts_at_sender = this->size_in_pkt; 30 | this->largest_cap_seq_received = -1; 31 | this->total_queuing_time = 0; 32 | this->rts_received = false; 33 | this->latest_cap_sent_time = start_time; 34 | this->latest_data_pkt_send_time = start_time; 35 | this->capability_packet_sent_count = 0; 36 | this->capability_waste_count = 0; 37 | this->notified_num_flow_at_sender = 1; 38 | this->last_capa_data_seq_num_sent = -1; 39 | this->received_until = 0; 40 | this->received_count = 0; 41 | } 42 | 43 | 44 | void CapabilityFlow::start_flow() 45 | { 46 | assign_init_capability(); 47 | ((CapabilityHost*) this->src)->start_capability_flow(this); 48 | } 49 | 50 | 51 | void CapabilityFlow::send_pending_data() 52 | { 53 | int capa_data_seq = this->capabilities.top()->data_seq_num; 54 | int capa_seq = this->use_capability(); 55 | 56 | Packet *p; 57 | if (next_seq_no + mss <= this->size) { 58 | p = this->send(next_seq_no, capa_seq, capa_data_seq, params.capability_third_level && this->size_in_pkt > params.capability_prio_thresh?2:1); 59 | next_seq_no += mss; 60 | } else { 61 | p = this->send(next_seq_no, capa_seq, capa_data_seq, params.capability_third_level && this->size_in_pkt > params.capability_prio_thresh?2:1); 62 | next_seq_no = this->size; 63 | } 64 | 65 | if(debug_flow(this->id)) 66 | std::cout << get_current_time() << " flow " << this->id << " send pkt " << this->total_pkt_sent << " " << p->size << "\n"; 67 | 68 | double td = src->queue->get_transmission_delay(p->size); 69 | assert(((SchedulingHost*) src)->host_proc_event == NULL); 70 | ((SchedulingHost*) src)->host_proc_event = new HostProcessingEvent(get_current_time() + td + INFINITESIMAL_TIME, (SchedulingHost*) src); 71 | add_to_event_queue(((SchedulingHost*) src)->host_proc_event); 72 | } 73 | 74 | 75 | void CapabilityFlow::send_pending_data_low_prio() 76 | { 77 | assert(false); 78 | Packet *p = this->send(this->next_seq_no, -1, -1, 9); 79 | next_seq_no += mss; 80 | if(debug_flow(this->id)) 81 | std::cout << get_current_time() << " flow " << this->id << " send pkt " << this->total_pkt_sent << "\n"; 82 | 83 | double td = src->queue->get_transmission_delay(p->size); 84 | assert(((SchedulingHost*) src)->host_proc_event == NULL); 85 | ((SchedulingHost*) src)->host_proc_event = new HostProcessingEvent(get_current_time() + td + INFINITESIMAL_TIME, (SchedulingHost*) src); 86 | add_to_event_queue(((SchedulingHost*) src)->host_proc_event); 87 | } 88 | 89 | void CapabilityFlow::receive_rts(Packet* p) { 90 | if(debug_flow(p->flow->id)) 91 | std::cout << get_current_time() << " received RTS for flow " << p->flow->id << "\n"; 92 | 93 | this->rts_received = true; 94 | set_capability_count(); 95 | ((CapabilityHost*)(this->dst))->hold_on = this->init_capa_size(); 96 | ((CapabilityHost*)(this->dst))->active_receiving_flows.push(this); 97 | 98 | if( ((CapabilityHost*)(this->dst))->capa_proc_evt && 99 | ((CapabilityHost*)(this->dst))->capa_proc_evt->is_timeout_evt 100 | ) 101 | { 102 | ((CapabilityHost*)(this->dst))->capa_proc_evt->cancelled = true; 103 | ((CapabilityHost*)(this->dst))->capa_proc_evt = NULL; 104 | } 105 | 106 | if(((CapabilityHost*)(this->dst))->capa_proc_evt == NULL){ 107 | ((CapabilityHost*)(this->dst))->schedule_capa_proc_evt(0, false); 108 | } 109 | } 110 | 111 | void CapabilityFlow::receive(Packet *p) 112 | { 113 | if(this->finished) { 114 | delete p; 115 | return; 116 | } 117 | 118 | if(p->type == NORMAL_PACKET) 119 | { 120 | if (this->first_byte_receive_time == -1) { 121 | this->first_byte_receive_time = get_current_time(); 122 | } 123 | 124 | if (!rts_received) { 125 | receive_rts(p); 126 | } 127 | 128 | if(packets_received.count(p->capa_data_seq) == 0){ 129 | packets_received.insert(p->capa_data_seq); 130 | received_count++; 131 | while(received_until < size_in_pkt && packets_received.count(received_until) > 0) 132 | { 133 | received_until++; 134 | } 135 | } 136 | 137 | received_bytes += (p->size - hdr_size); 138 | if(num_outstanding_packets >= ((p->size - hdr_size) / (mss))) 139 | num_outstanding_packets -= ((p->size - hdr_size) / (mss)); 140 | else 141 | num_outstanding_packets = 0; 142 | total_queuing_time += p->total_queuing_delay; 143 | if(p->capability_seq_num_in_data > largest_cap_seq_received) 144 | largest_cap_seq_received = p->capability_seq_num_in_data; 145 | // if(debug_flow(this->id)) 146 | // std::cout << get_current_time() << " flow " << this->id << " received pkt " << received_count << "\n"; 147 | if (received_count >= goal) { 148 | this->finished_at_receiver = true; 149 | send_ack(); 150 | if(debug_flow(this->id)) 151 | std::cout << get_current_time() << " flow " << this->id << " send ACK \n"; 152 | } 153 | } 154 | else if(p->type == ACK_PACKET) 155 | { 156 | if(debug_flow(this->id)) 157 | std::cout << get_current_time() << " flow " << this->id << " received ack\n"; 158 | add_to_event_queue(new FlowFinishedEvent(get_current_time(), this)); 159 | } 160 | else if(p->type == CAPABILITY_PACKET) 161 | { 162 | Capability* c = new Capability(); 163 | if(CAPABILITY_MEASURE_WASTE) 164 | { 165 | if(this->has_sibling_idle_source()) 166 | c->has_idle_sibling_sender = true; 167 | else 168 | c->has_idle_sibling_sender = false; 169 | } 170 | c->timeout = get_current_time() + ((CapabilityPkt*)p)->ttl; 171 | c->seq_num = ((CapabilityPkt*)p)->cap_seq_num; 172 | c->data_seq_num = ((CapabilityPkt*)p)->data_seq_num; 173 | this->capabilities.push(c); 174 | this->remaining_pkts_at_sender = ((CapabilityPkt*)p)->remaining_sz; 175 | 176 | if(((CapabilityHost*)(this->src))->host_proc_event == NULL) 177 | { 178 | ((CapabilityHost*)(this->src))->schedule_host_proc_evt(); 179 | } 180 | } 181 | else if(p->type == RTS_PACKET) 182 | { 183 | if (!rts_received) { 184 | this->receive_rts(p); 185 | } 186 | } 187 | else if(p->type == STATUS_PACKET) 188 | { 189 | if(CAPABILITY_NOTIFY_BLOCKING){ 190 | StatusPkt* s = (StatusPkt*) p; 191 | this->notified_num_flow_at_sender = s->num_flows_at_sender; 192 | } 193 | 194 | } 195 | delete p; 196 | } 197 | 198 | bool CapabilityFlow::has_sibling_idle_source() 199 | { 200 | bool has_idle = false; 201 | CapabilityHost* dst = (CapabilityHost*)this->dst; 202 | std::queue flows_tried; 203 | while(!dst->active_receiving_flows.empty()) 204 | { 205 | CapabilityFlow* f = dst->active_receiving_flows.top(); 206 | dst->active_receiving_flows.pop(); 207 | flows_tried.push(f); 208 | if(f != this && f->redundancy_ctrl_timeout <= get_current_time() 209 | && ((CapabilityHost*)(f->src))->is_sender_idle()) 210 | { 211 | has_idle = true; 212 | break; 213 | } 214 | 215 | } 216 | 217 | while(!flows_tried.empty()) 218 | { 219 | dst->active_receiving_flows.push(flows_tried.front()); 220 | flows_tried.pop(); 221 | } 222 | 223 | return has_idle; 224 | } 225 | 226 | Packet* CapabilityFlow::send(uint32_t seq, int capa_seq, int data_seq, int priority) 227 | { 228 | this->latest_data_pkt_send_time = get_current_time(); 229 | 230 | uint32_t pkt_size; 231 | if (seq + mss > this->size) { 232 | pkt_size = hdr_size + (this->size - seq); 233 | } else { 234 | pkt_size = hdr_size + mss; 235 | } 236 | 237 | Packet *p = new Packet(get_current_time(), this, seq, priority, pkt_size, src, dst); 238 | p->capability_seq_num_in_data = capa_seq; 239 | p->capa_data_seq = data_seq; 240 | total_pkt_sent++; 241 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, src->queue)); 242 | return p; 243 | } 244 | 245 | 246 | void CapabilityFlow::assign_init_capability(){ 247 | //sender side 248 | int init_capa = this->init_capa_size(); 249 | for(int i = 0; i < init_capa; i++){ 250 | Capability* c = new Capability(); 251 | c->timeout = get_current_time() + init_capa * params.get_full_pkt_tran_delay() + params.capability_timeout * params.get_full_pkt_tran_delay(); 252 | c->seq_num = i; 253 | c->data_seq_num = i; 254 | this->capabilities.push(c); 255 | } 256 | } 257 | 258 | 259 | void CapabilityFlow::set_capability_count(){ 260 | int init_capa = this->init_capa_size(); 261 | this->capability_count = init_capa; 262 | this->last_capa_data_seq_num_sent = init_capa - 1; 263 | if(this->capability_count == this->capability_goal){ 264 | this->redundancy_ctrl_timeout = get_current_time() + init_capa * params.get_full_pkt_tran_delay() * 2; 265 | } 266 | } 267 | 268 | 269 | int CapabilityFlow::get_next_capa_seq_num() 270 | { 271 | int count = 0; 272 | int data_seq = (last_capa_data_seq_num_sent + 1)%this->size_in_pkt; 273 | while(count < this->size_in_pkt) 274 | { 275 | if(packets_received.count(data_seq) == 0) 276 | { 277 | assert(data_seq >= 0 && data_seq < size_in_pkt); 278 | return data_seq; 279 | } 280 | else 281 | { 282 | data_seq++; 283 | if(data_seq >= size_in_pkt) 284 | { 285 | data_seq = received_until; 286 | } 287 | 288 | } 289 | count++; 290 | } 291 | assert(false); 292 | } 293 | 294 | void CapabilityFlow::send_capability_pkt(){ 295 | if(debug_flow(this->id)) 296 | std::cout << get_current_time() << " flow " << this->id << " send capa " << this->capability_count << "\n"; 297 | int data_seq_num = this->get_next_capa_seq_num(); 298 | last_capa_data_seq_num_sent = data_seq_num; 299 | CapabilityPkt* cp = new CapabilityPkt(this, this->dst, this->src, params.capability_timeout * params.get_full_pkt_tran_delay(), this->remaining_pkts(), this->capability_count, data_seq_num); 300 | this->capability_count++; 301 | this->capability_packet_sent_count++; 302 | this->latest_cap_sent_time = get_current_time(); 303 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), cp, dst->queue)); 304 | } 305 | 306 | void CapabilityFlow::send_notify_pkt(int num_flows_at_sender){ 307 | if(debug_flow(this->id)) 308 | std::cout << get_current_time() << " flow " << this->id << " send notify " << num_flows_at_sender << "\n"; 309 | StatusPkt* cp = new StatusPkt(this, this->src, this->dst, num_flows_at_sender); 310 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), cp, src->queue)); 311 | } 312 | 313 | void CapabilityFlow::send_rts_pkt(){ 314 | RTS* rts = new RTS(this, this->src, this->dst, 0, 0); 315 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), rts, src->queue)); 316 | } 317 | 318 | bool CapabilityFlow::has_capability(){ 319 | while(!this->capabilities.empty()){ 320 | //expired capability 321 | if(this->capabilities.top()->timeout < get_current_time()) 322 | { 323 | if(CAPABILITY_MEASURE_WASTE){ 324 | this->capability_waste_count += this->capabilities.top()->has_idle_sibling_sender?1:0; 325 | } 326 | 327 | delete this->capabilities.top(); 328 | this->capabilities.pop(); 329 | } 330 | //not expired 331 | else 332 | { 333 | return true; 334 | } 335 | } 336 | return false; 337 | } 338 | 339 | int CapabilityFlow::use_capability(){ 340 | assert(!this->capabilities.empty() && this->capabilities.top()->timeout >= get_current_time()); 341 | int seq_num = this->capabilities.top()->seq_num; 342 | delete this->capabilities.top(); 343 | this->capabilities.pop(); 344 | return seq_num; 345 | } 346 | 347 | Capability* CapabilityFlow::top_capability() 348 | { 349 | assert(!this->capabilities.empty()); 350 | return this->capabilities.top(); 351 | } 352 | 353 | double CapabilityFlow::top_capability_timeout(){ 354 | if(this->has_capability()) 355 | return this->top_capability()->timeout; 356 | else 357 | return 999999; 358 | } 359 | 360 | int CapabilityFlow::remaining_pkts(){ 361 | return std::max((int)0, (int)(this->size_in_pkt - this->received_count)); 362 | } 363 | 364 | int CapabilityFlow::capability_gap(){ 365 | assert(this->capability_count - this->largest_cap_seq_received >= 0); 366 | return this->capability_count - this->largest_cap_seq_received; 367 | } 368 | 369 | void CapabilityFlow::relax_capability_gap() 370 | { 371 | assert(this->capability_count - this->largest_cap_seq_received >= 0); 372 | this->largest_cap_seq_received = this->capability_count - params.capability_window; 373 | } 374 | 375 | int CapabilityFlow::init_capa_size(){ 376 | return this->size_in_pkt <= params.capability_initial?this->size_in_pkt:0; 377 | } 378 | 379 | 380 | -------------------------------------------------------------------------------- /ext/capabilityflow.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPABILITY_FLOW_H 2 | #define CAPABILITY_FLOW_H 3 | 4 | #include 5 | #include 6 | 7 | #include "fountainflow.h" 8 | #include "custompriorityqueue.h" 9 | 10 | struct Capability //for extendability 11 | { 12 | double timeout; 13 | int seq_num; 14 | bool has_idle_sibling_sender; 15 | int data_seq_num; 16 | }; 17 | 18 | class CapabilityComparator{ 19 | public: 20 | bool operator() (Capability* a, Capability* b); 21 | }; 22 | 23 | 24 | class CapabilityFlow : public FountainFlow { 25 | public: 26 | CapabilityFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 27 | virtual void start_flow(); 28 | virtual void send_pending_data(); 29 | void receive_rts(Packet *p); 30 | virtual void receive(Packet *p); 31 | void send_pending_data_low_prio(); 32 | Packet* send(uint32_t seq, int capa_seq, int data_seq, int priority); 33 | void send_capability_pkt(); 34 | void send_notify_pkt(int); 35 | void send_rts_pkt(); 36 | bool has_capability(); 37 | int use_capability(); 38 | Capability* top_capability(); 39 | double top_capability_timeout(); 40 | int remaining_pkts(); 41 | void assign_init_capability(); 42 | void set_capability_count(); 43 | int capability_gap(); 44 | void relax_capability_gap(); 45 | int init_capa_size(); 46 | bool has_sibling_idle_source(); 47 | int get_next_capa_seq_num(); 48 | 49 | std::priority_queue, CapabilityComparator> capabilities; 50 | std::set packets_received; 51 | int last_capa_data_seq_num_sent; 52 | int received_until; 53 | bool finished_at_receiver; 54 | int capability_count; 55 | int capability_packet_sent_count; 56 | int capability_waste_count; 57 | double redundancy_ctrl_timeout; 58 | int capability_goal; 59 | int remaining_pkts_at_sender; 60 | int largest_cap_seq_received; 61 | double latest_cap_sent_time; 62 | bool rts_received; 63 | double latest_data_pkt_send_time; 64 | int notified_num_flow_at_sender; 65 | }; 66 | 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /ext/capabilityhost.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../coresim/event.h" 5 | #include "../coresim/flow.h" 6 | #include "../coresim/packet.h" 7 | #include "../coresim/debug.h" 8 | 9 | #include "capabilityflow.h" 10 | #include "capabilityhost.h" 11 | #include "factory.h" 12 | 13 | #include "../run/params.h" 14 | 15 | extern double get_current_time(); 16 | extern void add_to_event_queue(Event*); 17 | extern DCExpParams params; 18 | 19 | CapabilityProcessingEvent::CapabilityProcessingEvent(double time, CapabilityHost *h, bool is_timeout) 20 | : Event(CAPABILITY_PROCESSING, time) { 21 | this->host = h; 22 | this->is_timeout_evt = is_timeout; 23 | } 24 | 25 | CapabilityProcessingEvent::~CapabilityProcessingEvent() { 26 | if (host->capa_proc_evt == this) { 27 | host->capa_proc_evt = NULL; 28 | } 29 | } 30 | 31 | void CapabilityProcessingEvent::process_event() { 32 | this->host->capa_proc_evt = NULL; 33 | this->host->send_capability(); 34 | } 35 | 36 | SenderNotifyEvent::SenderNotifyEvent(double time, CapabilityHost* h) : Event(SENDER_NOTIFY, time) { 37 | this->host = h; 38 | } 39 | 40 | SenderNotifyEvent::~SenderNotifyEvent() { 41 | } 42 | 43 | void SenderNotifyEvent::process_event() { 44 | this->host->sender_notify_evt = NULL; 45 | this->host->notify_flow_status(); 46 | } 47 | 48 | bool CapabilityFlowComparator::operator() (CapabilityFlow* a, CapabilityFlow* b){ 49 | //return a->remaining_pkts_at_sender > b->remaining_pkts_at_sender; 50 | if(params.deadline && params.schedule_by_deadline) { 51 | return a->deadline > b->deadline; 52 | } 53 | else { 54 | if (a->remaining_pkts_at_sender > b->remaining_pkts_at_sender) 55 | return true; 56 | else if (a->remaining_pkts_at_sender == b->remaining_pkts_at_sender) 57 | return a->start_time > b->start_time; 58 | else 59 | return false; 60 | //return a->latest_data_pkt_send_time > b->latest_data_pkt_send_time; 61 | //return a->start_time > b->start_time; 62 | } 63 | } 64 | 65 | bool CapabilityFlowComparatorAtReceiver::operator() (CapabilityFlow* a, CapabilityFlow* b){ 66 | //return a->size_in_pkt > b->size_in_pkt; 67 | if(params.deadline && params.schedule_by_deadline) { 68 | return a->deadline > b->deadline; 69 | } 70 | else { 71 | if (a->notified_num_flow_at_sender > b->notified_num_flow_at_sender) 72 | return true; 73 | else if(a->notified_num_flow_at_sender == b->notified_num_flow_at_sender) { 74 | if(a->remaining_pkts() > b->remaining_pkts()) 75 | return true; 76 | else if (a->remaining_pkts() == b->remaining_pkts()) 77 | return a->start_time > b->start_time; //TODO: this is cheating. but not a big problem 78 | else 79 | return false; 80 | } 81 | else 82 | return false; 83 | //return a->latest_cap_sent_time > b->latest_cap_sent_time; 84 | //return a->start_time > b->start_time; 85 | } 86 | } 87 | 88 | CapabilityHost::CapabilityHost(uint32_t id, double rate, uint32_t queue_type) : SchedulingHost(id, rate, queue_type) { 89 | this->capa_proc_evt = NULL; 90 | this->hold_on = 0; 91 | this->total_capa_schd_evt_count = 0; 92 | this->could_better_schd_count = 0; 93 | this->sender_notify_evt = NULL; 94 | this->host_type = CAPABILITY_HOST; 95 | } 96 | 97 | void CapabilityHost::start_capability_flow(CapabilityFlow* f) { 98 | if(debug_flow(f->id) || debug_host(this->id)) 99 | std::cout 100 | << get_current_time() 101 | << " flow " << f->id 102 | << " src " << this->id 103 | << " curr q size " << this->queue->bytes_in_queue 104 | << " num flows " << this->active_receiving_flows.size() <<"\n"; 105 | 106 | this->active_sending_flows.push(f); 107 | f->send_rts_pkt(); 108 | if(f->has_capability() && ((CapabilityHost*)(f->src))->host_proc_event == NULL) { 109 | ((CapabilityHost*)(f->src))->schedule_host_proc_evt(); 110 | } 111 | if(CAPABILITY_NOTIFY_BLOCKING && this->sender_notify_evt == NULL) 112 | this->notify_flow_status(); 113 | } 114 | 115 | void CapabilityHost::schedule_host_proc_evt(){ 116 | assert(this->host_proc_event == NULL); 117 | 118 | double qpe_time = 0; 119 | double td_time = 0; 120 | if(this->queue->busy){ 121 | qpe_time = this->queue->queue_proc_event->time; 122 | } 123 | else{ 124 | qpe_time = get_current_time(); 125 | } 126 | 127 | uint32_t queue_size = this->queue->bytes_in_queue; 128 | td_time = this->queue->get_transmission_delay(queue_size); 129 | 130 | this->host_proc_event = new HostProcessingEvent(qpe_time + td_time + INFINITESIMAL_TIME, this); 131 | add_to_event_queue(this->host_proc_event); 132 | } 133 | 134 | void CapabilityHost::schedule_capa_proc_evt(double time, bool is_timeout) 135 | { 136 | assert(this->capa_proc_evt == NULL); 137 | this->capa_proc_evt = new CapabilityProcessingEvent(get_current_time() + time + INFINITESIMAL_TIME, this, is_timeout); 138 | add_to_event_queue(this->capa_proc_evt); 139 | } 140 | 141 | void CapabilityHost::schedule_sender_notify_evt() 142 | { 143 | assert(this->sender_notify_evt == NULL); 144 | this->sender_notify_evt = new SenderNotifyEvent(get_current_time() + (params.get_full_pkt_tran_delay() * 20) + INFINITESIMAL_TIME, this); 145 | add_to_event_queue(this->sender_notify_evt); 146 | } 147 | 148 | 149 | //should only be called in HostProcessingEvent::process() 150 | void CapabilityHost::send(){ 151 | assert(this->host_proc_event == NULL); 152 | 153 | 154 | if(this->queue->busy) 155 | { 156 | schedule_host_proc_evt(); 157 | } 158 | else 159 | { 160 | bool pkt_sent = false; 161 | std::queue flows_tried; 162 | while(!this->active_sending_flows.empty()){ 163 | if(this->active_sending_flows.top()->finished){ 164 | this->active_sending_flows.pop(); 165 | continue; 166 | } 167 | 168 | CapabilityFlow* top_flow = this->active_sending_flows.top(); 169 | 170 | 171 | if(top_flow->has_capability()) 172 | { 173 | top_flow->send_pending_data(); 174 | pkt_sent = true; 175 | break; 176 | } 177 | else{ 178 | this->active_sending_flows.pop(); 179 | flows_tried.push(top_flow); 180 | } 181 | 182 | } 183 | 184 | //code for 4th priority level 185 | if(params.capability_fourth_level && !pkt_sent && flows_tried.size() > 0){ 186 | std::vector candidate; 187 | for(int i = 0; i < flows_tried.size(); i++){ 188 | if(flows_tried.front()->size_in_pkt > params.capability_initial) 189 | candidate.push_back(flows_tried.front()); 190 | } 191 | 192 | if(candidate.size()){ 193 | int f_index = rand()%candidate.size(); 194 | candidate[f_index]->send_pending_data_low_prio(); 195 | } 196 | 197 | } 198 | 199 | while(!flows_tried.empty()) 200 | { 201 | CapabilityFlow* f = flows_tried.front(); 202 | flows_tried.pop(); 203 | this->active_sending_flows.push(f); 204 | } 205 | 206 | } 207 | 208 | } 209 | 210 | void CapabilityHost::notify_flow_status() 211 | { 212 | std::queue flows_tried; 213 | int num_large_flow = 0; 214 | 215 | while(!this->active_sending_flows.empty()) 216 | { 217 | CapabilityFlow* f = this->active_sending_flows.top(); 218 | this->active_sending_flows.pop(); 219 | if(!f->finished){ 220 | flows_tried.push(f); 221 | if(f->size_in_pkt > params.capability_initial) 222 | num_large_flow++; 223 | } 224 | } 225 | 226 | while(!flows_tried.empty()){ 227 | this->active_sending_flows.push(flows_tried.front()); 228 | if(flows_tried.front()->size_in_pkt > params.capability_initial) 229 | flows_tried.front()->send_notify_pkt(num_large_flow>2?2:1); 230 | flows_tried.pop(); 231 | } 232 | 233 | if(!this->active_sending_flows.empty()) 234 | this->schedule_sender_notify_evt(); 235 | } 236 | 237 | bool CapabilityHost::check_better_schedule(CapabilityFlow* f) 238 | { 239 | return ((CapabilityHost*)f->src)->active_sending_flows.top() == f; 240 | } 241 | 242 | bool CapabilityHost::is_sender_idle(){ 243 | bool idle = true; 244 | std::queue flows_tried; 245 | while(!this->active_sending_flows.empty()) 246 | { 247 | CapabilityFlow* f = this->active_sending_flows.top(); 248 | this->active_sending_flows.pop(); 249 | flows_tried.push(f); 250 | if(f->has_capability()){ 251 | idle = false; 252 | break; 253 | } 254 | } 255 | while(!flows_tried.empty()) 256 | { 257 | this->active_sending_flows.push(flows_tried.front()); 258 | flows_tried.pop(); 259 | } 260 | 261 | return idle; 262 | } 263 | 264 | void CapabilityHost::send_capability(){ 265 | //if(debug_host(this->id)) 266 | // std::cout << get_current_time() << " CapabilityHost::send_capability() at host " << this->id << "\n"; 267 | assert(capa_proc_evt == NULL); 268 | 269 | bool capability_sent = false; 270 | bool could_schd_better = false; 271 | this->total_capa_schd_evt_count++; 272 | std::queue flows_tried; 273 | double closet_timeout = 999999; 274 | 275 | if(CAPABILITY_HOLD && this->hold_on > 0){ 276 | hold_on--; 277 | capability_sent = true; 278 | } 279 | 280 | while(!this->active_receiving_flows.empty() && !capability_sent) 281 | { 282 | CapabilityFlow* f = this->active_receiving_flows.top(); 283 | this->active_receiving_flows.pop(); 284 | //if(debug_flow(f->id)) 285 | // std::cout << get_current_time() << " pop out flow " << f->id << "\n"; 286 | 287 | 288 | if(f->finished_at_receiver) 289 | { 290 | continue; 291 | } 292 | flows_tried.push(f); 293 | 294 | //not yet timed out, shouldn't send 295 | if(f->redundancy_ctrl_timeout > get_current_time()){ 296 | if(check_better_schedule(f)) 297 | could_schd_better = true; 298 | if(f->redundancy_ctrl_timeout < closet_timeout) 299 | { 300 | closet_timeout = f->redundancy_ctrl_timeout; 301 | } 302 | } 303 | //ok to send 304 | else 305 | { 306 | //just timeout, reset timeout state 307 | if(f->redundancy_ctrl_timeout > 0) 308 | { 309 | f->redundancy_ctrl_timeout = -1; 310 | f->capability_goal += f->remaining_pkts(); 311 | } 312 | 313 | if(f->capability_gap() > params.capability_window) 314 | { 315 | if(get_current_time() >= f->latest_cap_sent_time + params.capability_window_timeout * params.get_full_pkt_tran_delay()) 316 | f->relax_capability_gap(); 317 | else{ 318 | if(f->latest_cap_sent_time + params.capability_window_timeout * params.get_full_pkt_tran_delay() < closet_timeout) 319 | { 320 | closet_timeout = f->latest_cap_sent_time + params.capability_window_timeout* params.get_full_pkt_tran_delay(); 321 | } 322 | } 323 | 324 | } 325 | 326 | 327 | if(f->capability_gap() <= params.capability_window) 328 | { 329 | f->send_capability_pkt(); 330 | capability_sent = true; 331 | 332 | if(f->capability_count == f->capability_goal){ 333 | f->redundancy_ctrl_timeout = get_current_time() + params.capability_resend_timeout * params.get_full_pkt_tran_delay(); 334 | } 335 | 336 | break; 337 | } 338 | 339 | 340 | } 341 | } 342 | 343 | while(!flows_tried.empty()){ 344 | CapabilityFlow* tf = flows_tried.front(); 345 | flows_tried.pop(); 346 | this->active_receiving_flows.push(tf); 347 | } 348 | 349 | 350 | 351 | if(capability_sent)// pkt sent 352 | { 353 | this->schedule_capa_proc_evt(params.get_full_pkt_tran_delay(1500/* + 40*/), false); 354 | } 355 | else if(closet_timeout < 999999) //has unsend flow, but its within timeout 356 | { 357 | assert(closet_timeout > get_current_time()); 358 | this->schedule_capa_proc_evt(closet_timeout - get_current_time(), true); 359 | } 360 | else{ 361 | //do nothing, no unfinished flow 362 | } 363 | 364 | if(could_schd_better) 365 | this->could_better_schd_count++; 366 | } 367 | 368 | -------------------------------------------------------------------------------- /ext/capabilityhost.h: -------------------------------------------------------------------------------- 1 | #ifndef CAPABILITY_HOST_H 2 | #define CAPABILITY_HOST_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../coresim/node.h" 8 | #include "../coresim/packet.h" 9 | #include "../coresim/event.h" 10 | 11 | #include "schedulinghost.h" 12 | #include "custompriorityqueue.h" 13 | 14 | class CapabilityFlow; 15 | class CapabilityProcessingEvent; 16 | class SenderNotifyEvent; 17 | 18 | class CapabilityFlowComparator { 19 | public: 20 | bool operator() (CapabilityFlow* a, CapabilityFlow* b); 21 | }; 22 | 23 | class CapabilityFlowComparatorAtReceiver { 24 | public: 25 | bool operator() (CapabilityFlow* a, CapabilityFlow* b); 26 | }; 27 | 28 | class CapabilityHost : public SchedulingHost { 29 | public: 30 | CapabilityHost(uint32_t id, double rate, uint32_t queue_type); 31 | void schedule_host_proc_evt(); 32 | void start_capability_flow(CapabilityFlow* f); 33 | void send(); 34 | //std::priority_queue, CapabilityFlowComparator> active_sending_flows; 35 | CustomPriorityQueue, CapabilityFlowComparator> active_sending_flows; 36 | 37 | void send_capability(); 38 | void schedule_capa_proc_evt(double time, bool is_timeout); 39 | void schedule_sender_notify_evt(); 40 | bool check_better_schedule(CapabilityFlow* f); 41 | bool is_sender_idle(); 42 | void notify_flow_status(); 43 | //std::priority_queue, CapabilityFlowComparatorAtReceiver> active_receiving_flows; 44 | CustomPriorityQueue, CapabilityFlowComparatorAtReceiver> active_receiving_flows; 45 | CapabilityProcessingEvent *capa_proc_evt; 46 | SenderNotifyEvent* sender_notify_evt; 47 | int hold_on; 48 | int total_capa_schd_evt_count; 49 | int could_better_schd_count; 50 | }; 51 | 52 | #define CAPABILITY_PROCESSING 11 53 | class CapabilityProcessingEvent : public Event { 54 | public: 55 | CapabilityProcessingEvent(double time, CapabilityHost *host, bool is_timeout); 56 | ~CapabilityProcessingEvent(); 57 | void process_event(); 58 | CapabilityHost *host; 59 | bool is_timeout_evt; 60 | }; 61 | 62 | #define SENDER_NOTIFY 13 63 | class SenderNotifyEvent : public Event { 64 | public: 65 | SenderNotifyEvent(double time, CapabilityHost *host); 66 | ~SenderNotifyEvent(); 67 | void process_event(); 68 | CapabilityHost *host; 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /ext/custompriorityqueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * custompriorityqueue.h 3 | * 4 | * Created on: Apr 28, 2015 5 | * Author: peter 6 | */ 7 | 8 | #ifndef CUSTOMPRIORITYQUEUE_H_ 9 | #define CUSTOMPRIORITYQUEUE_H_ 10 | 11 | #include 12 | #include "assert.h" 13 | 14 | template 15 | class CustomPriorityQueue 16 | { 17 | private: 18 | int best_index; 19 | 20 | public: 21 | _Sequence v; 22 | _Compare comp; 23 | 24 | 25 | CustomPriorityQueue() 26 | { 27 | comp = _Compare(); 28 | v = _Sequence(); 29 | best_index = -1; 30 | } 31 | 32 | bool empty() const 33 | { 34 | return v.empty(); 35 | } 36 | int size() const { 37 | return v.size(); 38 | } 39 | void push(const _Tp& x) 40 | { 41 | assert(x); 42 | v.push_back(x); 43 | best_index = -1; 44 | } 45 | 46 | void pop() 47 | { 48 | assert(v.size() > 0); 49 | if(best_index < 0) 50 | this->top(); 51 | if(best_index >= 0){ 52 | v.erase(v.begin() + best_index); 53 | best_index = -1; 54 | } 55 | } 56 | 57 | _Tp top() 58 | { 59 | assert(v.size() > 0); 60 | _Tp best = *v.begin(); 61 | for(int i = 0; i < v.size(); i++) 62 | { 63 | if(!comp(v[i],best)){ 64 | best = v[i]; 65 | best_index = i; 66 | } 67 | } 68 | return best; 69 | } 70 | }; 71 | 72 | 73 | #endif /* CUSTOMPRIORITYQUEUE_H_ */ 74 | -------------------------------------------------------------------------------- /ext/dctcpFlow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dctcpFlow.h" 4 | 5 | #include "../coresim/event.h" 6 | #include "../run/params.h" 7 | 8 | extern double get_current_time(); 9 | extern void add_to_event_queue(Event *); 10 | extern int get_event_queue_size(); 11 | extern DCExpParams params; 12 | extern uint32_t num_outstanding_packets; 13 | extern uint32_t duplicated_packets_received; 14 | 15 | DctcpFlow::DctcpFlow( 16 | uint32_t id, 17 | double start_time, 18 | uint32_t size, 19 | Host *s, 20 | Host *d 21 | ) : Flow(id, start_time, size, s, d) { 22 | //ce_state = false; 23 | //delayed_ack_counter = 0; 24 | dctcp_g = 0.0625; 25 | dctcp_alpha = 0; 26 | ecn_history = new std::deque(max_cwnd); 27 | } 28 | 29 | void DctcpFlow::receive(Packet* p) { 30 | if (finished) { 31 | delete p; 32 | return; 33 | } 34 | 35 | if (p->type == ACK_PACKET) { 36 | Ack *a = (Ack *) p; 37 | receive_ack(a); 38 | } 39 | else if(p->type == NORMAL_PACKET) { 40 | this->receive_data_pkt(p); 41 | } 42 | else { 43 | assert(false); 44 | } 45 | 46 | delete p; 47 | } 48 | 49 | //Receiver Side 50 | 51 | //Delayed Ack Implementation 52 | /* 53 | void DctcpFlow::mark_receipt(Packet* p) { 54 | received_count++; 55 | total_queuing_time += p->total_queuing_delay; 56 | 57 | if (received.count(p->seq_no) == 0) { 58 | received[p->seq_no] = true; 59 | if(num_outstanding_packets >= ((p->size - hdr_size) / (mss))) 60 | num_outstanding_packets -= ((p->size - hdr_size) / (mss)); 61 | else 62 | num_outstanding_packets = 0; 63 | received_bytes += (p->size - hdr_size); 64 | } else { 65 | duplicated_packets_received += 1; 66 | } 67 | if (p->seq_no > max_seq_no_recv) { 68 | max_seq_no_recv = p->seq_no; 69 | } 70 | } 71 | 72 | void DctcpFlow::determine_ack(DctcpPacket* p) { 73 | // Determing which ack to send 74 | uint32_t s = recv_till; 75 | bool in_sequence = true; 76 | std::vector sack_list; 77 | while (s <= max_seq_no_recv) { 78 | if (received.count(s) > 0) { 79 | if (in_sequence) { 80 | recv_till += mss; 81 | } else { 82 | sack_list.push_back(s); 83 | } 84 | } else { 85 | in_sequence = false; 86 | } 87 | s += mss; 88 | } 89 | 90 | //send_ack(recv_till, sack_list); // Cumulative Ack 91 | Packet* a = new DctcpAck(this, recv_till, sack_list, hdr_size, dst, src, p->ecn, delayed_ack_counter); 92 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), a, dst->queue)); 93 | } 94 | 95 | void DctcpFlow::receive_data_pkt(Packet* p) { 96 | mark_receipt(p); 97 | 98 | DctcpPacket *dcp = (DctcpPacket*) p; 99 | if (ce_state) { 100 | if (dcp->ecn) { 101 | if (delayed_ack_counter == params.dctcp_delayed_ack_freq) { 102 | determine_ack(dcp); 103 | delayed_ack_counter = 0; 104 | } 105 | else { 106 | delayed_ack_counter++; 107 | } 108 | } 109 | else { 110 | determine_ack(dcp); 111 | delayed_ack_counter = 0; 112 | ce_state = false; 113 | } 114 | } 115 | else { 116 | if (dcp->ecn) { 117 | determine_ack(dcp); 118 | delayed_ack_counter = 0; 119 | ce_state = true; 120 | } 121 | else { 122 | if (delayed_ack_counter == params.dctcp_delayed_ack_freq) { 123 | determine_ack(dcp); 124 | delayed_ack_counter = 0; 125 | } 126 | else { 127 | delayed_ack_counter++; 128 | } 129 | } 130 | } 131 | } 132 | */ 133 | 134 | void DctcpFlow::receive_data_pkt(Packet* p) { 135 | received_count++; 136 | total_queuing_time += p->total_queuing_delay; 137 | 138 | if (received.count(p->seq_no) == 0) { 139 | received[p->seq_no] = true; 140 | if(num_outstanding_packets >= ((p->size - hdr_size) / (mss))) 141 | num_outstanding_packets -= ((p->size - hdr_size) / (mss)); 142 | else 143 | num_outstanding_packets = 0; 144 | received_bytes += (p->size - hdr_size); 145 | } else { 146 | duplicated_packets_received += 1; 147 | } 148 | if (p->seq_no > max_seq_no_recv) { 149 | max_seq_no_recv = p->seq_no; 150 | } 151 | // Determing which ack to send 152 | uint32_t s = recv_till; 153 | bool in_sequence = true; 154 | std::vector sack_list; 155 | while (s <= max_seq_no_recv) { 156 | if (received.count(s) > 0) { 157 | if (in_sequence) { 158 | recv_till += mss; 159 | } else { 160 | sack_list.push_back(s); 161 | } 162 | } else { 163 | in_sequence = false; 164 | } 165 | s += mss; 166 | } 167 | 168 | Packet *a = new DctcpAck(this, recv_till, sack_list, hdr_size, dst, src, ((DctcpPacket*) p)->ecn); //Acks are dst->src 169 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), a, dst->queue)); 170 | } 171 | 172 | void DctcpFlow::increase_cwnd() { 173 | // cwnd <- cwnd * (1 - a/2) 174 | // floor(x + 0.5) same as round to nearest integer 175 | cwnd_mss = (uint32_t) floor(cwnd_mss * (1 - dctcp_alpha / 2) + 0.5); 176 | } 177 | 178 | void DctcpFlow::receive_ack(Ack* a) { 179 | DctcpAck *dca = (DctcpAck*) a; 180 | uint32_t ack = a->seq_no; 181 | std::vector sack_list = a->sack_list; 182 | 183 | this->scoreboard_sack_bytes = sack_list.size() * mss; 184 | 185 | // On timeouts; next_seq_no is updated to the last_unacked_seq; 186 | // In such cases, the ack can be greater than next_seq_no; update it 187 | if (next_seq_no < ack) { 188 | next_seq_no = ack; 189 | } 190 | 191 | // New ack! 192 | if (ack > last_unacked_seq) { 193 | // Update the last unacked seq 194 | last_unacked_seq = ack; 195 | 196 | // Update ecn_history 197 | //for (uint32_t i = 0; i < dca->delayed_num; i++) // only needed for delayed ack 198 | assert(dca->ecn == 1 || dca->ecn == 0); 199 | ecn_history->push_front(dca->ecn); 200 | while (ecn_history->size() > max_cwnd) 201 | ecn_history->pop_back(); 202 | 203 | // Update alpha 204 | // a <- (1 - g) * a + g * F 205 | uint32_t ecn_set_count = 0; 206 | uint32_t sz = ecn_history->size(); 207 | for (uint32_t i = 0; i < cwnd_mss; i++) { 208 | assert(i < sz); 209 | if (ecn_history->at(i) == true) { 210 | ecn_set_count ++; 211 | } 212 | 213 | // TODO doing the following causes an unexplainable bug at -O2 but not -Og 214 | // 215 | //volatile char setecn = (ecn_history->at(i) ) ? 1 : 0; 216 | //std::cout << setecn << " " << ecn_history->at(i) << "\n"; 217 | //assert(ecn_history->at(i) == 0 || ecn_history->at(i) == 1); 218 | //assert(setecn == 1 || setecn == 0); 219 | //ecn_set_count += setecn; 220 | } 221 | assert(ecn_set_count <= cwnd_mss && cwnd_mss <= sz); 222 | double frac_ecn = ecn_set_count / cwnd_mss; 223 | assert(frac_ecn >= 0.0 && frac_ecn <= 1.0); 224 | dctcp_alpha = (1 - dctcp_g) * dctcp_alpha + dctcp_g * frac_ecn; 225 | assert(dctcp_alpha >= 0.0 && dctcp_alpha <= 1.0); 226 | 227 | // Adjust cwnd 228 | increase_cwnd(); 229 | 230 | // Send the remaining data 231 | send_pending_data(); 232 | 233 | // Update the retx timer 234 | if (retx_event != NULL) { // Try to move 235 | cancel_retx_event(); 236 | if (last_unacked_seq < size) { 237 | // Move the timeout to last_unacked_seq 238 | double timeout = get_current_time() + retx_timeout; 239 | set_timeout(timeout); 240 | } 241 | } 242 | } 243 | 244 | if (ack == size && !finished) { 245 | finished = true; 246 | received.clear(); 247 | finish_time = get_current_time(); 248 | flow_completion_time = finish_time - start_time; 249 | FlowFinishedEvent *ev = new FlowFinishedEvent(get_current_time(), this); 250 | add_to_event_queue(ev); 251 | } 252 | } 253 | 254 | uint32_t DctcpFlow::get_priority(uint32_t seq) { 255 | return 1; 256 | } 257 | -------------------------------------------------------------------------------- /ext/dctcpFlow.h: -------------------------------------------------------------------------------- 1 | #ifndef DCTCP_FLOW_H 2 | #define DCTCP_FLOW_H 3 | 4 | #include "dctcpPacket.h" 5 | #include "../coresim/flow.h" 6 | #include "../coresim/node.h" 7 | 8 | class DctcpFlow : public Flow { 9 | public: 10 | DctcpFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 11 | // subclass to set priorities to 1 12 | virtual uint32_t get_priority(uint32_t seq); 13 | 14 | // Receiver Side 15 | virtual void receive_data_pkt(Packet* p); 16 | //void mark_receipt(Packet* p); 17 | //void determine_ack(DctcpPacket* p); 18 | 19 | // After looking at DCTCP NS2 code, Delayed ACK is not used. 20 | // 21 | // ECN-Echo + Delayed ACK state machine 22 | // 23 | // while no ECN set, send 1 ACK per m packets with ECN = 0 24 | // if ECN set in received packet, immediately send ACK with ECN = 0 25 | // while ECN = 1, send 1 ACK per m packets with ECN = 1 26 | // if ECN not set in received packet, immediately send ACK with ECN = 1 27 | // delayed ACK m number typically = 2. params.dctcp_delayed_ack_freq 28 | 29 | //bool ce_state; 30 | //uint32_t delayed_ack_counter; 31 | 32 | // Sender Side 33 | virtual void receive(Packet* p); 34 | void receive_ack(Ack* a); 35 | 36 | // sender response to ECN-Echo: cwnd <- cwnd * (1 - a/2) 37 | // a <- (1 - g) * a + g * F 38 | // where g = params.dctcp_discount_rate and F = fraction of packets marked in last window 39 | virtual void increase_cwnd(); 40 | std::deque* ecn_history; 41 | double dctcp_alpha; 42 | double dctcp_g; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /ext/dctcpPacket.h: -------------------------------------------------------------------------------- 1 | #ifndef DCTCP_PACKET_H 2 | #define DCTCP_PACKET_H 3 | 4 | #include "../coresim/packet.h" 5 | 6 | class DctcpPacket : public Packet { 7 | public: 8 | bool ecn; 9 | 10 | DctcpPacket( 11 | double sending_time, 12 | Flow *flow, 13 | uint32_t seq_no, 14 | uint32_t pf_priority, 15 | uint32_t size, 16 | Host *src, 17 | Host *dst, 18 | bool ecn 19 | ) : Packet(sending_time, flow, seq_no, pf_priority, size, src, dst) { 20 | this->ecn = ecn; 21 | } 22 | }; 23 | 24 | class DctcpAck : public Ack { 25 | public: 26 | bool ecn; 27 | //uint32_t delayed_num; 28 | 29 | DctcpAck( 30 | Flow *flow, 31 | uint32_t seq_no_acked, 32 | std::vector sack_list, 33 | uint32_t size, 34 | Host* src, 35 | Host* dst, 36 | bool ecn 37 | // uint32_t delayed_num 38 | ) : Ack(flow, seq_no_acked, sack_list, size, src, dst) { 39 | this->ecn = ecn; 40 | // this->delayed_num = delayed_num; 41 | } 42 | }; 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /ext/dctcpQueue.cpp: -------------------------------------------------------------------------------- 1 | // Akshay Narayan 2 | // 11 January 2016 3 | 4 | #include "dctcpQueue.h" 5 | #include "dctcpPacket.h" 6 | 7 | #include "../run/params.h" 8 | 9 | extern double get_current_time(); 10 | extern void add_to_event_queue(Event *ev); 11 | extern DCExpParams params; 12 | 13 | DctcpQueue::DctcpQueue(uint32_t id, double rate, uint32_t limit_bytes, int location) : Queue(id, rate, limit_bytes, location) {} 14 | 15 | /** 16 | * ECN marking. Otherwise just a droptail queue. 17 | * K_min > (C (pkts/s) * RTT (s)) / 7 18 | * at 10 Gbps recommend K = 65 packets, at 1 Gbps K = 20 19 | * if queue length < params.dctcp_mark_thresh, don't mark (ECN = 0). 20 | * if queue length > params.dctcp_mark_thresh, mark (ECN = 1). 21 | */ 22 | void DctcpQueue::enque(Packet *packet) { 23 | p_arrivals += 1; 24 | b_arrivals += packet->size; 25 | if (bytes_in_queue + packet->size <= limit_bytes) { 26 | packets.push_back(packet); 27 | bytes_in_queue += packet->size; 28 | 29 | if (packets.size() >= params.dctcp_mark_thresh) { 30 | ((DctcpPacket*) packet)->ecn = true; 31 | } 32 | } 33 | else { 34 | pkt_drop++; 35 | drop(packet); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /ext/dctcpQueue.h: -------------------------------------------------------------------------------- 1 | // Akshay Narayan 2 | // 11 January 2016 3 | 4 | #ifndef DCTCP_QUEUE_H 5 | #define DCTCP_QUEUE_H 6 | 7 | #include "../coresim/queue.h" 8 | #include "../coresim/packet.h" 9 | 10 | #define DCTCP_QUEUE 5 11 | 12 | class DctcpQueue : public Queue { 13 | public: 14 | DctcpQueue(uint32_t id, double rate, uint32_t limit_bytes, int location); 15 | void enque(Packet *packet); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /ext/factory.cpp: -------------------------------------------------------------------------------- 1 | #include "factory.h" 2 | 3 | #include "pfabricqueue.h" 4 | #include "pfabricflow.h" 5 | 6 | #include "schedulinghost.h" 7 | 8 | #include "capabilityhost.h" 9 | #include "capabilityflow.h" 10 | 11 | #include "magicflow.h" 12 | #include "magichost.h" 13 | 14 | #include "fastpassflow.h" 15 | #include "fastpasshost.h" 16 | 17 | #include "tcpflow.h" 18 | 19 | #include "dctcpQueue.h" 20 | #include "dctcpFlow.h" 21 | 22 | #include "ideal.h" 23 | 24 | IdealArbiter* ideal_arbiter = NULL; 25 | 26 | /* Factory method to return appropriate queue */ 27 | Queue* Factory::get_queue( 28 | uint32_t id, 29 | double rate, 30 | uint32_t queue_size, 31 | uint32_t type, 32 | double drop_prob, 33 | int location 34 | ) { // Default drop_prob is 0.0 35 | 36 | switch(type) { 37 | case DROPTAIL_QUEUE: 38 | return new Queue(id, rate, queue_size, location); 39 | case PFABRIC_QUEUE: 40 | return new PFabricQueue(id, rate, queue_size, location); 41 | case PROB_DROP_QUEUE: 42 | return new ProbDropQueue(id, rate, queue_size, drop_prob, location); 43 | case DCTCP_QUEUE: 44 | return new DctcpQueue(id, rate, queue_size, location); 45 | } 46 | assert(false); 47 | return NULL; 48 | } 49 | 50 | int Factory::flow_counter = 0; 51 | 52 | Flow* Factory::get_flow( 53 | double start_time, 54 | uint32_t size, 55 | Host *src, 56 | Host *dst, 57 | uint32_t flow_type, 58 | double rate 59 | ) { 60 | return Factory::get_flow(Factory::flow_counter++, start_time, size, src, dst, flow_type, rate); 61 | } 62 | 63 | Flow* Factory::get_flow( 64 | uint32_t id, 65 | double start_time, 66 | uint32_t size, 67 | Host *src, 68 | Host *dst, 69 | uint32_t flow_type, 70 | double rate 71 | ) { // Default rate is 1.0 72 | switch (flow_type) { 73 | case NORMAL_FLOW: 74 | return new Flow(id, start_time, size, src, dst); 75 | break; 76 | case PFABRIC_FLOW: 77 | return new PFabricFlow(id, start_time, size, src, dst); 78 | break; 79 | case CAPABILITY_FLOW: 80 | return new CapabilityFlow(id, start_time, size, src, dst); 81 | break; 82 | case MAGIC_FLOW: 83 | return new MagicFlow(id, start_time, size, src, dst); 84 | break; 85 | case FASTPASS_FLOW: 86 | return new FastpassFlow(id, start_time, size, src, dst); 87 | break; 88 | case VANILLA_TCP_FLOW: 89 | return new TCPFlow(id, start_time, size, src, dst); 90 | break; 91 | case DCTCP_FLOW: 92 | return new DctcpFlow(id, start_time, size, src, dst); 93 | break; 94 | case IDEAL_FLOW: 95 | return new IdealFlow(id, start_time, size, src, dst); 96 | break; 97 | } 98 | assert(false); 99 | return NULL; 100 | } 101 | 102 | Host* Factory::get_host( 103 | uint32_t id, 104 | double rate, 105 | uint32_t queue_type, 106 | uint32_t host_type 107 | ) { 108 | switch (host_type) { 109 | case NORMAL_HOST: 110 | return new Host(id, rate, queue_type, NORMAL_HOST); 111 | break; 112 | case SCHEDULING_HOST: 113 | return new SchedulingHost(id, rate, queue_type); 114 | break; 115 | case CAPABILITY_HOST: 116 | return new CapabilityHost(id, rate, queue_type); 117 | break; 118 | case MAGIC_HOST: 119 | return new MagicHost(id, rate, queue_type); 120 | break; 121 | case FASTPASS_HOST: 122 | return new FastpassHost(id, rate, queue_type); 123 | break; 124 | case IDEAL_HOST: 125 | if (ideal_arbiter == NULL) { 126 | ideal_arbiter = new IdealArbiter(); 127 | } 128 | 129 | return new IdealHost(id, rate, queue_type); 130 | break; 131 | } 132 | std::cerr << host_type << " unknown\n"; 133 | assert(false); 134 | return NULL; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /ext/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef FACTORY_H 2 | #define FACTORY_H 3 | 4 | #include "../coresim/flow.h" 5 | #include "../coresim/node.h" 6 | #include "../coresim/queue.h" 7 | 8 | /* Queue types */ 9 | #define DROPTAIL_QUEUE 1 10 | #define PFABRIC_QUEUE 2 11 | #define PROB_DROP_QUEUE 4 12 | #define DCTCP_QUEUE 5 13 | 14 | /* Flow types */ 15 | #define NORMAL_FLOW 1 16 | #define PFABRIC_FLOW 2 17 | #define VANILLA_TCP_FLOW 42 18 | #define DCTCP_FLOW 43 19 | #define CAPABILITY_FLOW 112 20 | #define MAGIC_FLOW 113 21 | #define FASTPASS_FLOW 114 22 | #define IDEAL_FLOW 120 23 | 24 | /* Host types */ 25 | #define NORMAL_HOST 1 26 | #define SCHEDULING_HOST 2 27 | #define CAPABILITY_HOST 12 28 | #define MAGIC_HOST 13 29 | #define FASTPASS_HOST 14 30 | #define FASTPASS_ARBITER 10 31 | #define IDEAL_HOST 20 32 | 33 | class Factory { 34 | public: 35 | static int flow_counter; 36 | static Flow *get_flow( 37 | uint32_t id, 38 | double start_time, 39 | uint32_t size, 40 | Host *src, 41 | Host *dst, 42 | uint32_t flow_type, 43 | double paced_rate = 0.0 44 | ); 45 | 46 | static Flow *get_flow( 47 | double start_time, 48 | uint32_t size, 49 | Host *src, 50 | Host *dst, 51 | uint32_t flow_type, 52 | double paced_rate = 0.0 53 | ); 54 | 55 | static Queue *get_queue( 56 | uint32_t id, 57 | double rate, 58 | uint32_t queue_size, 59 | uint32_t type, 60 | double drop_prob, 61 | int location 62 | ); 63 | 64 | static Host* get_host( 65 | uint32_t id, 66 | double rate, 67 | uint32_t queue_type, 68 | uint32_t host_type 69 | ); 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ext/fastpassTopology.cpp: -------------------------------------------------------------------------------- 1 | #include "../coresim/packet.h" 2 | #include "../coresim/queue.h" 3 | 4 | #include "fastpassTopology.h" 5 | 6 | #include "../run/params.h" 7 | 8 | extern DCExpParams params; 9 | 10 | FastpassAggSwitch::FastpassAggSwitch( 11 | uint32_t id, 12 | uint32_t nq1, 13 | double r1, 14 | uint32_t nq2, 15 | double r2, 16 | uint32_t queue_type 17 | ) : AggSwitch(id, nq1, r1, nq2, r2, queue_type) { 18 | queue_to_arbiter = NULL; 19 | } 20 | 21 | FastpassTopology::FastpassTopology( 22 | uint32_t num_hosts, 23 | uint32_t num_agg_switches, 24 | uint32_t num_core_switches, 25 | double bandwidth, 26 | uint32_t queue_type 27 | ) : PFabricTopology(num_hosts, num_agg_switches, num_core_switches, bandwidth, queue_type) { 28 | for (auto s = this->switches.begin(); s != this->switches.end(); s++) { 29 | for (auto q = (*s)->queues.begin(); q != (*s)->queues.end(); q++) { 30 | delete *q; 31 | } 32 | delete *s; 33 | } 34 | 35 | this->agg_switches.clear(); 36 | this->core_switches.clear(); 37 | this->switches.clear(); 38 | this->hosts.clear(); 39 | Queue::instance_count = 0; 40 | 41 | uint32_t hosts_per_agg_switch = num_hosts / num_agg_switches; 42 | //std::cout << "\n\n" << hosts_per_agg_switch << "\n\n"; 43 | 44 | this->num_hosts = num_hosts; 45 | this->num_agg_switches = num_agg_switches; 46 | this->num_core_switches = num_core_switches; 47 | 48 | //Capacities 49 | double c1 = bandwidth; 50 | double c2 = hosts_per_agg_switch * bandwidth / num_core_switches; 51 | 52 | // Create Hosts 53 | for (uint32_t i = 0; i < num_hosts; i++) { 54 | hosts.push_back(Factory::get_host(i, c1, queue_type, params.host_type)); 55 | } 56 | 57 | arbiter = new FastpassArbiter(num_hosts, c1, queue_type); 58 | 59 | // Create Switches 60 | for (uint32_t i = 0; i < num_agg_switches; i++) { 61 | AggSwitch* sw; 62 | if (i == 0) sw = new FastpassAggSwitch(i, hosts_per_agg_switch, c1, num_core_switches, c2, queue_type); 63 | else sw = new AggSwitch(i, hosts_per_agg_switch, c1, num_core_switches, c2, queue_type); 64 | 65 | agg_switches.push_back(sw); // TODO make generic 66 | switches.push_back(sw); 67 | } 68 | for (uint32_t i = 0; i < num_core_switches; i++) { 69 | CoreSwitch* sw = new CoreSwitch(i + num_agg_switches, num_agg_switches, c2, queue_type); 70 | core_switches.push_back(sw); 71 | switches.push_back(sw); 72 | } 73 | ((FastpassAggSwitch*) agg_switches[0])->queue_to_arbiter = Factory::get_queue(num_agg_switches + num_core_switches, c1, params.queue_size, queue_type, 0, 3); 74 | 75 | 76 | //Connect host queues 77 | for (uint32_t i = 0; i < num_hosts; i++) { 78 | hosts[i]->queue->set_src_dst(hosts[i], agg_switches[i/16]); 79 | } 80 | 81 | arbiter->queue->set_src_dst(arbiter, agg_switches[0]); 82 | // std::cout << "Linking arbiter with queue " << arbiter->queue->id << " " << arbiter->queue->unique_id << " with agg switch " << agg_switches[0]->id << "\n" ; 83 | 84 | 85 | // For agg switches -- REMAINING 86 | for (uint32_t i = 0; i < num_agg_switches; i++) { 87 | // Queues to Hosts 88 | for (uint32_t j = 0; j < hosts_per_agg_switch; j++) { // TODO make generic 89 | Queue *q = agg_switches[i]->queues[j]; 90 | q->set_src_dst(agg_switches[i], hosts[i * 16 + j]); 91 | // std::cout << "Linking Agg " << i << " to Host" << i * 16 + j << " with queue " << q->id << " " << q->unique_id << "\n"; 92 | } 93 | // Queues to Core 94 | for (uint32_t j = 0; j < num_core_switches; j++) { 95 | Queue *q = agg_switches[i]->queues[j + 16]; 96 | q->set_src_dst(agg_switches[i], core_switches[j]); 97 | // std::cout << "Linking Agg " << i << " to Core" << j << " with queue " << q->id << " " << q->unique_id << "\n"; 98 | } 99 | } 100 | 101 | ((FastpassAggSwitch*) agg_switches[0])->queue_to_arbiter->set_src_dst(agg_switches[0], arbiter); 102 | // std::cout << "Linking arbiter switch " << agg_switches[0]->id << " with queue " << ((FastpassAggSwitch*) agg_switches[0])->queue_to_arbiter->id << " " << ((FastpassAggSwitch*) agg_switches[0])->queue_to_arbiter->unique_id << "\n"; 103 | 104 | //For core switches -- PERFECT 105 | for (uint32_t i = 0; i < num_core_switches; i++) { 106 | for (uint32_t j = 0; j < num_agg_switches; j++) { 107 | Queue *q = core_switches[i]->queues[j]; 108 | q->set_src_dst(core_switches[i], agg_switches[j]); 109 | // std::cout << "Linking Core " << i << " to Agg" << j << " with queue " << q->id << " " << q->unique_id << "\n"; 110 | } 111 | } 112 | 113 | for (auto s = this->switches.begin(); s != this->switches.end(); s++) { 114 | for (auto q = (*s)->queues.begin(); q != (*s)->queues.end(); q++) { 115 | assert((*q)->src == (*s)); 116 | assert((*q)->src != NULL && (*q)->dst != NULL); 117 | } 118 | } 119 | } 120 | 121 | Queue* FastpassTopology::get_next_hop(Packet* p, Queue* q) { 122 | if (q->dst->type == HOST) { 123 | return NULL; // Packet Arrival 124 | } 125 | 126 | // At host level 127 | if (q->src->type == HOST) { // Same Rack or not 128 | assert (p->src->id == q->src->id); 129 | 130 | if (p->src->id / 16 == p->dst->id / 16 || 131 | ( 132 | (p->src->host_type == FASTPASS_ARBITER && p->dst->id / 16 == 0) || 133 | (p->dst->host_type == FASTPASS_ARBITER && p->src->id / 16 == 0) 134 | ) 135 | ) { 136 | return ((Switch *) q->dst)->queues[p->dst->id % 16]; 137 | } 138 | else { 139 | uint32_t hash_port = 0; 140 | if(params.load_balancing == 0) 141 | hash_port = q->spray_counter++%4; 142 | else if(params.load_balancing == 1) 143 | hash_port = (p->src->id + p->dst->id + p->flow->id) % 4; 144 | return ((Switch *) q->dst)->queues[16 + hash_port]; 145 | } 146 | } 147 | 148 | // At switch level 149 | if (q->src->type == SWITCH) { 150 | if (((Switch *) q->src)->switch_type == AGG_SWITCH) { 151 | if (p->dst->host_type == FASTPASS_ARBITER) 152 | return ((Switch *) q->dst)->queues[0]; 153 | else 154 | return ((Switch *) q->dst)->queues[p->dst->id / 16]; 155 | } 156 | if (((Switch *) q->src)->switch_type == CORE_SWITCH) { 157 | if (p->dst->host_type == FASTPASS_ARBITER) { 158 | assert(((Switch*)q->dst)->id == 0); 159 | return ((FastpassAggSwitch *) q->dst)->queue_to_arbiter; 160 | } 161 | else 162 | return ((Switch *) q->dst)->queues[p->dst->id % 16]; 163 | } 164 | } 165 | 166 | assert(false); 167 | } 168 | 169 | -------------------------------------------------------------------------------- /ext/fastpassTopology.h: -------------------------------------------------------------------------------- 1 | #ifndef FP_TOPO_H 2 | #define FP_TOPO_H 3 | 4 | #include "../coresim/topology.h" 5 | #include "fastpasshost.h" 6 | 7 | class FastpassAggSwitch : public AggSwitch { 8 | public: 9 | FastpassAggSwitch(uint32_t id, uint32_t nq1, double r1, uint32_t nq2, double r2, uint32_t queue_type); 10 | Queue* queue_to_arbiter; 11 | }; 12 | 13 | class FastpassTopology : virtual public PFabricTopology { 14 | public: 15 | FastpassTopology( 16 | uint32_t num_hosts, 17 | uint32_t num_agg_switches, 18 | uint32_t num_core_switches, 19 | double bandwidth, 20 | uint32_t queue_type 21 | ); 22 | virtual Queue* get_next_hop(Packet* p, Queue* q); 23 | 24 | FastpassArbiter* arbiter; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ext/fastpassflow.cpp: -------------------------------------------------------------------------------- 1 | #include "fastpasshost.h" 2 | #include "fastpassflow.h" 3 | 4 | #include "../coresim/packet.h" 5 | #include "../coresim/topology.h" 6 | #include "../coresim/event.h" 7 | #include "../coresim/debug.h" 8 | 9 | #include "fastpassTopology.h" 10 | 11 | extern Topology *topology; 12 | extern double get_current_time(); 13 | extern void add_to_event_queue(Event*); 14 | extern DCExpParams params; 15 | extern uint32_t num_outstanding_packets; 16 | 17 | FastpassFlow::FastpassFlow( 18 | uint32_t id, 19 | double start_time, 20 | uint32_t size, 21 | Host *s, 22 | Host *d 23 | ) : Flow(id, start_time, size, s, d) { 24 | this->sender_remaining_num_pkts = this->size_in_pkt; 25 | this->arbiter_received_rts = false; 26 | this->arbiter_finished = false; 27 | this->sender_acked_count = 0; 28 | this->sender_acked_until = 0; 29 | this->sender_last_pkt_sent = -1; 30 | this->sender_finished = false; 31 | } 32 | 33 | void FastpassFlow::start_flow() { 34 | update_remaining_size(); 35 | } 36 | 37 | void FastpassFlow::update_remaining_size() { 38 | FastpassRTS* rts = new FastpassRTS(this, this->src, dynamic_cast(topology)->arbiter, this->sender_finished?-1:this->sender_remaining_num_pkts); 39 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), rts, src->queue)); 40 | } 41 | 42 | void FastpassFlow::send_ack_pkt(uint32_t seq) { 43 | PlainAck* ack = new PlainAck(this, seq, params.hdr_size, this->dst, this->src); 44 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), ack, this->dst->queue)); 45 | } 46 | 47 | void FastpassFlow::send_schedule_pkt(FastpassEpochSchedule* schd) { 48 | FastpassSchedulePkt* pkt = new FastpassSchedulePkt(this, dynamic_cast(topology)->arbiter, this->src, schd); 49 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), pkt, dynamic_cast(topology)->arbiter->queue)); 50 | } 51 | 52 | 53 | int FastpassFlow::next_pkt_to_send() 54 | { 55 | int pkt = this->sender_last_pkt_sent; 56 | for(int i = 0; i < this->size_in_pkt; i++){ 57 | pkt++; 58 | if(pkt >= this->size_in_pkt) 59 | pkt = sender_acked_until; 60 | if(sender_acked.count(pkt) == 0) 61 | return pkt; 62 | } 63 | } 64 | 65 | void FastpassFlow::send_data_pkt() { 66 | this->sender_last_pkt_sent = next_pkt_to_send(); 67 | Packet *p = new Packet(get_current_time(), this, this->sender_last_pkt_sent * mss, 1, mss + hdr_size, src, dst); 68 | if(debug_flow(this->id)) 69 | std::cout << get_current_time() << " flow " << this->id << " send data " << this->sender_last_pkt_sent << " \n"; 70 | total_pkt_sent++; 71 | next_seq_no += mss; 72 | if(sender_remaining_num_pkts > 0) sender_remaining_num_pkts--; 73 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, src->queue)); 74 | if(this->sender_remaining_num_pkts == 0) 75 | add_to_event_queue(new FastpassTimeoutEvent(get_current_time() + params.fastpass_epoch_time, this)); 76 | } 77 | 78 | 79 | void FastpassFlow::fastpass_timeout() 80 | { 81 | if(!this->sender_finished) 82 | { 83 | this->sender_remaining_num_pkts = this->size_in_pkt - this->sender_acked_count; 84 | this->update_remaining_size(); 85 | } 86 | } 87 | 88 | void FastpassFlow::receive(Packet *p) { 89 | if (p->type == FASTPASS_RTS) { 90 | if(debug_flow(this->id)) 91 | std::cout << get_current_time() << " flow " << this->id << " received rts\n"; 92 | dynamic_cast(topology)->arbiter->receive_rts((FastpassRTS*) p); 93 | } else if (p->type == FASTPASS_SCHEDULE) { 94 | if(debug_flow(this->id)) 95 | std::cout << get_current_time() << " flow " << this->id << " received schedule\n"; 96 | ((FastpassHost*) this->src)->receive_schedule_pkt((FastpassSchedulePkt*) p); 97 | } else if (p->type == NORMAL_PACKET) { 98 | if(debug_flow(this->id)) 99 | std::cout << get_current_time() << " flow " << this->id << " received data seq" << p->seq_no << "\n"; 100 | this->send_ack_pkt(p->seq_no); 101 | this->received_bytes += mss; 102 | if(receiver_received.count(p->seq_no) == 0) 103 | { 104 | receiver_received.insert(p->seq_no); 105 | if(num_outstanding_packets >= ((p->size - hdr_size) / (mss))) 106 | num_outstanding_packets -= ((p->size - hdr_size) / (mss)); 107 | else 108 | num_outstanding_packets = 0; 109 | } 110 | 111 | } else if (p->type == ACK_PACKET) { 112 | if(debug_flow(this->id)) 113 | std::cout << get_current_time() << " flow " << this->id << " received ack seq" << p->seq_no << "\n"; 114 | int acked_pkt = p->seq_no/mss; 115 | if(sender_acked.count(acked_pkt) == 0) 116 | { 117 | sender_acked.insert(acked_pkt); 118 | sender_acked_count++; 119 | while(sender_acked.count(sender_acked_until) > 0){ 120 | sender_acked_until++; 121 | } 122 | } 123 | if(!this->sender_finished && sender_acked_count == this->size_in_pkt){ 124 | this->sender_finished = true; 125 | this->update_remaining_size(); 126 | add_to_event_queue(new FlowFinishedEvent(get_current_time(), this)); 127 | } 128 | } else { 129 | assert(false); 130 | } 131 | delete p; 132 | } 133 | 134 | void FastpassFlow::schedule_send_pkt(double time) { 135 | add_to_event_queue(new FastpassFlowProcessingEvent(time, this)); 136 | } 137 | 138 | 139 | ArbiterProcessingEvent::ArbiterProcessingEvent(double time, FastpassArbiter* a) : Event(ARBITER_PROCESSING, time) { 140 | this->arbiter = a; 141 | } 142 | 143 | ArbiterProcessingEvent::~ArbiterProcessingEvent() { 144 | } 145 | 146 | void ArbiterProcessingEvent::process_event() { 147 | this->arbiter->arbiter_proc_evt = NULL; 148 | this->arbiter->schedule_epoch(); 149 | } 150 | 151 | -------------------------------------------------------------------------------- /ext/fastpassflow.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTPASS_FLOW_H 2 | #define FASTPASS_FLOW_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../coresim/flow.h" 8 | 9 | class FastpassEpochSchedule; 10 | 11 | class FastpassFlow : public Flow { 12 | public: 13 | FastpassFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 14 | void start_flow(); 15 | void update_remaining_size(); 16 | void send_ack_pkt(uint32_t); 17 | void send_schedule_pkt(FastpassEpochSchedule* schd); 18 | void send_data_pkt(); 19 | void receive(Packet *p); 20 | void schedule_send_pkt(double time); 21 | int next_pkt_to_send(); 22 | void fastpass_timeout(); 23 | 24 | int sender_remaining_num_pkts; 25 | std::set sender_acked; 26 | std::set receiver_received; 27 | int sender_acked_count; 28 | int sender_acked_until; 29 | int sender_last_pkt_sent; 30 | bool sender_finished; 31 | int arbiter_remaining_num_pkts; 32 | bool arbiter_received_rts; 33 | bool arbiter_finished; 34 | }; 35 | 36 | #define FASTPASS_FLOW_PROCESSING 15 37 | class FastpassFlowProcessingEvent : public Event { 38 | public: 39 | FastpassFlowProcessingEvent(double time, FastpassFlow *flow); 40 | ~FastpassFlowProcessingEvent(); 41 | void process_event(); 42 | FastpassFlow* flow; 43 | }; 44 | 45 | #define FASTPASS_TIMEOUT 16 46 | class FastpassTimeoutEvent : public Event { 47 | public: 48 | FastpassTimeoutEvent(double time, FastpassFlow *flow); 49 | ~FastpassTimeoutEvent(); 50 | void process_event(); 51 | FastpassFlow* flow; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /ext/fastpasshost.cpp: -------------------------------------------------------------------------------- 1 | #include "assert.h" 2 | 3 | #include "../coresim/event.h" 4 | #include "../coresim/topology.h" 5 | #include "../coresim/debug.h" 6 | 7 | #include "factory.h" 8 | #include "fastpassflow.h" 9 | #include "fastpasshost.h" 10 | #include "fastpassTopology.h" 11 | 12 | #include "../run/params.h" 13 | 14 | extern uint32_t total_finished_flows; 15 | extern double get_current_time(); 16 | extern void add_to_event_queue(Event*); 17 | extern DCExpParams params; 18 | extern Topology *topology; 19 | 20 | bool FastpassFlowComparator::operator() (FastpassFlow* a, FastpassFlow* b) { 21 | return a->arbiter_remaining_num_pkts > b->arbiter_remaining_num_pkts; 22 | } 23 | 24 | 25 | FastpassEpochSchedule::FastpassEpochSchedule(double s) { 26 | this->start_time = s; 27 | for(int i = 0; i < FASTPASS_EPOCH_PKTS; i++) 28 | { 29 | schedule[i] = NULL; 30 | } 31 | } 32 | 33 | FastpassFlow* FastpassEpochSchedule::get_sender() { 34 | for (int i = 0; i < FASTPASS_EPOCH_PKTS; i++) { 35 | if (schedule[i]) return schedule[i]; 36 | } 37 | return NULL; 38 | } 39 | 40 | FastpassHost::FastpassHost(uint32_t id, double rate, uint32_t queue_type) : Host(id, rate, queue_type, FASTPASS_HOST) { 41 | } 42 | 43 | void FastpassHost::receive_schedule_pkt(FastpassSchedulePkt* pkt) { 44 | // assert(pkt->schedule->start_time >= get_current_time()); 45 | if (pkt->schedule->start_time >= get_current_time()) { 46 | pkt->schedule->start_time = get_current_time(); 47 | } 48 | 49 | for(int i = 0; i < FASTPASS_EPOCH_PKTS; i++) 50 | { 51 | if(pkt->schedule->schedule[i]) 52 | pkt->schedule->schedule[i]->schedule_send_pkt(pkt->schedule->start_time + i * params.fastpass_epoch_time / FASTPASS_EPOCH_PKTS); 53 | } 54 | 55 | delete pkt->schedule; 56 | } 57 | 58 | 59 | FastpassArbiter::FastpassArbiter(uint32_t id, double rate, uint32_t queue_type) : Host(id, rate, queue_type, FASTPASS_ARBITER) {} 60 | 61 | void FastpassArbiter::start_arbiter() { 62 | this->schedule_proc_evt(1.0); 63 | } 64 | 65 | std::map FastpassArbiter::schedule_timeslot() 66 | { 67 | std::map schedule; 68 | std::set sender_used; 69 | std::set receiver_used; 70 | 71 | 72 | std::queue flows_tried; 73 | while(!sending_flows.empty()) 74 | { 75 | FastpassFlow* f = sending_flows.top(); 76 | sending_flows.pop(); 77 | if(f->arbiter_finished){ 78 | continue; 79 | } 80 | bool sender_free = sender_used.count(f->src->id) == 0; 81 | bool receiver_free = receiver_used.count(f->dst->id) == 0; 82 | if(debug_flow(f->id) && get_current_time() >= 1.03000023262123){ 83 | std::cout << get_current_time() << " attempting schedule flow " << f->id << " " << f->src->id << "->" << f->dst->id << " for epoch " << 84 | get_current_time() + params.fastpass_epoch_time << " s_free" << sender_free << " r_free" << receiver_free << " arb_remaining " << f->arbiter_remaining_num_pkts << 85 | " sender_last_pkt_sent " << f->sender_last_pkt_sent << "/" << f->size_in_pkt << "\n"; 86 | if(!sender_free) 87 | std::cout << "sender used by " << schedule[f->src->id]->id << " " << schedule[f->src->id]->src->id << "->" << schedule[f->src->id]->dst->id << "\n"; 88 | } 89 | 90 | if(f->arbiter_remaining_num_pkts > 0 && sender_free && receiver_free){ 91 | f->arbiter_remaining_num_pkts--; 92 | sender_used.insert(f->src->id); 93 | receiver_used.insert(f->dst->id); 94 | schedule[f->src->id] = f; 95 | if(debug_flow(f->id)) 96 | std::cout << get_current_time() << " scheduled flow " << f->id << " for epoch " << get_current_time() + params.fastpass_epoch_time << 97 | " remaining pkts " << f->arbiter_remaining_num_pkts << "\n"; 98 | } 99 | flows_tried.push(f); 100 | } 101 | 102 | while(!flows_tried.empty()) 103 | { 104 | sending_flows.push(flows_tried.front()); 105 | flows_tried.pop(); 106 | } 107 | 108 | 109 | return schedule; 110 | } 111 | 112 | 113 | void FastpassArbiter::schedule_proc_evt(double time) { 114 | if (this->arbiter_proc_evt != NULL) { 115 | this->arbiter_proc_evt->cancelled = true; 116 | this->arbiter_proc_evt = NULL; 117 | } 118 | this->arbiter_proc_evt = new ArbiterProcessingEvent(time, this); 119 | add_to_event_queue(this->arbiter_proc_evt); 120 | } 121 | 122 | void FastpassArbiter::schedule_epoch() { 123 | if (total_finished_flows >= params.num_flows_to_run) 124 | return; 125 | 126 | std::vector schedules; 127 | for (uint i = 0; i < params.num_hosts; i++){ 128 | schedules.push_back(new FastpassEpochSchedule(get_current_time() + params.fastpass_epoch_time)); 129 | } 130 | 131 | 132 | 133 | for(int i = 0; i < FASTPASS_EPOCH_PKTS; i++){ 134 | if(this->sending_flows.size() > 0){ 135 | std::map one_time_slot = schedule_timeslot(); 136 | 137 | for(auto iter = one_time_slot.begin(); iter != one_time_slot.end(); ++iter) 138 | { 139 | int sender = iter->first; 140 | FastpassFlow* f = iter->second; 141 | schedules[sender]->schedule[i] = f; 142 | } 143 | } 144 | } 145 | 146 | assert(this->queue->limit_bytes - this->queue->bytes_in_queue >= 144 * 40); 147 | 148 | for(int i = 0; i < params.num_hosts; i++) 149 | { 150 | FastpassFlow* f = schedules[i]->get_sender(); 151 | if(f) 152 | f->send_schedule_pkt(schedules[i]); 153 | else 154 | delete schedules[i]; 155 | } 156 | 157 | //schedule next arbiter proc evt 158 | this->schedule_proc_evt(get_current_time() + params.fastpass_epoch_time); 159 | } 160 | 161 | void FastpassArbiter::receive_rts(FastpassRTS* rts) 162 | { 163 | if(!((FastpassFlow*)rts->flow)->arbiter_received_rts) 164 | { 165 | ((FastpassFlow*) rts->flow)->arbiter_received_rts = true; 166 | dynamic_cast(topology)->arbiter->sending_flows.push((FastpassFlow*)rts->flow); 167 | } 168 | 169 | if(rts->remaining_num_pkts < 0){ 170 | ((FastpassFlow*)rts->flow)->arbiter_remaining_num_pkts = 0; 171 | ((FastpassFlow*)rts->flow)->arbiter_finished = true; 172 | } 173 | else 174 | ((FastpassFlow*)rts->flow)->arbiter_remaining_num_pkts = rts->remaining_num_pkts; 175 | } 176 | 177 | 178 | FastpassFlowProcessingEvent::FastpassFlowProcessingEvent(double time, FastpassFlow* f) 179 | : Event(FASTPASS_FLOW_PROCESSING, time) { 180 | this->flow = f; 181 | } 182 | 183 | FastpassFlowProcessingEvent::~FastpassFlowProcessingEvent() { 184 | } 185 | 186 | void FastpassFlowProcessingEvent::process_event() { 187 | this->flow->send_data_pkt(); 188 | } 189 | 190 | 191 | FastpassTimeoutEvent::FastpassTimeoutEvent(double time, FastpassFlow* f) : Event(FASTPASS_TIMEOUT, time) { 192 | this->flow = f; 193 | } 194 | 195 | FastpassTimeoutEvent::~FastpassTimeoutEvent() { 196 | } 197 | 198 | void FastpassTimeoutEvent::process_event() { 199 | this->flow->fastpass_timeout(); 200 | } 201 | 202 | -------------------------------------------------------------------------------- /ext/fastpasshost.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTPASS_HOST_H 2 | #define FASTPASS_HOST_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../coresim/node.h" 8 | #include "../coresim/packet.h" 9 | #include "../coresim/event.h" 10 | 11 | #include "../run/params.h" 12 | 13 | class ArbiterProcessingEvent; 14 | class FastpassFlow; 15 | 16 | class FastpassFlowComparator { 17 | public: 18 | bool operator() (FastpassFlow* a, FastpassFlow* b); 19 | }; 20 | 21 | class FastpassEpochSchedule { 22 | public: 23 | FastpassEpochSchedule(double s); 24 | FastpassFlow* get_sender(); 25 | double start_time; 26 | std::map schedule; 27 | }; 28 | 29 | class FastpassHost : public Host { 30 | public: 31 | FastpassHost(uint32_t id, double rate, uint32_t queue_type); 32 | void receive_schedule_pkt(FastpassSchedulePkt* pkt); 33 | }; 34 | 35 | class FastpassArbiter : public Host { 36 | public: 37 | FastpassArbiter(uint32_t id, double rate, uint32_t queue_type); 38 | void start_arbiter(); 39 | void schedule_proc_evt(double time); 40 | std::map schedule_timeslot(); 41 | void schedule_epoch(); 42 | void receive_rts(FastpassRTS* rts); 43 | 44 | ArbiterProcessingEvent* arbiter_proc_evt; 45 | std::priority_queue, FastpassFlowComparator> sending_flows; 46 | }; 47 | 48 | #define ARBITER_PROCESSING 14 49 | class ArbiterProcessingEvent : public Event { 50 | public: 51 | ArbiterProcessingEvent(double time, FastpassArbiter *host); 52 | ~ArbiterProcessingEvent(); 53 | void process_event(); 54 | FastpassArbiter* arbiter; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /ext/fountainflow.cpp: -------------------------------------------------------------------------------- 1 | #include "fountainflow.h" 2 | 3 | #include "../coresim/event.h" 4 | #include "../coresim/packet.h" 5 | #include "../coresim/debug.h" 6 | 7 | #include "schedulinghost.h" 8 | 9 | #include "../run/params.h" 10 | 11 | extern double get_current_time(); 12 | extern void add_to_event_queue(Event*); 13 | extern DCExpParams params; 14 | 15 | FountainFlow::FountainFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) : Flow(id, start_time, size, s, d) { 16 | this->goal = this->size_in_pkt; 17 | } 18 | 19 | void FountainFlow::send_pending_data() { 20 | if (this->finished) { 21 | return; 22 | } 23 | Packet *p = send(next_seq_no); 24 | next_seq_no += mss; 25 | //need to schedule next one 26 | double td = src->queue->get_transmission_delay(p->size); 27 | flow_proc_event = new FlowProcessingEvent(get_current_time() + td, this); 28 | add_to_event_queue(flow_proc_event); 29 | } 30 | 31 | Packet* FountainFlow::send(uint32_t seq) { 32 | uint32_t priority = 1; 33 | Packet *p = new Packet(get_current_time(), this, seq, priority, mss + hdr_size, src, dst); 34 | total_pkt_sent++; 35 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, src->queue)); 36 | return p; 37 | } 38 | 39 | void FountainFlow::send_ack() { 40 | Packet *ack = new PlainAck(this, 0, hdr_size, dst, src); 41 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), ack, dst->queue)); 42 | } 43 | 44 | void FountainFlow::receive(Packet *p) { 45 | if (this->finished) { 46 | return; 47 | } 48 | if (p->type == NORMAL_PACKET) { 49 | received_count++; 50 | //only send one ack per bdp 51 | if (received_count >= goal && (received_count - goal) % 7 == 0) { 52 | send_ack(); 53 | } 54 | } 55 | else if (p->type == ACK_PACKET) { 56 | if (flow_proc_event != NULL) { 57 | flow_proc_event->cancelled = true; 58 | } 59 | add_to_event_queue(new FlowFinishedEvent(get_current_time(), this)); 60 | } 61 | else if (p->type == RTS_PACKET){ 62 | 63 | } 64 | } 65 | 66 | 67 | FountainFlowWithSchedulingHost::FountainFlowWithSchedulingHost(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) : FountainFlow(id, start_time, size, s, d) { 68 | } 69 | 70 | void FountainFlowWithSchedulingHost::start_flow() { 71 | ((SchedulingHost*) this->src)->start(this); 72 | } 73 | 74 | void FountainFlowWithSchedulingHost::send_pending_data() { 75 | if (this->finished) { 76 | ((SchedulingHost*) this->src)->send(); 77 | return; 78 | } 79 | 80 | Packet *p = this->send(next_seq_no); 81 | next_seq_no += mss; 82 | 83 | double td = src->queue->get_transmission_delay(p->size); 84 | ((SchedulingHost*) src)->host_proc_event = new HostProcessingEvent(get_current_time() + td, (SchedulingHost*) src); 85 | add_to_event_queue(((SchedulingHost*) src)->host_proc_event); 86 | } 87 | 88 | void FountainFlowWithSchedulingHost::receive(Packet *p) { 89 | if (this->finished) { 90 | return; 91 | } 92 | if (p->type == NORMAL_PACKET) { 93 | received_count++; 94 | 95 | //only send one ack per bdp 96 | if (received_count >= goal && (received_count - goal) % 7 == 0) { 97 | send_ack(); 98 | } 99 | } 100 | else if (p->type == ACK_PACKET) { 101 | add_to_event_queue(new FlowFinishedEvent(get_current_time(), this)); 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /ext/fountainflow.h: -------------------------------------------------------------------------------- 1 | #ifndef FOUNTAIN_FLOW_H 2 | #define FOUNTAIN_FLOW_H 3 | 4 | #include 5 | #include "../coresim/flow.h" 6 | 7 | class FountainFlow : public Flow { 8 | public: 9 | FountainFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 10 | virtual void send_pending_data(); 11 | virtual void receive(Packet *p); 12 | virtual Packet* send(uint32_t seq); 13 | virtual void send_ack(); 14 | uint32_t goal; 15 | }; 16 | 17 | class FountainFlowWithSchedulingHost : public FountainFlow { 18 | public: 19 | FountainFlowWithSchedulingHost(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 20 | virtual void start_flow(); 21 | virtual void send_pending_data(); 22 | virtual void receive(Packet *p); 23 | }; 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /ext/ideal.cpp: -------------------------------------------------------------------------------- 1 | #include "ideal.h" 2 | 3 | #include 4 | #include "assert.h" 5 | 6 | extern DCExpParams params; 7 | 8 | extern double get_current_time(); 9 | extern void add_to_event_queue(Event *); 10 | extern uint32_t num_outstanding_packets; 11 | extern IdealArbiter* ideal_arbiter; 12 | 13 | IdealArbiter::IdealArbiter() { 14 | active_flows = new std::vector(); 15 | srcs = new std::array(); 16 | dsts = new std::array(); 17 | 18 | assert(srcs->size() == params.num_hosts); 19 | } 20 | 21 | bool compareFlows(IdealFlow* i, IdealFlow* j) { 22 | uint32_t i_remain = i->acked - i->size; 23 | uint32_t j_remain = j->acked - j->size; 24 | return i_remain > j_remain; 25 | } 26 | 27 | void IdealArbiter::flow_arrival(IdealFlow* f) { 28 | for (auto it = active_flows->begin(); it != active_flows->end(); it++) { 29 | assert(*it != f); 30 | } 31 | 32 | active_flows->push_back(f); 33 | std::stable_sort(active_flows->begin(), active_flows->end(), compareFlows); 34 | 35 | compute_schedule(); 36 | } 37 | 38 | void IdealArbiter::flow_finished(IdealFlow* f) { 39 | assert(f->sent >= f->size); 40 | ((IdealHost*) f->src)->active_flow = NULL; 41 | for (auto it = active_flows->begin(); it != active_flows->end(); it++) { 42 | if (*it == f) { 43 | active_flows->erase(it); 44 | compute_schedule(); 45 | return; 46 | } 47 | } 48 | } 49 | 50 | void IdealArbiter::compute_schedule() { 51 | srcs->fill(false); 52 | dsts->fill(false); 53 | 54 | for (auto it = active_flows->begin(); it != active_flows->end(); it++) { 55 | IdealFlow* f = (IdealFlow*) *it; 56 | if (f->finished) { 57 | if (((IdealHost*) f->src)->active_flow == f) { 58 | ((IdealHost*) f->src)->active_flow = NULL; 59 | } 60 | it = active_flows->erase(it); 61 | if (it == active_flows->end()) { 62 | break; 63 | } 64 | } 65 | if (!srcs->at(f->src->id) && !dsts->at(f->dst->id)) { 66 | auto previous = ((IdealHost*) f->src)->active_flow; 67 | if (previous != NULL && 68 | previous->id != f->id && 69 | ((IdealHost*) f->src)->host_proc_event != NULL 70 | ) { 71 | // new flow 72 | ((IdealHost*) f->src)->host_proc_event->cancelled = true; 73 | ((IdealHost*) f->src)->host_proc_event = NULL; 74 | } 75 | ((IdealHost*) f->src)->active_flow = f; 76 | 77 | srcs->at(f->src->id) = true; 78 | dsts->at(f->dst->id) = true; 79 | 80 | if (((IdealHost*) f->src)->host_proc_event == NULL || ((IdealHost*) f->src)->host_proc_event->cancelled) { 81 | ((IdealHost*) f->src)->host_proc_event = new HostProcessingEvent(get_current_time(), (IdealHost*) f->src); 82 | add_to_event_queue(((IdealHost*) f->src)->host_proc_event); 83 | } 84 | } 85 | } 86 | } 87 | 88 | IdealHost::IdealHost(uint32_t id, double rate, uint32_t queue_type) : SchedulingHost(id, rate, queue_type) { 89 | this->dispatch = ideal_arbiter; 90 | this->active_flow = NULL; 91 | } 92 | 93 | void IdealHost::start(Flow* f) { 94 | dispatch->flow_arrival((IdealFlow*) f); 95 | } 96 | 97 | void IdealHost::send() { 98 | // send packets from arbiter-assigned flow 99 | assert(host_proc_event == NULL); 100 | double td = this->queue->get_transmission_delay(params.mss + params.hdr_size); 101 | if (active_flow != NULL && !active_flow->finished) { 102 | assert(active_flow->src == this); 103 | 104 | host_proc_event = new HostProcessingEvent(get_current_time() + td + INFINITESIMAL_TIME, this); 105 | add_to_event_queue(host_proc_event); 106 | 107 | active_flow->send_pending_data(); 108 | } 109 | } 110 | 111 | IdealAck::IdealAck(Flow* flow, uint32_t recv, Host* src, Host* dst) : PlainAck(flow, 0, params.hdr_size, src, dst) { 112 | received = recv; 113 | } 114 | 115 | IdealFlow::IdealFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) : Flow(id, start_time, size, s, d) { 116 | received = 0; 117 | acked = 0; 118 | sent = 0; 119 | } 120 | 121 | void IdealFlow::start_flow() { 122 | ((IdealHost*) src)->start(this); 123 | } 124 | 125 | void IdealFlow::handle_timeout() { 126 | this->retx_event = NULL; 127 | if (!finished) { 128 | this->start_flow(); 129 | } 130 | } 131 | 132 | void IdealFlow::send_pending_data() { 133 | if (finished) { 134 | cancel_retx_event(); 135 | return; 136 | } 137 | 138 | // send a packet 139 | send(0); 140 | sent += mss; 141 | 142 | if (sent == size) { // if there was a timeout (sent > size), just wait for ACK 143 | assert(retx_event == NULL); 144 | set_timeout(get_current_time() + params.retx_timeout_value); 145 | 146 | ((IdealHost*) src)->host_proc_event->cancelled = true; 147 | ((IdealHost*) src)->dispatch->flow_finished(this); 148 | } 149 | } 150 | 151 | void IdealFlow::receive(Packet* p) { 152 | if (this->finished) { 153 | delete p; 154 | return; 155 | } 156 | 157 | Packet* ack; 158 | switch (p->type) { 159 | case NORMAL_PACKET: 160 | this->received += mss; 161 | ack = new IdealAck(this, this->received, this->dst, this->src); 162 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), ack, this->dst->queue)); 163 | break; 164 | case ACK_PACKET: 165 | if (((IdealAck*) p)->received < this->acked) { 166 | break; // old ack 167 | } 168 | 169 | this->acked = ((IdealAck*) p)->received; 170 | num_outstanding_packets -= 1; 171 | 172 | if (this->acked >= size) { 173 | assert(finished == false); 174 | 175 | if (retx_event != NULL) { 176 | if (id == 21) std::cout << get_current_time() * 1e6 << " 21 finished??\n"; 177 | cancel_retx_event(); 178 | } 179 | 180 | if (sent > size) { 181 | if (((IdealHost*) src)->host_proc_event != NULL) { 182 | ((IdealHost*) src)->host_proc_event->cancelled = true; 183 | } 184 | ((IdealHost*) src)->dispatch->flow_finished(this); 185 | } 186 | 187 | if (((IdealHost*) src)->active_flow == this) { 188 | ((IdealHost*) src)->active_flow = NULL; 189 | } 190 | 191 | finished = true; 192 | finish_time = get_current_time(); 193 | flow_completion_time = finish_time - start_time; 194 | FlowFinishedEvent *ev = new FlowFinishedEvent(get_current_time(), this); 195 | add_to_event_queue(ev); 196 | } 197 | break; 198 | default: 199 | assert(false); 200 | } 201 | 202 | delete p; 203 | } 204 | 205 | uint32_t IdealFlow::get_priority(uint32_t seq) { 206 | return size - acked; 207 | } 208 | -------------------------------------------------------------------------------- /ext/ideal.h: -------------------------------------------------------------------------------- 1 | #ifndef IDEAL_H 2 | #define IDEAL_H 3 | 4 | #include "../coresim/flow.h" 5 | #include "schedulinghost.h" 6 | 7 | #include "../run/params.h" 8 | 9 | #include 10 | 11 | class IdealFlow; 12 | 13 | class IdealArbiter { 14 | public: 15 | std::vector* active_flows; 16 | std::array* srcs; 17 | std::array* dsts; 18 | 19 | IdealArbiter(); 20 | void flow_arrival(IdealFlow* f); 21 | void flow_finished(IdealFlow* f); 22 | void compute_schedule(); 23 | }; 24 | 25 | class IdealHost : public SchedulingHost { 26 | public: 27 | IdealHost(uint32_t id, double rate, uint32_t queue_type); 28 | IdealArbiter* dispatch; 29 | IdealFlow* active_flow; 30 | 31 | virtual void start(Flow* f); 32 | virtual void send(); 33 | }; 34 | 35 | class IdealAck : public PlainAck { 36 | public: 37 | IdealAck(Flow* flow, uint32_t num_received, Host* src, Host* dst); 38 | uint32_t received; 39 | }; 40 | 41 | class IdealFlow : public Flow { 42 | public: 43 | IdealFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 44 | 45 | uint32_t sent; // Sender side 46 | uint32_t acked; 47 | 48 | uint32_t received; // Receiver side 49 | 50 | virtual void start_flow(); 51 | virtual void handle_timeout(); 52 | virtual void send_pending_data(); 53 | virtual void receive(Packet* p); 54 | virtual uint32_t get_priority(uint32_t seq); 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /ext/magicflow.cpp: -------------------------------------------------------------------------------- 1 | #include "../coresim/event.h" 2 | #include "../coresim/packet.h" 3 | 4 | #include "magicflow.h" 5 | #include "magichost.h" 6 | 7 | #include "../run/params.h" 8 | 9 | extern DCExpParams params; 10 | extern double get_current_time(); 11 | extern void add_to_event_queue(Event*); 12 | 13 | MagicFlow::MagicFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) 14 | : FountainFlowWithSchedulingHost(id, start_time, size, s, d) { 15 | this->send_count = 0; 16 | this->remaining_pkt_this_round = 0; 17 | this->ack_timeout = 0; 18 | this->virtual_rts_send_count = 0; 19 | if (params.magic_inflate == 1) { 20 | this->added_infl_time = false; 21 | } 22 | else { 23 | this->added_infl_time = true; 24 | } 25 | } 26 | 27 | void MagicFlow::start_flow() { 28 | if (!this->added_infl_time) { 29 | add_to_event_queue(new FlowArrivalEvent(get_current_time() + 1.6e-6, this)); 30 | this->added_infl_time = true; 31 | return; 32 | } 33 | else { 34 | FountainFlowWithSchedulingHost::start_flow(); 35 | } 36 | } 37 | 38 | double MagicFlow::get_propa_time(){ 39 | //return this->src->id/16 == this->dst->id/16?0.0000016:0.0000026; 40 | return 0.0000026; 41 | } 42 | 43 | Packet* MagicFlow::send(uint32_t seq) { 44 | uint32_t priority = 1; 45 | if(this->size_in_pkt > 8) 46 | priority = 2; 47 | //priority = this->remaining_pkt(); 48 | Packet *p = new Packet(get_current_time(), this, seq, priority, mss + hdr_size, src, dst); 49 | total_pkt_sent++; 50 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), p, src->queue)); 51 | return p; 52 | } 53 | 54 | void MagicFlow::send_pending_data() { 55 | Packet *p = this->send(next_seq_no); 56 | next_seq_no += mss; 57 | this->send_count++; 58 | assert(this->remaining_pkt_this_round > 0); 59 | this->remaining_pkt_this_round--; 60 | 61 | if(((SchedulingHost*) src)->host_proc_event == NULL || ((MagicHost*) src)->is_host_proc_event_a_timeout){ 62 | if(((SchedulingHost*) src)->host_proc_event) 63 | ((SchedulingHost*) src)->host_proc_event->cancelled = true; 64 | double td = src->queue->get_transmission_delay(p->size); 65 | ((SchedulingHost*) src)->host_proc_event = new HostProcessingEvent(get_current_time() + td, (SchedulingHost*) src); 66 | add_to_event_queue(((SchedulingHost*) src)->host_proc_event); 67 | } 68 | } 69 | 70 | void MagicFlow::receive(Packet *p) { 71 | if (this->finished) { 72 | return; 73 | } 74 | if (p->type == NORMAL_PACKET) { 75 | received_count++; 76 | received_bytes += (p->size - hdr_size); 77 | //only send one ack per bdp 78 | // if (received_count == size_in_pkt){ 79 | // assert( this == ((QuickSchedulingHost*)(this->dst))->flow_receiving ); 80 | // ((QuickSchedulingHost*)(this->dst))->flow_receiving = NULL; 81 | // } 82 | 83 | if (received_count >= goal) { 84 | send_ack(); 85 | } 86 | } 87 | else if (p->type == ACK_PACKET) { 88 | //assert(this == ((QuickSchedulingHost*)(this->src))->flow_sending ); 89 | this->finished = true; 90 | //((QuickSchedulingHost*)(this->src))->flow_sending = NULL; 91 | //((QuickSchedulingHost*)(this->src))->schedule(); 92 | add_to_event_queue(new FlowFinishedEvent(get_current_time(), this)); 93 | } 94 | delete p; 95 | } 96 | 97 | double MagicFlow::estimated_finish_time() { 98 | if(this->finished || received_count >= size_in_pkt) 99 | return get_current_time(); 100 | else 101 | return get_current_time() + (size_in_pkt - received_count) * 0.0000013; 102 | } 103 | 104 | unsigned MagicFlow::remaining_pkt() { 105 | return (uint)std::max((int)size_in_pkt - (int)received_count, (int)0); 106 | } 107 | 108 | -------------------------------------------------------------------------------- /ext/magicflow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAGIC_FLOW_H 2 | #define MAGIC_FLOW_H 3 | 4 | #include 5 | #include "fountainflow.h" 6 | 7 | class MagicFlow : public FountainFlowWithSchedulingHost { 8 | public: 9 | MagicFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 10 | virtual void start_flow(); 11 | virtual void receive(Packet *p); 12 | virtual void send_pending_data(); 13 | double estimated_finish_time(); 14 | unsigned remaining_pkt(); 15 | double get_propa_time(); 16 | Packet* send(uint32_t seq); 17 | double schedule_time; 18 | double ack_timeout; 19 | int send_count; 20 | int virtual_rts_send_count; 21 | int remaining_pkt_this_round; 22 | double last_pkt_sent_at; 23 | double total_waiting_time; 24 | 25 | bool added_infl_time; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /ext/magichost.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../coresim/event.h" 4 | #include "../coresim/flow.h" 5 | #include "../coresim/debug.h" 6 | 7 | #include "magichost.h" 8 | #include "magicflow.h" 9 | #include "factory.h" 10 | 11 | #include "../run/params.h" 12 | 13 | extern double get_current_time(); 14 | extern void add_to_event_queue(Event*); 15 | extern DCExpParams params; 16 | 17 | MagicHostScheduleEvent::MagicHostScheduleEvent(double time, MagicHost *h) : Event(MAGIC_HOST_SCHEDULE, time) { 18 | this->host = h; 19 | } 20 | 21 | MagicHostScheduleEvent::~MagicHostScheduleEvent() { 22 | } 23 | 24 | void MagicHostScheduleEvent::process_event() { 25 | //std::cout << "calling schd() at event.cpp 369 for host" << this->host->id << "\n"; 26 | this->host->schedule(); 27 | this->host->try_send(); 28 | } 29 | 30 | bool has_higher_priority(MagicFlow* a, MagicFlow* b) { 31 | // use FIFO ordering since all flows are same size 32 | if(a->size_in_pkt < b->size_in_pkt) 33 | return true; 34 | else if(a->size_in_pkt == b->size_in_pkt) 35 | return a->remaining_pkt() < b->remaining_pkt(); 36 | else 37 | return false; 38 | } 39 | 40 | bool MagicHostFlowComparator::operator() (MagicFlow* a, MagicFlow* b) { 41 | // use FIFO ordering since all flows are same size 42 | if(a->remaining_pkt() > b->remaining_pkt()) 43 | return true; 44 | else if(a->remaining_pkt() == b->remaining_pkt()) 45 | return a->start_time > b->start_time; 46 | else 47 | return false; 48 | } 49 | 50 | 51 | bool MagicFlowTimeoutComparator::operator() (MagicFlow* a, MagicFlow* b) { 52 | // use FIFO ordering since all flows are same size 53 | return a->ack_timeout > b->ack_timeout; 54 | } 55 | 56 | 57 | 58 | 59 | MagicHost::MagicHost(uint32_t id, double rate, uint32_t queue_type) : SchedulingHost(id, rate, queue_type) { 60 | this->flow_sending = NULL; 61 | this->recv_busy_until = 0; 62 | this->host_type = MAGIC_HOST; 63 | } 64 | 65 | void MagicHost::start(Flow* f) { 66 | if(debug_flow(f->id) || debug_host(this->id)) 67 | std::cout << get_current_time() << " host:" << this->id << " flow started " << f->id << " " << f->src->id << "->" << f->dst->id << " sz:" << f->size_in_pkt << "\n"; 68 | 69 | ((MagicFlow*)f)->last_pkt_sent_at = get_current_time(); 70 | 71 | this->active_sending_flows.push((MagicFlow*)f); 72 | 73 | 74 | this->schedule(); 75 | this->try_send(); 76 | 77 | } 78 | 79 | 80 | void MagicHost::schedule() { 81 | 82 | if(debug_host(this->id)) 83 | std::cout << get_current_time() << " host:" << this->id << " calling schedule()\n"; 84 | 85 | if(this->flow_sending == NULL){ 86 | bool scheduled = false; 87 | double min_finish_time = 999999; 88 | 89 | std::queue flows_tried; 90 | 91 | bool has_short_flow_to_delay = false; 92 | while(!active_sending_flows.empty()){ 93 | MagicFlow* f = (MagicFlow*)active_sending_flows.top(); 94 | active_sending_flows.pop(); 95 | 96 | if(f->finished) 97 | continue; 98 | 99 | if (f->ack_timeout > get_current_time()){ 100 | if(f->ack_timeout < min_finish_time ) 101 | min_finish_time = f->ack_timeout; 102 | flows_tried.push(f); 103 | } 104 | else if(((MagicHost*)(f->dst))->recv_busy_until <= get_current_time() + f->get_propa_time() * params.magic_trans_slack 105 | || f->size_in_pkt < ((MagicHost*)(f->dst))->flow_receiving->size_in_pkt 106 | ){ 107 | //schedule the current flow 108 | f->virtual_rts_send_count++; 109 | f->schedule_time = get_current_time(); 110 | f->total_waiting_time += get_current_time() - f->last_pkt_sent_at; 111 | assert(((MagicHost*)(f->src))->flow_sending == NULL); 112 | //if(debug_flow(f->id)) 113 | // std::cout << get_current_time() << "!!!!!!!!! host:" << f->src->id << " flow_sending setting to f " << f->id << "\n"; 114 | 115 | ((MagicHost*)(f->src))->flow_sending = f; 116 | ((MagicHost*)(f->dst))->flow_receiving = f; 117 | int pkt_to_schd = std::max((unsigned)1, std::min((unsigned)params.reauth_limit, f->remaining_pkt())); 118 | f->remaining_pkt_this_round = pkt_to_schd; 119 | ((MagicHost*)(f->dst))->recv_busy_until = get_current_time() + f->get_propa_time() + 0.0000012 * pkt_to_schd; 120 | scheduled = true; 121 | break; 122 | } 123 | else 124 | { 125 | f->virtual_rts_send_count++; 126 | if(((MagicHost*)(f->dst))->recv_busy_until < min_finish_time ){ 127 | assert(((MagicHost*)(f->dst))->recv_busy_until - f->get_propa_time() * params.magic_trans_slack > get_current_time()); 128 | min_finish_time = ((MagicHost*)(f->dst))->recv_busy_until - f->get_propa_time() * params.magic_trans_slack; 129 | } 130 | 131 | flows_tried.push(f); 132 | 133 | if(params.magic_delay_scheduling){ 134 | double slack = ((MagicHost*)(f->dst))->recv_busy_until - (get_current_time() + f->get_propa_time() * params.magic_trans_slack); 135 | if(f->size_in_pkt < 10 && slack < params.reauth_limit * 0.0000012 * 0.9){ 136 | has_short_flow_to_delay = true; 137 | } 138 | if(active_sending_flows.size() > 0 && active_sending_flows.top()->size_in_pkt > 10 && has_short_flow_to_delay) 139 | break; 140 | } 141 | } 142 | } 143 | 144 | //push flows back 145 | while(!flows_tried.empty()){ 146 | Flow* f = flows_tried.front(); 147 | flows_tried.pop(); 148 | active_sending_flows.push((MagicFlow*)f); 149 | } 150 | 151 | //has sending flow, but no flow can be scheduled 152 | if(!scheduled && !active_sending_flows.empty() && min_finish_time < 999999){ 153 | if (min_finish_time > get_current_time()) 154 | add_to_event_queue(new MagicHostScheduleEvent(min_finish_time, this) ); 155 | else 156 | add_to_event_queue(new MagicHostScheduleEvent(min_finish_time, this) ); 157 | } 158 | } 159 | } 160 | 161 | void MagicHost::reschedule(){ 162 | ((MagicFlow*)this->flow_sending)->last_pkt_sent_at = get_current_time(); 163 | this->flow_sending = NULL; 164 | this->schedule(); 165 | } 166 | 167 | void MagicHost::try_send() { 168 | if(this->host_proc_event == NULL || this->is_host_proc_event_a_timeout){ 169 | send(); 170 | } 171 | } 172 | 173 | void MagicHost::send() { 174 | 175 | if(debug_host(this->id)) 176 | std::cout << get_current_time() << " send at host " << this->id << "\n"; 177 | 178 | if(this->flow_sending && this->flow_sending->finished) 179 | { 180 | if(debug_host(this->id)) 181 | std::cout << get_current_time() << " reschedule() at host " << this->id << " flow finished " << this->flow_sending->id << "\n"; 182 | this->reschedule(); 183 | } 184 | 185 | 186 | 187 | if(this->flow_sending && ((MagicFlow*)(this->flow_sending))->remaining_pkt_this_round == 0 ){ 188 | if( ((MagicFlow*)(this->flow_sending))->send_count >= (int)ceil(this->flow_sending->size_in_pkt * 1) ){ 189 | ((MagicFlow*)(this->flow_sending))->ack_timeout = get_current_time() + 0.0000095; 190 | } 191 | this->active_sending_flows.push((MagicFlow*)(this->flow_sending)); 192 | this->reschedule(); 193 | } 194 | 195 | 196 | 197 | if(this->queue->busy){ 198 | //queue busy, try send later 199 | if(this->host_proc_event == NULL){ 200 | QueueProcessingEvent *qpe = this->queue->queue_proc_event; 201 | uint32_t queue_size = this->queue->bytes_in_queue; 202 | double td = this->queue->get_transmission_delay(queue_size); 203 | this->host_proc_event = new HostProcessingEvent(qpe->time + td + INFINITESIMAL_TIME, this); 204 | this->is_host_proc_event_a_timeout = false; 205 | add_to_event_queue(this->host_proc_event); 206 | } 207 | }else{ 208 | //queue free, try send and schedule another HostProcessingEvent 209 | if(this->flow_sending) 210 | { 211 | if(debug_flow(this->flow_sending->id)) 212 | std::cout << get_current_time() << " flow " << this->flow_sending->id << " send pkt " << this->flow_sending->total_pkt_sent << "\n"; 213 | this->flow_sending->send_pending_data(); 214 | this->is_host_proc_event_a_timeout = false; 215 | } 216 | 217 | } 218 | 219 | 220 | } 221 | 222 | -------------------------------------------------------------------------------- /ext/magichost.h: -------------------------------------------------------------------------------- 1 | #ifndef MAGIC_HOST_H 2 | #define MAGIC_HOST_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../coresim/node.h" 9 | #include "../coresim/packet.h" 10 | #include "../coresim/event.h" 11 | 12 | #include "schedulinghost.h" 13 | 14 | class MagicFlow; 15 | class MagicHostScheduleEvent; 16 | 17 | class MagicHostFlowComparator { 18 | public: 19 | bool operator() (MagicFlow* a, MagicFlow* b); 20 | }; 21 | 22 | class MagicFlowTimeoutComparator{ 23 | public: 24 | bool operator() (MagicFlow* a, MagicFlow* b); 25 | }; 26 | 27 | class MagicHost : public SchedulingHost { 28 | public: 29 | MagicHost(uint32_t id, double rate, uint32_t queue_type); 30 | void start(Flow* f); 31 | void schedule(); 32 | void reschedule(); 33 | void try_send(); 34 | void send(); 35 | Flow* flow_sending; 36 | MagicFlow* flow_receiving; 37 | //Flow* flow_receiving; 38 | double recv_busy_until; 39 | bool is_host_proc_event_a_timeout; 40 | std::priority_queue, MagicHostFlowComparator> active_sending_flows; 41 | std::priority_queue, MagicFlowTimeoutComparator> sending_redundency; 42 | std::map receiver_pending_flows; 43 | }; 44 | 45 | #define MAGIC_HOST_SCHEDULE 12 46 | class MagicHostScheduleEvent : public Event { 47 | public: 48 | MagicHostScheduleEvent(double time, MagicHost *host); 49 | ~MagicHostScheduleEvent(); 50 | void process_event(); 51 | MagicHost *host; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /ext/pfabricflow.cpp: -------------------------------------------------------------------------------- 1 | #include "pfabricflow.h" 2 | 3 | 4 | /* Implementation for pFabric Flow */ 5 | 6 | PFabricFlow::PFabricFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d) 7 | : Flow(id, start_time, size, s, d) { 8 | //Congestion window parameters 9 | this->ssthresh = 100000; 10 | this->count_ack_additive_increase = 0; 11 | } 12 | 13 | void PFabricFlow::increase_cwnd() { 14 | if (cwnd_mss < ssthresh) { // slow start 15 | cwnd_mss += 1; 16 | } 17 | else { // additive increase 18 | if (++count_ack_additive_increase >= cwnd_mss) { 19 | count_ack_additive_increase = 0; 20 | cwnd_mss += 1; 21 | } 22 | } 23 | // Check if we exceed max_cwnd 24 | if (cwnd_mss > max_cwnd) { 25 | cwnd_mss = max_cwnd; 26 | } 27 | } 28 | 29 | void PFabricFlow::handle_timeout() { 30 | ssthresh = cwnd_mss / 2; 31 | if (ssthresh < 2) { 32 | ssthresh = 2; 33 | } 34 | Flow::handle_timeout(); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ext/pfabricflow.h: -------------------------------------------------------------------------------- 1 | #ifndef PFABRIC_FLOW_H 2 | #define PFABRIC_FLOW_H 3 | 4 | #include "../coresim/flow.h" 5 | #include "../coresim/node.h" 6 | 7 | class PFabricFlow : public Flow { 8 | public: 9 | PFabricFlow(uint32_t id, double start_time, uint32_t size, Host *s, Host *d); 10 | uint32_t ssthresh; 11 | uint32_t count_ack_additive_increase; 12 | virtual void increase_cwnd(); 13 | virtual void handle_timeout(); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /ext/pfabricqueue.cpp: -------------------------------------------------------------------------------- 1 | #include "pfabricqueue.h" 2 | #include "../run/params.h" 3 | 4 | #include 5 | #include 6 | 7 | extern double get_current_time(); 8 | extern void add_to_event_queue(Event *ev); 9 | extern DCExpParams params; 10 | 11 | /* PFabric Queue */ 12 | PFabricQueue::PFabricQueue(uint32_t id, double rate, uint32_t limit_bytes, int location) 13 | : Queue(id, rate, limit_bytes, location) {} 14 | 15 | void PFabricQueue::enque(Packet *packet) { 16 | p_arrivals += 1; 17 | b_arrivals += packet->size; 18 | packets.push_back(packet); 19 | bytes_in_queue += packet->size; 20 | packet->last_enque_time = get_current_time(); 21 | if (bytes_in_queue > limit_bytes) { 22 | uint32_t worst_priority = 0; 23 | uint32_t worst_index = 0; 24 | for (uint32_t i = 0; i < packets.size(); i++) { 25 | if (packets[i]->pf_priority >= worst_priority) { 26 | worst_priority = packets[i]->pf_priority; 27 | worst_index = i; 28 | } 29 | } 30 | bytes_in_queue -= packets[worst_index]->size; 31 | Packet *worst_packet = packets[worst_index]; 32 | 33 | packets.erase(packets.begin() + worst_index); 34 | pkt_drop++; 35 | drop(worst_packet); 36 | } 37 | } 38 | 39 | Packet* PFabricQueue::deque() { 40 | if (bytes_in_queue > 0) { 41 | 42 | uint32_t best_priority = UINT_MAX; 43 | Packet *best_packet = NULL; 44 | uint32_t best_index = 0; 45 | for (uint32_t i = 0; i < packets.size(); i++) { 46 | Packet* curr_pkt = packets[i]; 47 | if (curr_pkt->pf_priority < best_priority) { 48 | best_priority = curr_pkt->pf_priority; 49 | best_packet = curr_pkt; 50 | best_index = i; 51 | } 52 | } 53 | 54 | for (uint32_t i = 0; i < packets.size(); i++) { 55 | Packet* curr_pkt = packets[i]; 56 | if (curr_pkt->flow->id == best_packet->flow->id) { 57 | best_index = i; 58 | break; 59 | } 60 | } 61 | Packet *p = packets[best_index]; 62 | bytes_in_queue -= p->size; 63 | packets.erase(packets.begin() + best_index); 64 | 65 | p_departures += 1; 66 | b_departures += p->size; 67 | 68 | p->total_queuing_delay += get_current_time() - p->last_enque_time; 69 | 70 | if(p->type == NORMAL_PACKET){ 71 | if(p->flow->first_byte_send_time < 0) 72 | p->flow->first_byte_send_time = get_current_time(); 73 | if(this->location == 0) 74 | p->flow->first_hop_departure++; 75 | if(this->location == 3) 76 | p->flow->last_hop_departure++; 77 | } 78 | return p; 79 | 80 | } else { 81 | return NULL; 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /ext/pfabricqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef PFABRIC_QUEUE_H 2 | #define PFABRIC_QUEUE_H 3 | 4 | #include "../coresim/queue.h" 5 | #include "../coresim/packet.h" 6 | 7 | #define PFABRIC_QUEUE 2 8 | 9 | class PFabricQueue : public Queue { 10 | public: 11 | PFabricQueue(uint32_t id, double rate, uint32_t limit_bytes, int location); 12 | void enque(Packet *packet); 13 | Packet *deque(); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /ext/schedulinghost.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../coresim/flow.h" 4 | #include "../coresim/packet.h" 5 | #include "../coresim/event.h" 6 | 7 | #include "factory.h" 8 | #include "schedulinghost.h" 9 | 10 | #include "../run/params.h" 11 | 12 | extern double get_current_time(); 13 | extern void add_to_event_queue(Event*); 14 | extern DCExpParams params; 15 | 16 | HostProcessingEvent::HostProcessingEvent(double time, SchedulingHost *h) : Event(HOST_PROCESSING, time) { 17 | this->host = h; 18 | } 19 | 20 | HostProcessingEvent::~HostProcessingEvent() { 21 | if (host->host_proc_event == this) { 22 | host->host_proc_event = NULL; 23 | } 24 | } 25 | 26 | void HostProcessingEvent::process_event() { 27 | this->host->host_proc_event = NULL; 28 | this->host->send(); 29 | } 30 | 31 | bool HostFlowComparator::operator() (Flow* a, Flow* b) { 32 | // use FIFO ordering since all flows are same size 33 | return a->start_time > b->start_time; 34 | } 35 | 36 | SchedulingHost::SchedulingHost(uint32_t id, double rate, uint32_t queue_type) : Host(id, rate, queue_type, SCHEDULING_HOST) { 37 | this->host_proc_event = NULL; 38 | } 39 | 40 | void SchedulingHost::start(Flow* f) { 41 | this->sending_flows.push(f); 42 | if (this->host_proc_event == NULL || this->host_proc_event->time < get_current_time()) { 43 | this->send(); 44 | } 45 | else if (this->host_proc_event->host != this) { 46 | assert(false); 47 | } 48 | } 49 | 50 | void SchedulingHost::send() { 51 | if (this->sending_flows.empty()) { 52 | return; 53 | } 54 | 55 | if (!this->queue->busy) { 56 | while (!this->sending_flows.empty() && (this->sending_flows.top())->finished) { 57 | this->sending_flows.pop(); 58 | } 59 | if (this->sending_flows.empty()) { 60 | return; 61 | } 62 | (this->sending_flows.top())->send_pending_data(); 63 | } 64 | else { 65 | QueueProcessingEvent *qpe = this->queue->queue_proc_event; 66 | uint32_t queue_size = this->queue->bytes_in_queue; 67 | double td = this->queue->get_transmission_delay(queue_size); 68 | this->host_proc_event = new HostProcessingEvent(qpe->time + td, this); 69 | add_to_event_queue(this->host_proc_event); 70 | } 71 | } 72 | 73 | -------------------------------------------------------------------------------- /ext/schedulinghost.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEDULING_HOST_H 2 | #define SCHEDULING_HOST_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../coresim/node.h" 8 | #include "../coresim/packet.h" 9 | #include "../coresim/event.h" 10 | 11 | class Flow; 12 | class HostProcessingEvent; 13 | 14 | class HostFlowComparator { 15 | public: 16 | bool operator() (Flow* a, Flow* b); 17 | }; 18 | 19 | class SchedulingHost : public Host { 20 | public: 21 | SchedulingHost(uint32_t id, double rate, uint32_t queue_type); 22 | virtual void start(Flow* f); 23 | virtual void send(); 24 | std::priority_queue, HostFlowComparator> sending_flows; 25 | HostProcessingEvent* host_proc_event; 26 | }; 27 | 28 | #define HOST_PROCESSING 10 29 | class HostProcessingEvent : public Event { 30 | public: 31 | HostProcessingEvent(double time, SchedulingHost *host); 32 | ~HostProcessingEvent(); 33 | void process_event(); 34 | SchedulingHost *host; 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ext/tcpflow.cpp: -------------------------------------------------------------------------------- 1 | #include "tcpflow.h" 2 | 3 | #include "../coresim/event.h" 4 | 5 | extern double get_current_time(); 6 | extern void add_to_event_queue(Event* ev); 7 | 8 | TCPFlow::TCPFlow(uint32_t id, double start_time, uint32_t size, Host* s, Host* d) : Flow(id, start_time, size, s, d) { 9 | this->cwnd_mss = 1; 10 | } 11 | 12 | void TCPFlow::start_flow() { 13 | //send SYN 14 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), new RTSCTS(true, get_current_time(), this, hdr_size, this->src, this->dst), this->src->queue)); 15 | } 16 | 17 | void TCPFlow::receive(Packet* p) { 18 | if (p->type == RTS_PACKET) { 19 | // send SYNACK 20 | add_to_event_queue(new PacketQueuingEvent(get_current_time(), new RTSCTS(false, get_current_time(), this, hdr_size, this->dst, this->src), this->dst->queue)); 21 | } 22 | else if (p->type == CTS_PACKET) { 23 | // got SYNACK 24 | send_pending_data(); 25 | } 26 | else { 27 | Flow::receive(p); 28 | } 29 | } 30 | 31 | uint32_t TCPFlow::get_priority(uint32_t seq) { 32 | return 1; 33 | } 34 | -------------------------------------------------------------------------------- /ext/tcpflow.h: -------------------------------------------------------------------------------- 1 | #ifndef TCP_FLOW_H 2 | #define TCP_FLOW_H 3 | 4 | #include "../coresim/flow.h" 5 | #include "../coresim/node.h" 6 | #include "../coresim/packet.h" 7 | 8 | class TCPFlow : public Flow { 9 | public: 10 | TCPFlow(uint32_t id, double start_time, uint32_t size, Host* s, Host* d); 11 | virtual void start_flow(); 12 | virtual void receive(Packet *p); 13 | virtual uint32_t get_priority(uint32_t seq); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /py/CDF_aditya.txt: -------------------------------------------------------------------------------- 1 | 1 1 0 2 | 1 1 0.500000 3 | 2 1 0.600000 4 | 3 1 0.700000 5 | 5 1 0.750000 6 | 7 1 0.800000 7 | 40 1 0.812500 8 | 72 1 0.825000 9 | 137 1 0.850000 10 | 267 1 0.900000 11 | 1187 1 0.95000 12 | 2107 1 1.0 13 | -------------------------------------------------------------------------------- /py/CDF_datamining.txt: -------------------------------------------------------------------------------- 1 | 1 1 0 2 | 1 1 0.5 3 | 2 1 0.6 4 | 3 1 0.7 5 | 7 1 0.8 6 | 267 1 0.9 7 | 2107 1 0.95 8 | 66667 1 0.99 9 | 666667 1 1 10 | -------------------------------------------------------------------------------- /py/CDF_dctcp.txt: -------------------------------------------------------------------------------- 1 | 6 1 0 2 | 6 1 0.15 3 | 13 1 0.2 4 | 19 1 0.3 5 | 33 1 0.4 6 | 53 1 0.53 7 | 133 1 0.6 8 | 667 1 0.7 9 | 1333 1 0.8 10 | 3333 1 0.9 11 | 6667 1 0.97 12 | 20000 1 1 13 | -------------------------------------------------------------------------------- /py/run_experiments.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import subprocess 4 | import threading 5 | import multiprocessing 6 | 7 | conf_str_pfabric = '''init_cwnd: 12 8 | max_cwnd: 15 9 | retx_timeout: 45e-06 10 | queue_size: 36864 11 | propagation_delay: 0.0000002 12 | bandwidth: 40000000000.0 13 | queue_type: 2 14 | flow_type: 2 15 | num_flow: {0} 16 | flow_trace: ./{1} 17 | cut_through: 1 18 | mean_flow_size: 0 19 | load_balancing: 0 20 | preemptive_queue: 0 21 | big_switch: 0 22 | host_type: 1 23 | traffic_imbalance: 0 24 | load: 0.6 25 | reauth_limit: 3 26 | magic_trans_slack: 1.1 27 | magic_delay_scheduling: 1 28 | use_flow_trace: 0 29 | smooth_cdf: 1 30 | burst_at_beginning: 0 31 | capability_timeout: 1.5 32 | capability_resend_timeout: 9 33 | capability_initial: 8 34 | capability_window: 8 35 | capability_window_timeout: 25 36 | ddc: 0 37 | ddc_cpu_ratio: 0.33 38 | ddc_mem_ratio: 0.33 39 | ddc_disk_ratio: 0.34 40 | ddc_normalize: 2 41 | ddc_type: 0 42 | deadline: 0 43 | schedule_by_deadline: 0 44 | avg_deadline: 0.0001 45 | capability_third_level: 1 46 | capability_fourth_level: 0 47 | magic_inflate: 1 48 | interarrival_cdf: none 49 | num_host_types: 13 50 | permutation_tm: 1 51 | 52 | ''' 53 | 54 | conf_str_phost = '''init_cwnd: 2 55 | max_cwnd: 6 56 | retx_timeout: 9.50003e-06 57 | queue_size: 36864 58 | propagation_delay: 0.0000002 59 | bandwidth: 40000000000.0 60 | queue_type: 2 61 | flow_type: 112 62 | num_flow: {0} 63 | flow_trace: ./{1} 64 | cut_through: 1 65 | mean_flow_size: 0 66 | load_balancing: 0 67 | preemptive_queue: 0 68 | big_switch: 0 69 | host_type: 12 70 | traffic_imbalance: 0 71 | load: 0.6 72 | reauth_limit: 3 73 | magic_trans_slack: 1.1 74 | magic_delay_scheduling: 1 75 | use_flow_trace: 0 76 | smooth_cdf: 1 77 | burst_at_beginning: 0 78 | capability_timeout: 1.5 79 | capability_resend_timeout: 9 80 | capability_initial: 8 81 | capability_window: 8 82 | capability_window_timeout: 25 83 | ddc: 0 84 | ddc_cpu_ratio: 0.33 85 | ddc_mem_ratio: 0.33 86 | ddc_disk_ratio: 0.34 87 | ddc_normalize: 2 88 | ddc_type: 0 89 | deadline: 0 90 | schedule_by_deadline: 0 91 | avg_deadline: 0.0001 92 | capability_third_level: 1 93 | capability_fourth_level: 0 94 | magic_inflate: 1 95 | interarrival_cdf: none 96 | num_host_types: 13 97 | permutation_tm: 1 98 | 99 | ''' 100 | 101 | conf_str_fastpass = '''init_cwnd: 6 102 | max_cwnd: 12 103 | retx_timeout: 45e-06 104 | queue_size: 36864 105 | propagation_delay: 0.0000002 106 | bandwidth: 40000000000.0 107 | queue_type: 2 108 | flow_type: 114 109 | num_flow: {0} 110 | flow_trace: ./{1} 111 | cut_through: 1 112 | mean_flow_size: 0 113 | load_balancing: 0 114 | preemptive_queue: 0 115 | big_switch: 0 116 | host_type: 14 117 | traffic_imbalance: 0 118 | load: 0.6 119 | reauth_limit: 3 120 | magic_trans_slack: 1.1 121 | magic_delay_scheduling: 1 122 | use_flow_trace: 0 123 | smooth_cdf: 1 124 | burst_at_beginning: 0 125 | capability_timeout: 1.5 126 | capability_resend_timeout: 9 127 | capability_initial: 8 128 | capability_window: 8 129 | capability_window_timeout: 25 130 | ddc: 0 131 | ddc_cpu_ratio: 0.33 132 | ddc_mem_ratio: 0.33 133 | ddc_disk_ratio: 0.34 134 | ddc_normalize: 2 135 | ddc_type: 0 136 | deadline: 0 137 | schedule_by_deadline: 0 138 | avg_deadline: 0.0001 139 | capability_third_level: 1 140 | capability_fourth_level: 0 141 | magic_inflate: 1 142 | interarrival_cdf: none 143 | num_host_types: 13 144 | permutation_tm: 1 145 | 146 | ''' 147 | 148 | 149 | template = '../simulator 1 conf_{0}_{1}.txt > result_{0}_{1}.txt' 150 | cdf_temp = './CDF_{}.txt' 151 | 152 | runs = ['pfabric', 'phost', 'fastpass'] 153 | workloads = ['aditya', 'dctcp', 'datamining'] 154 | 155 | def getNumLines(trace): 156 | out = subprocess.check_output('wc -l {}'.format(trace), shell=True) 157 | return int(out.split()[0]) 158 | 159 | 160 | def run_exp(rw, semaphore): 161 | semaphore.acquire() 162 | print template.format(*rw) 163 | subprocess.call(template.format(*rw), shell=True) 164 | semaphore.release() 165 | 166 | threads = [] 167 | semaphore = threading.Semaphore(multiprocessing.cpu_count()) 168 | 169 | for r in runs: 170 | for w in workloads: 171 | cdf = cdf_temp.format(w) 172 | numLines = 1000000 173 | 174 | # generate conf file 175 | if r == 'pfabric': 176 | conf_str = conf_str_pfabric.format(numLines, cdf) 177 | elif r == 'phost': 178 | conf_str = conf_str_phost.format(numLines, cdf) 179 | elif r == 'fastpass': 180 | conf_str = conf_str_fastpass.format(numLines, cdf) 181 | else: 182 | assert False, r 183 | 184 | confFile = "conf_{0}_{1}.txt".format(r, w) 185 | with open(confFile, 'w') as f: 186 | print confFile 187 | f.write(conf_str) 188 | 189 | threads.append(threading.Thread(target=run_exp, args=((r, w), semaphore))) 190 | 191 | print '\n' 192 | [t.start() for t in threads] 193 | [t.join() for t in threads] 194 | print 'finished', len(threads), 'experiments' 195 | -------------------------------------------------------------------------------- /run/experiment.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "assert.h" 12 | #include "math.h" 13 | 14 | #include "../coresim/flow.h" 15 | #include "../coresim/packet.h" 16 | #include "../coresim/node.h" 17 | #include "../coresim/event.h" 18 | #include "../coresim/topology.h" 19 | #include "../coresim/queue.h" 20 | #include "../coresim/random_variable.h" 21 | 22 | #include "../ext/factory.h" 23 | #include "../ext/fountainflow.h" 24 | #include "../ext/capabilityflow.h" 25 | #include "../ext/fastpassTopology.h" 26 | 27 | #include "flow_generator.h" 28 | #include "stats.h" 29 | #include "params.h" 30 | 31 | #include "../ext/ideal.h" 32 | 33 | extern Topology *topology; 34 | extern double current_time; 35 | extern std::priority_queue, EventComparator> event_queue; 36 | extern std::deque flows_to_schedule; 37 | extern std::deque flow_arrivals; 38 | 39 | extern uint32_t num_outstanding_packets; 40 | extern uint32_t max_outstanding_packets; 41 | extern DCExpParams params; 42 | extern void add_to_event_queue(Event*); 43 | extern void read_experiment_parameters(std::string conf_filename, uint32_t exp_type); 44 | extern void read_flows_to_schedule(std::string filename, uint32_t num_lines, Topology *topo); 45 | extern uint32_t duplicated_packets_received; 46 | 47 | extern uint32_t num_outstanding_packets_at_50; 48 | extern uint32_t num_outstanding_packets_at_100; 49 | extern uint32_t arrival_packets_at_50; 50 | extern uint32_t arrival_packets_at_100; 51 | 52 | extern double start_time; 53 | extern double get_current_time(); 54 | 55 | extern void run_scenario(); 56 | 57 | void validate_flow(Flow* f){ 58 | double slowdown = 1000000.0 * f->flow_completion_time / topology->get_oracle_fct(f); 59 | if(slowdown < 0.999999){ 60 | std::cout << "Flow " << f->id << " has slowdown " << slowdown << "\n"; 61 | //assert(false); 62 | } 63 | //if(f->first_byte_send_time < 0 || f->first_byte_send_time < f->start_time - INFINITESIMAL_TIME) 64 | // std::cout << "Flow " << f->id << " first_byte_send_time: " << f->first_byte_send_time << " start time:" 65 | // << f->start_time << "\n"; 66 | } 67 | 68 | void debug_flow_stats(std::deque flows){ 69 | std::map freq; 70 | for (uint32_t i = 0; i < flows.size(); i++) { 71 | Flow *f = flows[i]; 72 | if(f->size_in_pkt == 3){ 73 | int fct = (int)(1000000.0 * f->flow_completion_time); 74 | if(freq.find(fct) == freq.end()) 75 | freq[fct] = 0; 76 | freq[fct]++; 77 | } 78 | } 79 | for(auto it = freq.begin(); it != freq.end(); it++) 80 | std::cout << it->first << " " << it->second << "\n"; 81 | } 82 | 83 | void assign_flow_deadline(std::deque flows) 84 | { 85 | ExponentialRandomVariable *nv_intarr = new ExponentialRandomVariable(params.avg_deadline); 86 | for(uint i = 0; i < flows.size(); i++) 87 | { 88 | Flow* f = flows[i]; 89 | double rv = nv_intarr->value(); 90 | f->deadline = f->start_time + std::max(topology->get_oracle_fct(f)/1000000.0 * 1.25, rv); 91 | //std::cout << f->start_time << " " << f->deadline << " " << topology->get_oracle_fct(f)/1000000 << " " << rv << "\n"; 92 | } 93 | } 94 | 95 | void printQueueStatistics(Topology *topo) { 96 | double totalSentFromHosts = 0; 97 | 98 | uint64_t dropAt[4]; 99 | uint64_t total_drop = 0; 100 | for (auto i = 0; i < 4; i++) { 101 | dropAt[i] = 0; 102 | } 103 | 104 | for (uint i = 0; i < topo->hosts.size(); i++) { 105 | int location = topo->hosts[i]->queue->location; 106 | dropAt[location] += topo->hosts[i]->queue->pkt_drop; 107 | } 108 | 109 | 110 | for (uint i = 0; i < topo->switches.size(); i++) { 111 | for (uint j = 0; j < topo->switches[i]->queues.size(); j++) { 112 | int location = topo->switches[i]->queues[j]->location; 113 | dropAt[location] += topo->switches[i]->queues[j]->pkt_drop; 114 | } 115 | } 116 | 117 | for (int i = 0; i < 4; i++) { 118 | total_drop += dropAt[i]; 119 | } 120 | for (int i = 0; i < 4; i++) { 121 | std::cout << "Hop:" << i << " Drp:" << dropAt[i] << "(" << (int)((double)dropAt[i]/total_drop * 100) << "%) "; 122 | } 123 | 124 | for (auto h = (topo->hosts).begin(); h != (topo->hosts).end(); h++) { 125 | totalSentFromHosts += (*h)->queue->b_departures; 126 | } 127 | 128 | std::cout << " Overall:" << std::setprecision(2) <<(double)total_drop*1460/totalSentFromHosts << "\n"; 129 | 130 | double totalSentToHosts = 0; 131 | for (auto tor = (topo->switches).begin(); tor != (topo->switches).end(); tor++) { 132 | for (auto q = ((*tor)->queues).begin(); q != ((*tor)->queues).end(); q++) { 133 | if ((*q)->rate == params.bandwidth) totalSentToHosts += (*q)->b_departures; 134 | } 135 | } 136 | 137 | double dead_bytes = totalSentFromHosts - totalSentToHosts; 138 | double total_bytes = 0; 139 | for (auto f = flows_to_schedule.begin(); f != flows_to_schedule.end(); f++) { 140 | total_bytes += (*f)->size; 141 | } 142 | 143 | double simulation_time = current_time - start_time; 144 | double utilization = (totalSentFromHosts * 8.0 / 144.0) / simulation_time; 145 | double dst_utilization = (totalSentToHosts * 8.0 / 144.0) / simulation_time; 146 | 147 | std::cout 148 | << "DeadPackets " << 100.0 * (dead_bytes/total_bytes) 149 | << "% DuplicatedPackets " << 100.0 * duplicated_packets_received * 1460.0 / total_bytes 150 | << "% Utilization " << utilization / 10000000000 * 100 << "% " << dst_utilization / 10000000000 * 100 151 | << "%\n"; 152 | } 153 | 154 | void run_experiment(int argc, char **argv, uint32_t exp_type) { 155 | if (argc < 3) { 156 | std::cout << "Usage: exp_type conf_file" << std::endl; 157 | return; 158 | } 159 | 160 | std::string conf_filename(argv[2]); 161 | read_experiment_parameters(conf_filename, exp_type); 162 | params.num_hosts = 144; 163 | params.num_agg_switches = 9; 164 | params.num_core_switches = 4; 165 | 166 | if (params.flow_type == FASTPASS_FLOW) { 167 | topology = new FastpassTopology(params.num_hosts, params.num_agg_switches, params.num_core_switches, params.bandwidth, params.queue_type); 168 | } 169 | else if (params.big_switch) { 170 | topology = new BigSwitchTopology(params.num_hosts, params.bandwidth, params.queue_type); 171 | } 172 | else { 173 | topology = new PFabricTopology(params.num_hosts, params.num_agg_switches, params.num_core_switches, params.bandwidth, params.queue_type); 174 | } 175 | 176 | uint32_t num_flows = params.num_flows_to_run; 177 | 178 | FlowGenerator *fg; 179 | if (params.use_flow_trace) { 180 | fg = new FlowReader(num_flows, topology, params.cdf_or_flow_trace); 181 | fg->make_flows(); 182 | } 183 | else if (params.interarrival_cdf != "none") { 184 | fg = new CustomCDFFlowGenerator(num_flows, topology, params.cdf_or_flow_trace, params.interarrival_cdf); 185 | fg->make_flows(); 186 | } 187 | else if (params.permutation_tm != 0) { 188 | fg = new PermutationTM(num_flows, topology, params.cdf_or_flow_trace); 189 | fg->make_flows(); 190 | } 191 | else if (params.bytes_mode) { 192 | fg = new PoissonFlowBytesGenerator(num_flows, topology, params.cdf_or_flow_trace); 193 | fg->make_flows(); 194 | } 195 | else if (params.traffic_imbalance < 0.01) { 196 | fg = new PoissonFlowGenerator(num_flows, topology, params.cdf_or_flow_trace); 197 | fg->make_flows(); 198 | } 199 | else { 200 | // TODO skew flow gen not yet implemented, need to move to FlowGenerator 201 | assert(false); 202 | //generate_flows_to_schedule_fd_with_skew(params.cdf_or_flow_trace, num_flows, topology); 203 | } 204 | 205 | if (params.deadline) { 206 | assign_flow_deadline(flows_to_schedule); 207 | } 208 | 209 | std::deque flows_sorted = flows_to_schedule; 210 | 211 | struct FlowComparator { 212 | bool operator() (Flow* a, Flow* b) { 213 | return a->start_time < b->start_time; 214 | } 215 | } fc; 216 | 217 | std::sort (flows_sorted.begin(), flows_sorted.end(), fc); 218 | 219 | for (uint32_t i = 0; i < flows_sorted.size(); i++) { 220 | Flow* f = flows_sorted[i]; 221 | if (exp_type == GEN_ONLY) { 222 | std::cout << f->id << " " << f->size << " " << f->src->id << " " << f->dst->id << " " << 1e6*f->start_time << "\n"; 223 | } 224 | else { 225 | flow_arrivals.push_back(new FlowArrivalEvent(f->start_time, f)); 226 | } 227 | } 228 | 229 | if (exp_type == GEN_ONLY) { 230 | return; 231 | } 232 | 233 | //add_to_event_queue(new LoggingEvent((flows_sorted.front())->start_time)); 234 | 235 | if (params.flow_type == FASTPASS_FLOW) { 236 | dynamic_cast(topology)->arbiter->start_arbiter(); 237 | } 238 | 239 | // 240 | // everything before this is setup; everything after is analysis 241 | // 242 | run_scenario(); 243 | 244 | for (uint32_t i = 0; i < flows_sorted.size(); i++) { 245 | Flow *f = flows_to_schedule[i]; 246 | validate_flow(f); 247 | if(!f->finished) { 248 | std::cout 249 | << "unfinished flow " 250 | << "size:" << f->size 251 | << " id:" << f->id 252 | << " next_seq:" << f->next_seq_no 253 | << " recv:" << f->received_bytes 254 | << " src:" << f->src->id 255 | << " dst:" << f->dst->id 256 | << "\n"; 257 | } 258 | } 259 | 260 | //cleanup 261 | delete fg; 262 | } 263 | -------------------------------------------------------------------------------- /run/flow_generator.h: -------------------------------------------------------------------------------- 1 | // 2 | // flow_generator.h 3 | // support arbitrary flow generation models. 4 | // 5 | // 6/15/2015 Akshay Narayan 6 | // 7 | 8 | #ifndef FLOW_GEN_H 9 | #define FLOW_GEN_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "math.h" 23 | #include "assert.h" 24 | 25 | #include "../coresim/flow.h" 26 | #include "../coresim/event.h" 27 | #include "../coresim/node.h" 28 | #include "../coresim/topology.h" 29 | #include "../coresim/queue.h" 30 | #include "../coresim/random_variable.h" 31 | 32 | #include "../ext/factory.h" 33 | 34 | #include "params.h" 35 | 36 | extern Topology *topology; 37 | extern double current_time; 38 | extern std::priority_queue, EventComparator> event_queue; 39 | extern std::deque flows_to_schedule; 40 | extern std::deque flow_arrivals; 41 | 42 | extern DCExpParams params; 43 | extern void add_to_event_queue(Event *); 44 | 45 | extern double start_time; 46 | extern double get_current_time(); 47 | 48 | // subclass FlowGenerator to implement your favorite flow generation scheme 49 | 50 | class FlowGenerator { 51 | public: 52 | uint32_t num_flows; 53 | Topology *topo; 54 | std::string filename; 55 | 56 | FlowGenerator(uint32_t num_flows, Topology *topo, std::string filename); 57 | virtual void write_flows_to_file(std::deque flows, std::string file); 58 | virtual void make_flows(); 59 | }; 60 | 61 | class PoissonFlowGenerator : public FlowGenerator { 62 | public: 63 | PoissonFlowGenerator(uint32_t num_flows, Topology *topo, std::string filename); 64 | virtual void make_flows(); 65 | }; 66 | 67 | class PoissonFlowBytesGenerator : public FlowGenerator { 68 | public: 69 | PoissonFlowBytesGenerator(uint32_t num_flows, Topology *topo, std::string filename); 70 | virtual void make_flows(); 71 | }; 72 | 73 | class FlowReader : public FlowGenerator { 74 | public: 75 | FlowReader(uint32_t num_flows, Topology *topo, std::string filename); 76 | virtual void make_flows(); 77 | }; 78 | 79 | class CustomCDFFlowGenerator : public FlowGenerator { 80 | public: 81 | CustomCDFFlowGenerator(uint32_t num_flows, Topology *topo, std::string filename, std::string interarrivals_cdf_filename); 82 | virtual void make_flows(); 83 | 84 | std::string interarrivals_cdf_filename; 85 | private: 86 | std::vector* makeCDFArray(std::string fn_template, std::string filename); 87 | }; 88 | 89 | class PermutationTM : public FlowGenerator { 90 | public: 91 | PermutationTM(uint32_t num_flows, Topology *topo, std::string filename); 92 | virtual void make_flows(); 93 | 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /run/params.cpp: -------------------------------------------------------------------------------- 1 | #include "params.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | DCExpParams params; 9 | 10 | /* Read parameters from a config file */ 11 | void read_experiment_parameters(std::string conf_filename, uint32_t exp_type) { 12 | std::ifstream input(conf_filename); 13 | std::string line; 14 | std::string key; 15 | params.interarrival_cdf = "none"; 16 | params.permutation_tm = 0; 17 | params.hdr_size = 40; 18 | while (std::getline(input, line)) { 19 | std::istringstream lineStream(line); 20 | if (line.empty()) { 21 | continue; 22 | } 23 | 24 | 25 | lineStream >> key; 26 | assert(key[key.length()-1] == ':'); 27 | key = key.substr(0, key.length()-1); 28 | if (key == "init_cwnd") { 29 | lineStream >> params.initial_cwnd; 30 | } 31 | else if (key == "max_cwnd") { 32 | lineStream >> params.max_cwnd; 33 | } 34 | else if (key == "retx_timeout") { 35 | lineStream >> params.retx_timeout_value; 36 | } 37 | else if (key == "queue_size") { 38 | lineStream >> params.queue_size; 39 | } 40 | else if (key == "propagation_delay") { 41 | lineStream >> params.propagation_delay; 42 | } 43 | else if (key == "bandwidth") { 44 | lineStream >> params.bandwidth; 45 | } 46 | else if (key == "queue_type") { 47 | lineStream >> params.queue_type; 48 | } 49 | else if (key == "flow_type") { 50 | lineStream >> params.flow_type; 51 | } 52 | else if (key == "num_flow") { 53 | lineStream >> params.num_flows_to_run; 54 | } 55 | else if (key == "flow_trace") { 56 | lineStream >> params.cdf_or_flow_trace; 57 | } 58 | else if (key == "cut_through") { 59 | lineStream >> params.cut_through; 60 | } 61 | else if (key == "mean_flow_size") { 62 | lineStream >> params.mean_flow_size; 63 | } 64 | else if (key == "load_balancing") { 65 | lineStream >> params.load_balancing; 66 | } 67 | else if (key == "preemptive_queue") { 68 | lineStream >> params.preemptive_queue; 69 | } 70 | else if (key == "big_switch") { 71 | lineStream >> params.big_switch; 72 | } 73 | else if (key == "host_type") { 74 | lineStream >> params.host_type; 75 | } 76 | else if (key == "imbalance") { 77 | lineStream >> params.traffic_imbalance; 78 | } 79 | else if (key == "load") { 80 | lineStream >> params.load; 81 | } 82 | else if (key == "traffic_imbalance") { 83 | lineStream >> params.traffic_imbalance; 84 | } 85 | else if (key == "reauth_limit") { 86 | lineStream >> params.reauth_limit; 87 | } 88 | else if (key == "magic_trans_slack") { 89 | lineStream >> params.magic_trans_slack; 90 | } 91 | else if (key == "magic_delay_scheduling") { 92 | lineStream >> params.magic_delay_scheduling; 93 | } 94 | else if (key == "capability_timeout") { 95 | lineStream >> params.capability_timeout; 96 | } 97 | else if (key == "use_flow_trace") { 98 | lineStream >> params.use_flow_trace; 99 | } 100 | else if (key == "smooth_cdf") { 101 | lineStream >> params.smooth_cdf; 102 | } 103 | else if (key == "burst_at_beginning") { 104 | lineStream >> params.burst_at_beginning; 105 | } 106 | else if (key == "capability_resend_timeout") { 107 | lineStream >> params.capability_resend_timeout; 108 | } 109 | else if (key == "capability_initial") { 110 | lineStream >> params.capability_initial; 111 | } 112 | else if (key == "capability_window") { 113 | lineStream >> params.capability_window; 114 | } 115 | else if (key == "capability_prio_thresh") { 116 | lineStream >> params.capability_prio_thresh; 117 | } 118 | else if (key == "capability_third_level") { 119 | lineStream >> params.capability_third_level; 120 | } 121 | else if (key == "capability_fourth_level") { 122 | lineStream >> params.capability_fourth_level; 123 | } 124 | else if (key == "capability_window_timeout") { 125 | lineStream >> params.capability_window_timeout; 126 | } 127 | else if (key == "ddc") { 128 | lineStream >> params.ddc; 129 | } 130 | else if (key == "ddc_cpu_ratio") { 131 | lineStream >> params.ddc_cpu_ratio; 132 | } 133 | else if (key == "ddc_mem_ratio") { 134 | lineStream >> params.ddc_mem_ratio; 135 | } 136 | else if (key == "ddc_disk_ratio") { 137 | lineStream >> params.ddc_disk_ratio; 138 | } 139 | else if (key == "ddc_normalize") { 140 | lineStream >> params.ddc_normalize; 141 | } 142 | else if (key == "ddc_type") { 143 | lineStream >> params.ddc_type; 144 | } 145 | else if (key == "deadline") { 146 | lineStream >> params.deadline; 147 | } 148 | else if (key == "schedule_by_deadline") { 149 | lineStream >> params.schedule_by_deadline; 150 | } 151 | else if (key == "avg_deadline") { 152 | lineStream >> params.avg_deadline; 153 | } 154 | else if (key == "magic_inflate") { 155 | lineStream >> params.magic_inflate; 156 | } 157 | else if (key == "interarrival_cdf") { 158 | lineStream >> params.interarrival_cdf; 159 | } 160 | else if (key == "num_host_types") { 161 | lineStream >> params.num_host_types; 162 | } 163 | else if (key == "permutation_tm") { 164 | lineStream >> params.permutation_tm; 165 | } 166 | else if (key == "dctcp_mark_thresh") { 167 | lineStream >> params.dctcp_mark_thresh; 168 | } 169 | else if (key == "hdr_size") { 170 | lineStream >> params.hdr_size; 171 | assert(params.hdr_size > 0); 172 | } 173 | else if (key == "bytes_mode") { 174 | lineStream >> params.bytes_mode; 175 | } 176 | //else if (key == "dctcp_delayed_ack_freq") { 177 | // lineStream >> params.dctcp_delayed_ack_freq; 178 | //} 179 | else { 180 | std::cout << "Unknown conf param: " << key << " in file: " << conf_filename << "\n"; 181 | assert(false); 182 | } 183 | 184 | params.fastpass_epoch_time = 1500 * 8 * (FASTPASS_EPOCH_PKTS + 0.5) / params.bandwidth; 185 | 186 | params.param_str.append(line); 187 | params.param_str.append(", "); 188 | } 189 | 190 | params.mss = 1460; 191 | } 192 | -------------------------------------------------------------------------------- /run/params.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAMS_H 2 | #define PARAMS_H 3 | 4 | #include 5 | #include 6 | 7 | class DCExpParams { 8 | public: 9 | std::string param_str; 10 | 11 | uint32_t initial_cwnd; 12 | uint32_t max_cwnd; 13 | double retx_timeout_value; 14 | uint32_t mss; 15 | uint32_t hdr_size; 16 | uint32_t queue_size; 17 | uint32_t queue_type; 18 | uint32_t flow_type; 19 | uint32_t load_balancing; //0 per pkt, 1 per flow 20 | 21 | double propagation_delay; 22 | double bandwidth; 23 | 24 | uint32_t num_flows_to_run; 25 | double end_time; 26 | std::string cdf_or_flow_trace; 27 | uint32_t bytes_mode; 28 | uint32_t cut_through; 29 | uint32_t mean_flow_size; 30 | 31 | 32 | uint32_t num_hosts; 33 | uint32_t num_agg_switches; 34 | uint32_t num_core_switches; 35 | uint32_t preemptive_queue; 36 | uint32_t big_switch; 37 | uint32_t host_type; 38 | double traffic_imbalance; 39 | double load; 40 | 41 | double reauth_limit; 42 | 43 | double magic_trans_slack; 44 | uint32_t magic_delay_scheduling; 45 | uint32_t magic_inflate; 46 | 47 | uint32_t use_flow_trace; 48 | uint32_t smooth_cdf; 49 | uint32_t burst_at_beginning; 50 | double capability_timeout; 51 | double capability_resend_timeout; 52 | uint32_t capability_initial; 53 | uint32_t capability_window; 54 | uint32_t capability_prio_thresh; 55 | double capability_window_timeout; 56 | uint32_t capability_third_level; 57 | uint32_t capability_fourth_level; 58 | 59 | uint32_t ddc; 60 | double ddc_cpu_ratio; 61 | double ddc_mem_ratio; 62 | double ddc_disk_ratio; 63 | uint32_t ddc_normalize; //0: sender send, 1: receiver side, 2: both 64 | uint32_t ddc_type; 65 | 66 | uint32_t deadline; 67 | uint32_t schedule_by_deadline; 68 | double avg_deadline; 69 | std::string interarrival_cdf; 70 | uint32_t num_host_types; 71 | 72 | double fastpass_epoch_time; 73 | 74 | uint32_t permutation_tm; 75 | 76 | uint32_t dctcp_mark_thresh; 77 | //uint32_t dctcp_delayed_ack_freq; 78 | 79 | double get_full_pkt_tran_delay(uint32_t size_in_byte = 1500) 80 | { 81 | return size_in_byte * 8 / this->bandwidth; 82 | } 83 | 84 | }; 85 | 86 | 87 | #define CAPABILITY_MEASURE_WASTE false 88 | #define CAPABILITY_NOTIFY_BLOCKING false 89 | #define CAPABILITY_HOLD true 90 | 91 | //#define FASTPASS_EPOCH_TIME 0.000010 92 | #define FASTPASS_EPOCH_PKTS 8 93 | 94 | void read_experiment_parameters(std::string conf_filename, uint32_t exp_type); 95 | 96 | /* General main function */ 97 | #define DEFAULT_EXP 1 98 | #define GEN_ONLY 2 99 | 100 | #define INFINITESIMAL_TIME 0.000000000001 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /run/stats.cpp: -------------------------------------------------------------------------------- 1 | #include "stats.h" 2 | #include 3 | #include 4 | #include "assert.h" 5 | 6 | Stats::Stats(bool get_dist) 7 | { 8 | this->sum = 0; 9 | this->sq_sum = 0; 10 | this->count = 0; 11 | this->get_dist = get_dist; 12 | } 13 | 14 | 15 | void Stats::input_data(double data){ 16 | sum += data; 17 | sq_sum += data * data; 18 | count++; 19 | raw.push_back(data); 20 | } 21 | 22 | void Stats::input_data(int data){ 23 | input_data((double)data); 24 | } 25 | 26 | void Stats::operator+=(const double &data){ 27 | input_data(data); 28 | } 29 | void Stats::operator+=(const int &data) 30 | { 31 | input_data(data); 32 | } 33 | 34 | 35 | double Stats::avg(){ 36 | return sum/count; 37 | } 38 | 39 | double Stats::size(){ 40 | return count; 41 | } 42 | 43 | double Stats::sd(){ 44 | return sqrt(sq_sum/count - avg() * avg()); 45 | } 46 | 47 | double Stats::total(){ 48 | return sum; 49 | } 50 | 51 | void Stats::set_precision() 52 | { 53 | 54 | } 55 | 56 | double Stats::get_percentile(double p){ 57 | if(raw.size() == 0) 58 | return -1; 59 | std::sort(raw.begin(), raw.end()); 60 | int loc = (int)(p*raw.size()); 61 | assert(loc >= 0 && loc < raw.size()); 62 | return raw[loc]; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /run/stats.h: -------------------------------------------------------------------------------- 1 | #ifndef STATS_H 2 | #define STATS_H 3 | 4 | #include 5 | #include 6 | class Stats 7 | { 8 | private: 9 | double sum; 10 | double sq_sum; 11 | int count; 12 | bool get_dist; 13 | std::map distribution; 14 | int dist_round_precision; 15 | std::vector raw; 16 | 17 | public: 18 | Stats(bool get_dist = false); 19 | void input_data(double data); 20 | void input_data(int); 21 | void operator+=(const double &data); 22 | void operator+=(const int &data); 23 | double avg(); 24 | double size(); 25 | double total(); 26 | double sd(); 27 | void set_precision(); 28 | double get_percentile(double p); 29 | }; 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /yaps-mascot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetSys/simulator/179b64ef7a78c3e1c3b95006b96a35f8fc0cff01/yaps-mascot.png --------------------------------------------------------------------------------