Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bug fixes.
[simgrid.git] / src / surf / gtnets / gtnets_simulator.cc
1 //Kayo Fujiwara 1/8/2007
2 #include "gtnets_simulator.h"
3 #include "gtnets_topology.h"
4 #include <map>
5 #include <vector>
6
7 using namespace std;
8
9 static vector<void*> meta_flows;
10 static int* meta_nflow;
11 static int meta_flg = 0;
12
13 void static tcp_sent_callback(void* action, double completion_time);
14
15 // Constructor.
16 // TODO: check the default values.
17 GTSim::GTSim(){
18   int wsize = 20000;
19   is_topology_ = 0;
20   nflow_ = 0;
21   sim_ = new Simulator();
22   topo_ = new SGTopology();
23
24   // Set default values.
25   TCP::DefaultAdvWin(wsize);
26   TCP::DefaultSegSize(1000);
27   TCP::DefaultTxBuffer(128000);
28   TCP::DefaultRxBuffer(128000);
29
30 }
31 GTSim::~GTSim(){
32
33   map<int, Linkp2p*>::iterator it;
34   for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
35     delete it->second;
36   }
37   map<int, SGLink*>::iterator it2;
38   for (it2 = tmp_links_.begin(); it2 != tmp_links_.end(); it2++){
39     delete it2->second;
40   }
41   map<int, Node*>::iterator it3;
42   for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
43     delete it3->second;
44   }
45   map<int, TCPServer*>::iterator it4;
46   for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
47     delete it4->second;
48   }
49   map<int, TCPSend*>::iterator it5;
50   for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
51     delete it5->second;
52   }
53   //TODO delete other objects!
54 }
55
56
57 int GTSim::add_link(int id, double bandwidth, double latency){
58   if (gtnets_links_.find(id) != gtnets_links_.end()){
59     fprintf(stderr, "can't add link %d. already exists.\n", id);
60     return -1;
61   }
62   gtnets_links_[id] = new Linkp2p(bandwidth, latency);
63   return 0;
64 }
65
66 int GTSim::add_route(int src, int dst, int* links, int nlink){
67   topo_->add_link(src, dst, links, nlink);
68   //  topo_->create_tmplink(src, dst, links, nlink);
69   return 0;
70 }
71
72 void GTSim::create_gtnets_topology(){
73   //TODO: add manual routing
74   //TODO: is this addressing fine?
75   static unsigned int address = IPAddr("192.168.0.1");
76   tmp_links_ = topo_->get_links();
77   map<int, SGLink*>::iterator it;
78
79   //By now, all links has two nodes.
80   //Connect left and right with the link.
81   for (it = tmp_links_.begin(); it != tmp_links_.end(); it++){
82     it->second->print();
83     //both nodes must be not null. TODO check it!
84     int linkid = it->second->id();
85     int leftid = it->second->left_node()->id();
86     int rightid = it->second->right_node()->id();
87
88     cout << "linkid: " << linkid << endl;
89     cout << "leftid: " << leftid << endl;
90     cout << "rightid: " << rightid << endl;
91
92
93     map<int, Node*>::iterator nodeit = gtnets_nodes_.find(leftid);
94     // if the nodes don't exist, add one.
95     if (nodeit == gtnets_nodes_.end()){
96       gtnets_nodes_[leftid] = new Node();
97       gtnets_nodes_[leftid]->SetIPAddr(address++);
98       //add host-node relationships.
99       vector<int> tmphosts = it->second->left_node()->hosts();
100
101       for (int i = 0; i < tmphosts.size(); i++){
102         gtnets_hosts_[tmphosts[i]] = leftid;
103         cout << "host: " << tmphosts[i] << " node: " << leftid << endl;
104       }
105
106     }
107     nodeit = gtnets_nodes_.find(rightid);
108     if (nodeit == gtnets_nodes_.end()){//new entry
109       gtnets_nodes_[rightid] = new Node();
110       gtnets_nodes_[rightid]->SetIPAddr(address++);
111
112       //add host-node relationships.
113       vector<int> tmphosts = it->second->right_node()->hosts();
114
115       for (int i = 0; i < tmphosts.size(); i++){
116         gtnets_hosts_[tmphosts[i]] = rightid;
117         cout << "host: " << tmphosts[i] << " node: " << rightid << endl;
118       }
119     }
120
121     gtnets_nodes_[leftid]->
122       AddDuplexLink(gtnets_nodes_[rightid], *gtnets_links_[linkid]);
123
124   }
125 }
126
127 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
128   if (is_topology_ == 0){
129     create_gtnets_topology();
130     is_topology_ = 1;
131   }
132   //TODO: what if more than two flows?
133   //TODO: check if src and dst exists.
134   //TODO: should use "flowID" to name servers and clients.
135   gtnets_servers_[nflow_] = (TCPServer*)gtnets_nodes_[gtnets_hosts_[dst]]->
136     AddApplication(TCPServer(TCPReno()));
137   gtnets_servers_[nflow_]->BindAndListen(80);
138
139   gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[gtnets_hosts_[src]]->
140     AddApplication(TCPSend(metadata, gtnets_nodes_[gtnets_hosts_[dst]]->GetIPAddr(), 
141                            80, Constant(datasize), TCPReno()));
142   gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
143   gtnets_clients_[nflow_]->Start(0);
144   nflow_++;
145
146   return 0;
147 }
148
149 Time_t GTSim::get_time_to_next_flow_completion(){
150   int status;
151   Time_t t1;
152   int pfds[2];
153   meta_flg=0;
154   
155   pipe(pfds);
156   
157   t1 = 0;
158   if (fork() != 0){
159     read(pfds[0], &t1, sizeof(Time_t));
160     waitpid(-1, &status, 0);      
161   }else{
162     Time_t t;
163     t = sim_->RunUntilNextCompletion();
164     write(pfds[1], (const void*)&t, sizeof(Time_t));
165     exit(0);
166   }
167   return t1;
168 }
169
170 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
171   meta_flows.clear();
172   meta_nflow = number_of_flows;
173   meta_flg = 1;
174
175   Time_t t1 = sim_->RunUntilNextCompletion();
176
177   *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
178   return 0;
179 }
180
181 int GTSim::run(double delta){
182   meta_flg=0;
183   sim_->Run(delta);
184   return 0;
185 }
186
187 // Clean up.
188 int GTSim::finalize(){
189   //TODO
190   is_topology_ = 0;
191   delete sim_;
192   delete topo_;
193   return 0;
194 }
195
196 void static tcp_sent_callback(void* action, double completion_time){
197   // Schedule the flow complete event.
198   SimulatorEvent* e =
199     new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
200   Simulator::instance->Schedule(e, 0, Simulator::instance);
201
202   if (meta_flg){
203     meta_flows.push_back(action);
204     (*meta_nflow)++;
205   }
206 }
207