2 /* Copyright (c) 2007 Kayo Fujiwara. All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "gtnets_simulator.h"
8 #include "gtnets_topology.h"
15 #include "xbt/asserts.h"
16 #include "RngStream.h"
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets_simulator, surf_network_gtnets,
19 "Logging specific to the SURF network GTNetS simulator");
24 static vector<void*> meta_flows;
25 static int* meta_nflow;
26 static int meta_flg = 0;
29 void static tcp_sent_callback(void* action, double completion_time);
33 // TODO: check the default values.
34 GTSim::GTSim(int WindowSize){
35 int wsize = WindowSize;
41 // EXTRACTED FROM GTNETS SOURCE CODE COMMENTS
42 // REDQueue::REDQueue(
43 // DCount_t in_w_q, Count_t in_min_th, Count_t in_max_th,
44 // Count_t in_limit, DCount_t in_max_p, Count_t in_mean_pktsize) : iface(nil)
45 // Set default values.
46 //Doc:Desc This constructor the critical RED parameters and builds a
47 //Doc:Desc correspoding RED queue
48 //Doc:Arg1 weight of the queue
49 //Doc:Arg2 minimum threshold
50 //Doc:Arg3 maximum threshold
51 //Doc:Arg4 Limit/max size for the queue
52 //Doc:Arg5 maximum value for mark/drop probability
53 //Doc:Arg6 Average packet size
56 //REDQueue *default_red_queue_ = new REDQueue(0.002, 2500, 7500, 30000, 0.10, 500);
58 //REDQueue *default_red_queue_ = new REDQueue();
60 //See for details of how those values are calucated below
61 //[1] Sally Floyd and Van Jacobson, "Random Early Detection Gateways with Congestion Avoidance",
62 // IEEE/ACM Transactions on Networking, vol. 1, n. 4, august 1993.
64 //[2] Kostas Pentikousis, "Active Queue Management", ACM Crossroads, vol. 7, n. 5,
67 //[3] Stefann De Cnodder, Omar Ecoumi, Kenny Paulwels, "RED behavior with different packet sizes",
68 // 5th IEEE Symposium on Computers and Communication, (ISCC 2000)
70 //[4] http://www.opalsoft.net/qos/DS-26.htm
73 // q_weight = fixed to 0.002 in most literature
74 // min_bytes = max / 3 = 16,666,666
75 // max_bytes = mean_bw * max_tolerable_latency, set to 1e8 * 0.5 = 50,000,000
76 // limit_bytes = 8 * max = 400,000,000
77 // prob = follow most literature 0.02
78 // avgpkt = fixed to the same TCP segment size, 1000 Bytes
80 // burst = (2*(min+max))/(3*avgpkt) ***DON'T USED BY GTNetS***
81 REDQueue *default_red_queue_ = new REDQueue(0.002, 16666666, 50000000, 400000000, 0.02, 1000);
83 Queue::Default(*default_red_queue_);
84 delete default_red_queue_;
86 cout << "Set default window size to " << wsize << endl;
87 TCP::DefaultAdvWin(wsize);
88 TCP::DefaultSegSize(1000);
89 TCP::DefaultTxBuffer(128000);
90 TCP::DefaultRxBuffer(128000);
92 sim_ = new Simulator();
94 topo_ = new GTNETS_Topology();
97 rm_ = new RoutingManual();
98 Routing::SetRouting(rm_);
102 // TODO: check the default values.
110 // EXTRACTED FROM GTNETS SOURCE CODE COMMENTS
111 // REDQueue::REDQueue(
112 // DCount_t in_w_q, Count_t in_min_th, Count_t in_max_th,
113 // Count_t in_limit, DCount_t in_max_p, Count_t in_mean_pktsize) : iface(nil)
114 // Set default values.
115 //Doc:Desc This constructor the critical RED parameters and builds a
116 //Doc:Desc correspoding RED queue
117 //Doc:Arg1 weight of the queue
118 //Doc:Arg2 minimum threshold
119 //Doc:Arg3 maximum threshold
120 //Doc:Arg4 Limit/max size for the queue
121 //Doc:Arg5 maximum value for mark/drop probability
122 //Doc:Arg6 Average packet size
125 //REDQueue *default_red_queue_ = new REDQueue(0.002, 2500, 7500, 30000, 0.10, 500);
127 //REDQueue *default_red_queue_ = new REDQueue();
129 //See for details of how those values are calucated below
130 //[1] Sally Floyd and Van Jacobson, "Random Early Detection Gateways with Congestion Avoidance",
131 // IEEE/ACM Transactions on Networking, vol. 1, n. 4, august 1993.
133 //[2] Kostas Pentikousis, "Active Queue Management", ACM Crossroads, vol. 7, n. 5,
136 //[3] Stefann De Cnodder, Omar Ecoumi, Kenny Paulwels, "RED behavior with different packet sizes",
137 // 5th IEEE Symposium on Computers and Communication, (ISCC 2000)
139 //[4] http://www.opalsoft.net/qos/DS-26.htm
142 // q_weight = fixed to 0.002 in most literature
143 // min_bytes = max / 3 = 16,666,666
144 // max_bytes = mean_bw * max_tolerable_latency, set to 1e8 * 0.5 = 50,000,000
145 // limit_bytes = 8 * max = 400,000,000
146 // prob = follow most literature 0.02
147 // avgpkt = fixed to the same TCP segment size, 1000 Bytes
149 // burst = (2*(min+max))/(3*avgpkt) ***DON'T USED BY GTNetS***
150 REDQueue *default_red_queue_ = new REDQueue(0.002, 16666666, 50000000, 400000000, 0.02, 1000);
152 Queue::Default(*default_red_queue_);
153 delete default_red_queue_;
155 TCP::DefaultAdvWin(wsize);
156 TCP::DefaultSegSize(1000);
157 TCP::DefaultTxBuffer(128000);
158 TCP::DefaultRxBuffer(128000);
160 sim_ = new Simulator();
162 topo_ = new GTNETS_Topology();
165 rm_ = new RoutingManual();
166 Routing::SetRouting(rm_);
171 map<int, Linkp2p*>::iterator it;
172 for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
175 while (!gtnets_links_.empty())
176 gtnets_links_.erase(gtnets_links_.begin());
178 map<int, Uniform*>::iterator it2;
179 for (it2 = uniform_jitter_generator_.begin(); it2 != uniform_jitter_generator_.end(); it2++){
182 while (!uniform_jitter_generator_.empty())
183 uniform_jitter_generator_.erase(uniform_jitter_generator_.begin());
185 map<int, Node*>::iterator it3;
186 for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
189 while (!gtnets_nodes_.empty())
190 gtnets_nodes_.erase(gtnets_nodes_.begin());
192 map<int, TCPServer*>::iterator it4;
193 for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
196 while (!gtnets_servers_.empty())
197 gtnets_servers_.erase(gtnets_servers_.begin());
199 map<int, TCPSend*>::iterator it5;
200 for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
203 while (!gtnets_clients_.empty())
204 gtnets_clients_.erase(gtnets_clients_.begin());
215 int GTSim::add_router(int id){
216 xbt_assert1(!(topo_->add_router(id) < 0), "can't add router %d. already exists", id);
219 //bandwidth: in bytes.
220 //latency: in seconds.
221 int GTSim::add_link(int id, double bandwidth, double latency){
222 double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS).
223 xbt_assert1(!(topo_->add_link(id) < 0),"Can't add link %d. already exists", id);
224 DEBUG3("Creating a new P2P, linkid %d, bandwidth %gl, latency %gl", id, bandwidth, latency);
225 gtnets_links_[id] = new Linkp2p(bw, latency);
227 DEBUG2("Using jitter %f, and seed %u", jitter_, jitter_seed_);
228 double min = -1*jitter_*latency;
229 double max = jitter_*latency;
230 uniform_jitter_generator_[id] = new Uniform(min,max);
231 gtnets_links_[id]->Jitter((const Random &) *(uniform_jitter_generator_[id]));
236 // if gtnets_nodes_ includes id, return true, otherwise return false.
237 bool GTSim::node_include(int id){
238 if (gtnets_nodes_.find(id) != gtnets_nodes_.end()) return true;
242 // if gtnets_link_ includes id, return true, otherwise return false.
243 bool GTSim::link_include(int id){
244 if (gtnets_links_.find(id) != gtnets_links_.end()) return true;
248 int GTSim::add_onehop_route(int src, int dst, int link){
249 xbt_assert3(!(topo_->add_onehop_route(src, dst, link) < 0), "Cannot add a route, src: %d, dst: %d, link: %d", src, dst, link);
253 // Generate the gtnets nodes according to topo_.
254 void GTSim::add_nodes(){
255 static unsigned int address = IPAddr("192.168.0.1");
256 IPAddr helper = IPAddr();
257 vector<GTNETS_Node*> nodes = topo_->nodes();
258 vector<GTNETS_Node*>::iterator it;
260 for (it = nodes.begin(); it != nodes.end(); it++){
262 gtnets_nodes_[id] = new Node();
263 gtnets_nodes_[id]->SetIPAddr(address++);
264 DEBUG2("In GTSim, add_node: %d, with IPAddr %s", id, helper.ToDotted(address-1));
269 void GTSim::node_connect(){
271 map<int, GTNETS_Link*> links = topo_->links();
272 map<int, GTNETS_Link*>::iterator it;
273 int linkid, srcid, dstid;
274 for (it = links.begin(); it != links.end(); it++){
275 linkid = it->second->id();
276 //if link is used in a route, connect the two nodes.
277 if (it->second->src_node() && it->second->dst_node()){
279 srcid = it->second->src_node()->id();
280 dstid = it->second->dst_node()->id();
282 gtnets_nodes_[srcid]->
283 AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
284 DEBUG3("Setting DuplexLink, src %d, dst %d, linkid %d", srcid, dstid, linkid);
289 // Create nodes and routes from the temporary topology, GTNETS_Topolgy.
290 void GTSim::create_gtnets_topology(){
295 void GTSim::print_topology(){
296 topo_->print_topology();
299 // Add a route that includes more than one hop. All one hop
300 // routes must have been added. When this function is called
301 // for the first time, all gtnets nodes are generated.
302 int GTSim::add_route(int src, int dst, int* links, int nlink){
303 if (is_topology_ == 0){
304 create_gtnets_topology();
308 IPAddr_t mymask = IPAddr("255.255.255.255");
310 int src_node = topo_->nodeid_from_hostid(src);
311 int dst_node = topo_->nodeid_from_hostid(dst);
313 xbt_assert1(!(gtnets_nodes_.find(src_node) == gtnets_nodes_.end()), "Node %d not found", src_node);
314 xbt_assert1(!(gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()), "Node %d not found", dst_node);
316 Node* tmpsrc = gtnets_nodes_[src_node];
317 Node* tmpdst = gtnets_nodes_[dst_node];
319 int next_node, cur_node;
322 for (int i = 0; i < nlink; i++){
323 xbt_assert1(!(gtnets_nodes_.find(cur_node) == gtnets_nodes_.end()), "Node %d not found", cur_node);
324 next_node = topo_->peer_node_id(links[i], cur_node);
325 xbt_assert0(!(next_node < 0), "Peer node not found");
326 xbt_assert1(!(gtnets_nodes_.find(next_node) == gtnets_nodes_.end()), "Node %d not found", next_node);
329 Node* tmpcur = gtnets_nodes_[cur_node];
330 Node* tmpnext = gtnets_nodes_[next_node];
332 tmpcur->AddRoute(tmpdst->GetIPAddr(),
334 tmpcur->GetIfByNode(tmpnext),
335 tmpnext->GetIPAddr());
337 tmpnext->AddRoute(tmpsrc->GetIPAddr(),
339 tmpnext->GetIfByNode(tmpcur),
340 tmpcur->GetIPAddr());
342 cur_node = next_node;
345 xbt_assert2(!(cur_node != dst_node), "Route inconsistency, last: %d, dst: %d",cur_node, dst_node);
352 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
353 //if no route with more than one links, topology has not been generated.
355 if (is_topology_ == 0){
356 create_gtnets_topology();
360 int src_node = topo_->nodeid_from_hostid(src);
361 xbt_assert1(!(src_node < 0), "Src %d not found", src_node);
363 int dst_node = topo_->nodeid_from_hostid(dst);
364 xbt_assert1(!(dst_node < 0), "Dst %d not found", dst_node);
366 gtnets_servers_[nflow_] = (TCPServer*) gtnets_nodes_[dst_node]->
367 AddApplication(TCPServer(TCPReno()));
368 gtnets_servers_[nflow_]->BindAndListen(1000+nflow_);
370 gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[src_node]->
371 AddApplication(TCPSend(metadata, gtnets_nodes_[dst_node]->GetIPAddr(),
372 1000+nflow_, Constant(datasize), TCPReno()));
373 gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
374 gtnets_clients_[nflow_]->Start(0);
376 gtnets_action_to_flow_[metadata] = nflow_;
382 Time_t GTSim::get_time_to_next_flow_completion(){
389 //remain needs to be updated in the future
396 if( (soon_pid=fork()) != 0){
397 read(pfds[0], &t1, sizeof(Time_t));
398 waitpid(soon_pid, &status, 0);
401 t = sim_->RunUntilNextCompletion();
402 write(pfds[1], (const void*)&t, sizeof(Time_t));
409 double GTSim::gtnets_get_flow_rx(void *metadata){
410 int flow_id = gtnets_action_to_flow_[metadata];
411 return gtnets_servers_[flow_id]->GetTotRx();
415 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
418 meta_nflow = number_of_flows;
421 Time_t t1 = sim_->RunUntilNextCompletion();
423 *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
427 int GTSim::run(double delta){
433 void GTSim::set_jitter(double d){
434 xbt_assert1(((0 <= d)&&(d <= 1)), "The jitter value must be within interval [0.0;1.0), got %f", d);
438 void GTSim::set_jitter_seed(int s){
441 if(jitter_seed_ > 0.0){
442 INFO1("Setting the jitter_seed with %d", jitter_seed_ );
443 Random::GlobalSeed(jitter_seed_ , jitter_seed_ , jitter_seed_ ,jitter_seed_ ,jitter_seed_ ,jitter_seed_);
447 void static tcp_sent_callback(void* action, double completion_time){
448 // Schedule the flow complete event.
450 new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
451 Simulator::instance->Schedule(e, 0, Simulator::instance);
454 meta_flows.push_back(action);