2 /* Copyright (c) 2007 Kayo Fujiwara. All rights reserved. */
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. */
7 #include "gtnets_simulator.h"
8 #include "gtnets_topology.h"
14 static vector<void*> meta_flows;
15 static int* meta_nflow;
16 static int meta_flg = 0;
18 void static tcp_sent_callback(void* action, double completion_time);
21 // TODO: check the default values.
26 sim_ = new Simulator();
27 topo_ = new GTNETS_Topology();
30 // Set default values.
31 TCP::DefaultAdvWin(wsize);
32 TCP::DefaultSegSize(1000);
33 TCP::DefaultTxBuffer(128000);
34 TCP::DefaultRxBuffer(128000);
37 rm_ = new RoutingManual();
38 Routing::SetRouting(rm_);
43 map<int, Linkp2p*>::iterator it;
44 for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
47 while (!gtnets_links_.empty())
48 gtnets_links_.erase(gtnets_links_.begin());
50 map<int, Node*>::iterator it3;
51 for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
54 while (!gtnets_nodes_.empty())
55 gtnets_nodes_.erase(gtnets_nodes_.begin());
57 map<int, TCPServer*>::iterator it4;
58 for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
61 while (!gtnets_servers_.empty())
62 gtnets_servers_.erase(gtnets_servers_.begin());
64 map<int, TCPSend*>::iterator it5;
65 for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
68 while (!gtnets_clients_.empty())
69 gtnets_clients_.erase(gtnets_clients_.begin());
80 int GTSim::add_router(int id){
81 if (topo_->add_router(id) < 0){
82 fprintf(stderr, "can't add router %d. already exists.\n", id);
87 //bandwidth: in bytes.
88 //latency: in seconds.
89 int GTSim::add_link(int id, double bandwidth, double latency){
90 double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS).
91 if (topo_->add_link(id) < 0){
92 fprintf(stderr, "can't add link %d. already exists.\n", id);
95 gtnets_links_[id] = new Linkp2p(bw, latency);
99 // if gtnets_nodes_ includes id, return true, otherwise return false.
100 bool GTSim::node_include(int id){
101 if (gtnets_nodes_.find(id) != gtnets_nodes_.end()) return true;
105 // if gtnets_link_ includes id, return true, otherwise return false.
106 bool GTSim::link_include(int id){
107 if (gtnets_links_.find(id) != gtnets_links_.end()) return true;
111 int GTSim::add_onehop_route(int src, int dst, int link){
112 if (topo_->add_onehop_route(src, dst, link) < 0){
113 fprintf(stderr, "Cannot add a route, src: %d, dst: %d, link: %d\n",
120 // Generate the gtnets nodes according to topo_.
121 void GTSim::add_nodes(){
122 static unsigned int address = IPAddr("192.168.0.1");
123 vector<GTNETS_Node*> nodes = topo_->nodes();
124 vector<GTNETS_Node*>::iterator it;
126 for (it = nodes.begin(); it != nodes.end(); it++){
128 gtnets_nodes_[id] = new Node();
129 gtnets_nodes_[id]->SetIPAddr(address++);
130 // printf("In GTSim, add_node: %d\n", id);
134 void GTSim::node_connect(){
136 map<int, GTNETS_Link*> links = topo_->links();
137 map<int, GTNETS_Link*>::iterator it;
138 int linkid, srcid, dstid;
139 for (it = links.begin(); it != links.end(); it++){
140 linkid = it->second->id();
141 //if link is used in a route, connect the two nodes.
142 if (it->second->src_node() && it->second->dst_node()){
144 srcid = it->second->src_node()->id();
145 dstid = it->second->dst_node()->id();
147 gtnets_nodes_[srcid]->
148 AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
153 // Create nodes and routes from the temporary topology, GTNETS_Topolgy.
154 void GTSim::create_gtnets_topology(){
159 // Add a route that includes more than one hop. All one hop
160 // routes must have been added. When this function is called
161 // for the first time, all gtnets nodes are generated.
162 int GTSim::add_route(int src, int dst, int* links, int nlink){
163 if (is_topology_ == 0){
164 create_gtnets_topology();
165 // topo_->print_topology();
169 IPAddr_t mymask = IPAddr("255.255.255.255");
171 int src_node = topo_->nodeid_from_hostid(src);
172 int dst_node = topo_->nodeid_from_hostid(dst);
174 if (gtnets_nodes_.find(src_node) == gtnets_nodes_.end()){
175 fprintf(stderr, "node %d not found\n", src_node);
178 if (gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()){
179 fprintf(stderr, "node %d not found\n", dst_node);
183 Node* tmpsrc = gtnets_nodes_[src_node];
184 Node* tmpdst = gtnets_nodes_[dst_node];
186 int next_node, cur_node;
189 for (int i = 0; i < nlink; i++){
190 if (gtnets_nodes_.find(cur_node) == gtnets_nodes_.end()){
191 fprintf(stderr, "node %d not found\n", cur_node);
194 next_node = topo_->peer_node_id(links[i], cur_node);
196 fprintf(stderr, "peer node not found\n");
199 if (gtnets_nodes_.find(next_node) == gtnets_nodes_.end()){
200 fprintf(stderr, "node %d not found\n", next_node);
205 Node* tmpcur = gtnets_nodes_[cur_node];
206 Node* tmpnext = gtnets_nodes_[next_node];
208 tmpcur->AddRoute(tmpdst->GetIPAddr(),
210 tmpcur->GetIfByNode(tmpnext),
211 tmpnext->GetIPAddr());
213 tmpnext->AddRoute(tmpsrc->GetIPAddr(),
215 tmpnext->GetIfByNode(tmpcur),
216 tmpcur->GetIPAddr());
218 cur_node = next_node;
221 if (cur_node != dst_node){
222 fprintf(stderr, "Route inconsistency, last: %d, dst: %d\n",
232 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
233 //if no route with more than one links, topology has not been generated.
235 if (is_topology_ == 0){
236 create_gtnets_topology();
237 // topo_->print_topology();
241 int src_node = topo_->nodeid_from_hostid(src);
243 fprintf(stderr, "src %d not found\n");
246 int dst_node = topo_->nodeid_from_hostid(dst);
248 fprintf(stderr, "dst %d not found\n");
252 gtnets_servers_[nflow_] = (TCPServer*)gtnets_nodes_[dst_node]->
253 AddApplication(TCPServer(TCPReno()));
254 //added by arnaud in order to avoid TCPServer duplicates.
255 //It is not needed since we create a new TCPServer for
256 //each flow. Also we need to control this variable
257 //to proper set the value of remaining communication amount.
259 gtnets_servers_[nflow_]->copyOnConnect=false;
260 gtnets_servers_[nflow_]->BindAndListen(80);
262 gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[src_node]->
263 AddApplication(TCPSend(metadata, gtnets_nodes_[dst_node]->GetIPAddr(),
264 80, Constant(datasize), TCPReno()));
265 gtnets_clients_[nflow_]->copyOnConnect=false;
266 gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
267 gtnets_clients_[nflow_]->Start(0);
269 //added by pedro in order to get statistics
270 //map an action from a gtnets flow id
271 //metadata is the action and flow is the id to gtnets
272 gtnets_action_to_flow_[metadata] = nflow_;
278 Time_t GTSim::get_time_to_next_flow_completion(){
284 //remain needs to be updated in the future
291 read(pfds[0], &t1, sizeof(Time_t));
292 waitpid(-1, &status, 0);
295 t = sim_->RunUntilNextCompletion();
296 write(pfds[1], (const void*)&t, sizeof(Time_t));
303 double GTSim::gtnets_get_flow_rx(void *metadata){
304 int flow = gtnets_action_to_flow_[metadata];
305 return ((TCPServer *)gtnets_servers_[flow])->totRx;//action_remain[flow];
308 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
310 meta_nflow = number_of_flows;
313 Time_t t1 = sim_->RunUntilNextCompletion();
315 *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
319 int GTSim::run(double delta){
326 void static tcp_sent_callback(void* action, double completion_time){
327 // Schedule the flow complete event.
329 new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
330 Simulator::instance->Schedule(e, 0, Simulator::instance);
333 meta_flows.push_back(action);