Logo AND Algorithmique Numérique Distribuée

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