Logo AND Algorithmique Numérique Distribuée

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