Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Sanitize a bit the <foreach> handling (cosmetics, no bug fixed so far)
[simgrid.git] / src / surf / gtnets / gtnets_simulator.cc
1 /*      $Id$     */
2 /* Copyright (c) 2007 Kayo Fujiwara. 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 DEBUG0
12         #undef DEBUG0
13 #endif
14 #include "xbt/log.h"
15 #include "xbt/asserts.h"
16
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets_simulator, surf_network_gtnets,
18                                 "Logging specific to the SURF network GTNetS simulator");
19
20
21 using namespace std;
22
23 static vector<void*> meta_flows;
24 static int* meta_nflow;
25 static int meta_flg = 0;
26
27
28 void static tcp_sent_callback(void* action, double completion_time);
29
30 // Constructor.
31 // TODO: check the default values.
32 GTSim::GTSim(){
33   int wsize = 20000;
34   is_topology_ = 0;
35   nflow_ = 0;
36   sim_ = new Simulator();
37   topo_ = new GTNETS_Topology();
38   uniform_jitter_ = NULL;
39   jitter_ = 0;
40   jitter_seed_ = 10;
41
42   sim_->verbose=false;
43   // Set default values.
44   TCP::DefaultAdvWin(wsize);
45   TCP::DefaultSegSize(1000);
46   TCP::DefaultTxBuffer(128000);
47   TCP::DefaultRxBuffer(128000);
48
49   // Manual routing
50   rm_ = new RoutingManual();
51   Routing::SetRouting(rm_);
52 }
53
54 GTSim::~GTSim(){
55
56   map<int, Linkp2p*>::iterator it;
57   for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
58     delete it->second;
59   }
60   while (!gtnets_links_.empty())
61     gtnets_links_.erase(gtnets_links_.begin());
62
63   map<int, Node*>::iterator it3;
64   for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
65     delete it3->second;
66   }
67   while (!gtnets_nodes_.empty())
68     gtnets_nodes_.erase(gtnets_nodes_.begin());
69
70   map<int, TCPServer*>::iterator it4;
71   for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
72     delete it4->second;
73   }
74   while (!gtnets_servers_.empty())
75     gtnets_servers_.erase(gtnets_servers_.begin());
76
77   map<int, TCPSend*>::iterator it5;
78   for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
79     delete it5->second;
80   }
81   while (!gtnets_clients_.empty())
82     gtnets_clients_.erase(gtnets_clients_.begin());
83
84   is_topology_ = 0;
85   delete sim_;
86   delete topo_;
87   delete rm_;
88   sim_ = 0;
89   topo_ = 0;
90   rm_ = 0;
91 }
92
93 int GTSim::add_router(int id){
94   xbt_assert1(!(topo_->add_router(id) < 0), "can't add router %d. already exists", id);
95 }
96
97 //bandwidth: in bytes.
98 //latency: in seconds.
99 int GTSim::add_link(int id, double bandwidth, double latency){
100   double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS).
101   xbt_assert1(!(topo_->add_link(id) < 0),"Can't add link %d. already exists", id);
102   DEBUG3("Creating a new P2P, linkid %d, bandwidth %gl, latency %gl", id, bandwidth, latency);
103   gtnets_links_[id] = new Linkp2p(bw, latency);
104   if(jitter_ > 0){
105         DEBUG2("Using jitter %f, and seed %u", jitter_, jitter_seed_);
106         double min = -1*jitter_*latency;
107         double max = jitter_*latency;
108         if(uniform_jitter_ == NULL){
109                 Random::GlobalSeed(jitter_seed_  , jitter_seed_+1, jitter_seed_+2,
110                                                    jitter_seed_+3, jitter_seed_+4, jitter_seed_+5);
111                 uniform_jitter_ = new Uniform(min,max);
112         }
113         gtnets_links_[id]->Jitter((const Random &) *uniform_jitter_);
114   }
115   return 0;
116 }
117
118 // if gtnets_nodes_ includes id, return true, otherwise return false.
119 bool GTSim::node_include(int id){
120   if (gtnets_nodes_.find(id) != gtnets_nodes_.end()) return true;
121   else return false;
122 }
123
124 // if gtnets_link_ includes id, return true, otherwise return false.
125 bool GTSim::link_include(int id){
126   if (gtnets_links_.find(id) != gtnets_links_.end()) return true;
127   else return false;
128 }
129
130 int GTSim::add_onehop_route(int src, int dst, int link){
131   xbt_assert3(!(topo_->add_onehop_route(src, dst, link) < 0), "Cannot add a route, src: %d, dst: %d, link: %d", src, dst, link);
132   return 0;
133 }
134
135 // Generate the gtnets nodes according to topo_.
136 void GTSim::add_nodes(){
137   static unsigned int address = IPAddr("192.168.0.1");
138   IPAddr helper = IPAddr();
139   vector<GTNETS_Node*> nodes = topo_->nodes();
140   vector<GTNETS_Node*>::iterator it;
141   int id;
142   for (it = nodes.begin(); it != nodes.end(); it++){
143     id = (*it)->id();
144     gtnets_nodes_[id] = new Node();
145     gtnets_nodes_[id]->SetIPAddr(address++);
146     DEBUG2("In GTSim, add_node: %d, with IPAddr %s", id, helper.ToDotted(address-1));
147
148   }
149 }
150
151 void GTSim::node_connect(){
152
153   map<int, GTNETS_Link*> links = topo_->links();
154   map<int, GTNETS_Link*>::iterator it;
155   int linkid, srcid, dstid;
156   for (it = links.begin(); it != links.end(); it++){
157     linkid = it->second->id();
158     //if link is used in a route, connect the two nodes.
159     if (it->second->src_node() && it->second->dst_node()){
160
161       srcid = it->second->src_node()->id();
162       dstid = it->second->dst_node()->id();
163
164       gtnets_nodes_[srcid]->
165         AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
166     DEBUG3("Setting DuplexLink, src %d, dst %d, linkid %d", srcid, dstid, linkid);
167     }
168   }
169 }
170
171 // Create nodes and routes from the temporary topology, GTNETS_Topolgy.
172 void GTSim::create_gtnets_topology(){
173   add_nodes();
174   node_connect();
175 }
176
177 void GTSim::print_topology(){
178   topo_->print_topology();
179 }
180
181 // Add a route that includes more than one hop. All one hop
182 // routes must have been added. When this function is called
183 // for the first time, all gtnets nodes are generated.
184 int GTSim::add_route(int src, int dst, int* links, int nlink){
185   if (is_topology_ == 0){
186     create_gtnets_topology();
187     is_topology_ = 1;
188   }  
189
190   IPAddr_t mymask = IPAddr("255.255.255.255");
191
192   int src_node = topo_->nodeid_from_hostid(src);
193   int dst_node = topo_->nodeid_from_hostid(dst);
194
195   xbt_assert1(!(gtnets_nodes_.find(src_node) == gtnets_nodes_.end()), "Node %d not found", src_node);
196   xbt_assert1(!(gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()), "Node %d not found", dst_node);
197
198   Node* tmpsrc = gtnets_nodes_[src_node];
199   Node* tmpdst = gtnets_nodes_[dst_node];
200
201   int next_node, cur_node;
202   
203   cur_node = src_node;
204   for (int i = 0; i < nlink; i++){
205         xbt_assert1(!(gtnets_nodes_.find(cur_node) == gtnets_nodes_.end()), "Node %d not found", cur_node);
206     next_node = topo_->peer_node_id(links[i], cur_node);
207     xbt_assert0(!(next_node < 0), "Peer node not found");
208     xbt_assert1(!(gtnets_nodes_.find(next_node) == gtnets_nodes_.end()), "Node %d not found", next_node);
209     
210     //add route
211     Node* tmpcur = gtnets_nodes_[cur_node];
212     Node* tmpnext = gtnets_nodes_[next_node];
213
214     tmpcur->AddRoute(tmpdst->GetIPAddr(),
215                      mymask,
216                      tmpcur->GetIfByNode(tmpnext),
217                      tmpnext->GetIPAddr());
218
219     tmpnext->AddRoute(tmpsrc->GetIPAddr(),
220                       mymask,
221                       tmpnext->GetIfByNode(tmpcur),
222                       tmpcur->GetIPAddr());
223     
224     cur_node = next_node;
225   }
226
227   xbt_assert2(!(cur_node != dst_node), "Route inconsistency, last: %d, dst: %d",cur_node, dst_node);
228
229   return 0;
230 }
231
232
233
234 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
235   //if no route with more than one links, topology has not been generated.
236   //generate it here.
237   if (is_topology_ == 0){
238     create_gtnets_topology();
239     is_topology_ = 1;
240   }
241
242   int src_node = topo_->nodeid_from_hostid(src);
243   xbt_assert1(!(src_node < 0), "Src %d not found", src_node);
244
245   int dst_node = topo_->nodeid_from_hostid(dst);
246   xbt_assert1(!(dst_node < 0), "Dst %d not found", dst_node);
247
248   gtnets_servers_[nflow_] = (TCPServer*) gtnets_nodes_[dst_node]->
249        AddApplication(TCPServer(TCPReno()));
250   gtnets_servers_[nflow_]->BindAndListen(1000+nflow_);
251
252   gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[src_node]->
253     AddApplication(TCPSend(metadata, gtnets_nodes_[dst_node]->GetIPAddr(), 
254                            1000+nflow_, Constant(datasize), TCPReno()));
255   gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
256   gtnets_clients_[nflow_]->Start(0);
257
258   gtnets_action_to_flow_[metadata] = nflow_;
259   nflow_++;
260
261   return 0;
262 }
263
264 Time_t GTSim::get_time_to_next_flow_completion(){
265   int status;
266   Time_t t1;
267   int pfds[2];
268   int soon_pid=-1;
269   meta_flg=0;
270
271   //remain needs to be updated in the future
272   Count_t remain;
273   
274   pipe(pfds);
275   
276   t1 = 0;
277
278   if ( (soon_pid=fork()) != 0){
279     read(pfds[0], &t1, sizeof(Time_t));
280     waitpid(soon_pid, &status, 0);      
281   }else{
282     Time_t t;
283     t = sim_->RunUntilNextCompletion();
284     write(pfds[1], (const void*)&t, sizeof(Time_t));
285     exit(0);
286   }
287
288   return t1;
289 }
290
291 double GTSim::gtnets_get_flow_rx(void *metadata){
292   int flow_id = gtnets_action_to_flow_[metadata];
293   return gtnets_servers_[flow_id]->GetTotRx(); 
294 }
295
296 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
297
298   meta_flows.clear();
299   meta_nflow = number_of_flows;
300   meta_flg = 1;
301
302   Time_t t1 = sim_->RunUntilNextCompletion();
303
304   *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
305   return 0;
306 }
307
308 int GTSim::run(double delta){
309   meta_flg=0;
310   sim_->Run(delta);
311   return 0;
312 }
313
314 void GTSim::set_jitter(double d){
315   jitter_ = d;
316 }
317
318 void GTSim::set_jitter_seed(int s){
319   jitter_seed_ = s;
320 }
321
322 void static tcp_sent_callback(void* action, double completion_time){
323   // Schedule the flow complete event.
324   SimulatorEvent* e =
325     new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
326   Simulator::instance->Schedule(e, 0, Simulator::instance);
327
328   if (meta_flg){
329     meta_flows.push_back(action);
330     (*meta_nflow)++;
331   }
332 }
333
334