Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
6c348f7745dff6d5a9f574eac0cd8aca74ab2130
[simgrid.git] / src / surf / gtnets / gtnets_simulator.cc
1 /* Copyright (c) 2007-2011, 2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include "gtnets_simulator.h"
8 #include "gtnets_topology.h"
9 #include <map>
10 #include <vector>
11 #ifdef XBT_DEBUG
12         #undef XBT_DEBUG
13 #endif
14 #include "xbt/log.h"
15 #include "xbt/asserts.h"
16 #include "RngStream.h"
17 #include <unistd.h> /* pipe */
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets_simulator, surf_network_gtnets,
20                                 "Logging specific to the SURF network GTNetS simulator");
21
22
23 using namespace std;
24
25 static vector<void*> meta_flows;
26 static int* meta_nflow;
27 static int meta_flg = 0;
28
29
30 void static tcp_sent_callback(void* action, double completion_time);
31
32
33 // Constructor.
34 // TODO: check the default values.
35 GTSim::GTSim(int WindowSize){
36   int wsize = WindowSize;
37   is_topology_ = 0;
38   nflow_ = 0;
39   jitter_ = 0;
40   jitter_seed_ = 10;
41
42   // EXTRACTED FROM GTNETS SOURCE CODE COMMENTS
43   //  REDQueue::REDQueue(
44   //     DCount_t in_w_q, Count_t in_min_th, Count_t in_max_th,
45   //     Count_t in_limit, DCount_t in_max_p, Count_t in_mean_pktsize) : iface(nil)
46   // Set default values.
47   //Doc:Desc This constructor the critical RED parameters and builds a
48   //Doc:Desc correspoding RED queue
49   //Doc:Arg1 weight of the queue
50   //Doc:Arg2 minimum threshold
51   //Doc:Arg3 maximum threshold
52   //Doc:Arg4 Limit/max size for the queue
53   //Doc:Arg5 maximum value for mark/drop probability
54   //Doc:Arg6 Average packet size
55
56   //Default Parameters
57   //REDQueue *default_red_queue_ = new REDQueue(0.002, 2500, 7500, 30000, 0.10, 500);
58   //Same as above
59   //REDQueue *default_red_queue_ = new REDQueue();
60
61   //See for details of how those values are calucated below
62   //[1] Sally Floyd and Van Jacobson, "Random Early Detection Gateways with Congestion Avoidance",
63   //    IEEE/ACM Transactions on Networking, vol. 1, n. 4, august 1993.
64   //
65   //[2] Kostas Pentikousis, "Active Queue Management", ACM Crossroads, vol. 7, n. 5,
66   //    mid-summer 2001
67   //
68   //[3] Stefann De Cnodder, Omar Ecoumi, Kenny Paulwels, "RED behavior with different packet sizes",
69   //    5th IEEE Symposium on Computers and Communication, (ISCC 2000)
70   //
71   //[4] http://www.opalsoft.net/qos/DS-26.htm
72   //
73   //short explanation:
74   // q_weight = fixed to 0.002 in most literature
75   // min_bytes = max / 3 = 16,666,666
76   // max_bytes = mean_bw * max_tolerable_latency, set to 1e8 * 0.5 = 50,000,000
77   // limit_bytes = 8 * max = 400,000,000
78   // prob = follow most literature 0.02
79   // avgpkt = fixed to the same TCP segment size, 1000 Bytes
80   //
81   // burst = (2*(min+max))/(3*avgpkt) ***DON'T USED BY GTNetS***
82   REDQueue *default_red_queue_ = new REDQueue(0.002, 16666666, 50000000, 400000000, 0.02, 1000);
83
84   Queue::Default(*default_red_queue_);
85   delete default_red_queue_;
86
87   TCP::DefaultAdvWin(wsize);
88   TCP::DefaultSegSize(1000);
89   TCP::DefaultTxBuffer(128000);
90   TCP::DefaultRxBuffer(128000);
91
92   sim_ = new Simulator();
93   sim_->verbose=false;
94   topo_ = new GTNETS_Topology();
95
96   // Manual routing
97   rm_ = new RoutingManual();
98   Routing::SetRouting(rm_);
99 }
100
101 // Constructor.
102 // TODO: check the default values.
103 GTSim::GTSim(){
104   int wsize = 20000;
105   is_topology_ = 0;
106   nflow_ = 0;
107   jitter_ = 0;
108   jitter_seed_ = 10;
109
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
123
124   //Default Parameters
125   //REDQueue *default_red_queue_ = new REDQueue(0.002, 2500, 7500, 30000, 0.10, 500);
126   //Same as above
127   //REDQueue *default_red_queue_ = new REDQueue();
128
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.
132   //
133   //[2] Kostas Pentikousis, "Active Queue Management", ACM Crossroads, vol. 7, n. 5,
134   //    mid-summer 2001
135   //
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)
138   //
139   //[4] http://www.opalsoft.net/qos/DS-26.htm
140   //
141   //short explanation:
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
148   //
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);
151
152   Queue::Default(*default_red_queue_);
153   delete default_red_queue_;
154
155   TCP::DefaultAdvWin(wsize);
156   TCP::DefaultSegSize(1000);
157   TCP::DefaultTxBuffer(128000);
158   TCP::DefaultRxBuffer(128000);
159
160   sim_ = new Simulator();
161   sim_->verbose=false;
162   topo_ = new GTNETS_Topology();
163
164   // Manual routing
165   rm_ = new RoutingManual();
166   Routing::SetRouting(rm_);
167 }
168
169 GTSim::~GTSim(){
170
171   map<int, Linkp2p*>::iterator it;
172   for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
173     delete it->second;
174   }
175   while (!gtnets_links_.empty())
176     gtnets_links_.erase(gtnets_links_.begin());
177
178   map<int, Uniform*>::iterator it2;
179   for (it2 = uniform_jitter_generator_.begin(); it2 != uniform_jitter_generator_.end(); it2++){
180     delete it2->second;
181   }
182   while (!uniform_jitter_generator_.empty())
183     uniform_jitter_generator_.erase(uniform_jitter_generator_.begin());
184
185   map<int, Node*>::iterator it3;
186   for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
187     delete it3->second;
188   }
189   while (!gtnets_nodes_.empty())
190     gtnets_nodes_.erase(gtnets_nodes_.begin());
191
192   map<int, TCPServer*>::iterator it4;
193   for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
194     delete it4->second;
195   }
196   while (!gtnets_servers_.empty())
197     gtnets_servers_.erase(gtnets_servers_.begin());
198
199   map<int, TCPSend*>::iterator it5;
200   for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
201     delete it5->second;
202   }
203   while (!gtnets_clients_.empty())
204     gtnets_clients_.erase(gtnets_clients_.begin());
205
206   is_topology_ = 0;
207   delete sim_;
208   delete topo_;
209   delete rm_;
210   sim_ = 0;
211   topo_ = 0;
212   rm_ = 0;
213 }
214
215 int GTSim::add_router(int id){
216   xbt_assert(!(topo_->add_router(id) < 0), "can't add router %d. already exists", id);
217 }
218
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_assert(!(topo_->add_link(id) < 0),"Can't add link %d. already exists", id);
224   XBT_DEBUG("Creating a new P2P, linkid %d, bandwidth %gl, latency %gl", id, bandwidth, latency);
225   gtnets_links_[id] = new Linkp2p(bw, latency);
226   if(jitter_ > 0){
227         XBT_DEBUG("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]));
232   }
233   return 0;
234 }
235
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;
239   else return false;
240 }
241
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;
245   else return false;
246 }
247
248 int GTSim::add_onehop_route(int src, int dst, int link){
249   xbt_assert(!(topo_->add_onehop_route(src, dst, link) < 0), "Cannot add a route, src: %d, dst: %d, link: %d", src, dst, link);
250   return 0;
251 }
252
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;
259   int id;
260   for (it = nodes.begin(); it != nodes.end(); it++){
261     id = (*it)->id();
262     gtnets_nodes_[id] = new Node();
263     gtnets_nodes_[id]->SetIPAddr(address++);
264     XBT_DEBUG("In GTSim, add_node: %d, with IPAddr %s", id, helper.ToDotted(address-1));
265
266   }
267 }
268
269 void GTSim::node_connect(){
270
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()){
278
279       srcid = it->second->src_node()->id();
280       dstid = it->second->dst_node()->id();
281
282       gtnets_nodes_[srcid]->
283         AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
284     XBT_DEBUG("Setting DuplexLink, src %d, dst %d, linkid %d", srcid, dstid, linkid);
285     }
286   }
287 }
288
289 // Create nodes and routes from the temporary topology, GTNETS_Topolgy.
290 void GTSim::create_gtnets_topology(){
291   add_nodes();
292   node_connect();
293 }
294
295 void GTSim::print_topology(){
296   topo_->print_topology();
297 }
298
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();
305     is_topology_ = 1;
306   }  
307
308   IPAddr_t mymask = IPAddr("255.255.255.255");
309
310   int src_node = topo_->nodeid_from_hostid(src);
311   int dst_node = topo_->nodeid_from_hostid(dst);
312
313   xbt_assert(!(gtnets_nodes_.find(src_node) == gtnets_nodes_.end()), "Node %d not found", src_node);
314   xbt_assert(!(gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()), "Node %d not found", dst_node);
315
316   Node* tmpsrc = gtnets_nodes_[src_node];
317   Node* tmpdst = gtnets_nodes_[dst_node];
318
319   int next_node, cur_node;
320   
321   cur_node = src_node;
322   for (int i = 0; i < nlink; i++){
323         xbt_assert(!(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_assert(!(next_node < 0), "Peer node not found");
326     xbt_assert(!(gtnets_nodes_.find(next_node) == gtnets_nodes_.end()), "Node %d not found", next_node);
327     
328     //add route
329     Node* tmpcur = gtnets_nodes_[cur_node];
330     Node* tmpnext = gtnets_nodes_[next_node];
331
332     tmpcur->AddRoute(tmpdst->GetIPAddr(),
333                      mymask,
334                      tmpcur->GetIfByNode(tmpnext),
335                      tmpnext->GetIPAddr());
336
337     tmpnext->AddRoute(tmpsrc->GetIPAddr(),
338                       mymask,
339                       tmpnext->GetIfByNode(tmpcur),
340                       tmpcur->GetIPAddr());
341     
342     cur_node = next_node;
343   }
344
345   xbt_assert(!(cur_node != dst_node), "Route inconsistency, last: %d, dst: %d",cur_node, dst_node);
346
347   return 0;
348 }
349
350
351
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.
354   //generate it here.
355   if (is_topology_ == 0){
356     create_gtnets_topology();
357     is_topology_ = 1;
358   }
359
360   int src_node = topo_->nodeid_from_hostid(src);
361   xbt_assert(!(src_node < 0), "Src %d not found", src_node);
362
363   int dst_node = topo_->nodeid_from_hostid(dst);
364   xbt_assert(!(dst_node < 0), "Dst %d not found", dst_node);
365
366   gtnets_servers_[nflow_] = (TCPServer*) gtnets_nodes_[dst_node]->
367        AddApplication(TCPServer(TCPReno()));
368   gtnets_servers_[nflow_]->BindAndListen(1000+nflow_);
369
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);
375
376   gtnets_action_to_flow_[metadata] = nflow_;
377   nflow_++;
378
379   return 0;
380 }
381
382 Time_t GTSim::get_time_to_next_flow_completion(){
383   int status;
384   Time_t t1;
385   int pfds[2];
386   int soon_pid=-1;
387   meta_flg=0;
388
389   //remain needs to be updated in the future
390   Count_t remain;
391   
392   pipe(pfds);
393   
394   t1 = 0;
395   fflush (NULL);
396   if( (soon_pid=fork()) != 0){
397     read(pfds[0], &t1, sizeof(Time_t));
398     waitpid(soon_pid, &status, 0);      
399   }else{
400     Time_t t;
401     t = sim_->RunUntilNextCompletion();
402     write(pfds[1], (const void*)&t, sizeof(Time_t));
403     exit(0);
404   }
405
406   return t1;
407 }
408
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(); 
412 }
413
414
415 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
416
417   meta_flows.clear();
418   meta_nflow = number_of_flows;
419   meta_flg = 1;
420
421   Time_t t1 = sim_->RunUntilNextCompletion();
422
423   *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
424   return 0;
425 }
426
427 int GTSim::run(double delta){
428   meta_flg=0;
429   sim_->Run(delta);
430   return 0;
431 }
432
433 void GTSim::set_jitter(double d){
434   xbt_assert(((0 <= d)&&(d <= 1)), "The jitter value must be within interval [0.0;1.0), got %f", d);
435   jitter_ = d;
436 }
437
438 void GTSim::set_jitter_seed(int s){
439   jitter_seed_ = s;
440
441   if(jitter_seed_ > 0.0){
442     XBT_INFO("Setting the jitter_seed with %d", jitter_seed_ );
443     Random::GlobalSeed(jitter_seed_  , jitter_seed_  , jitter_seed_  ,jitter_seed_  ,jitter_seed_  ,jitter_seed_);
444   }
445 }
446
447 void static tcp_sent_callback(void* action, double completion_time){
448   // Schedule the flow complete event.
449   SimulatorEvent* e =
450     new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
451   Simulator::instance->Schedule(e, 0, Simulator::instance);
452
453   if (meta_flg){
454     meta_flows.push_back(action);
455     (*meta_nflow)++;
456   }
457 }
458
459