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"
15 #include "xbt/asserts.h"
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets_simulator, surf_network_gtnets,
18 "Logging specific to the SURF network GTNetS simulator");
23 static vector<void*> meta_flows;
24 static int* meta_nflow;
25 static int meta_flg = 0;
28 void static tcp_sent_callback(void* action, double completion_time);
31 // TODO: check the default values.
36 sim_ = new Simulator();
37 topo_ = new GTNETS_Topology();
42 // Set default values.
43 TCP::DefaultAdvWin(wsize);
44 TCP::DefaultSegSize(1000);
45 TCP::DefaultTxBuffer(128000);
46 TCP::DefaultRxBuffer(128000);
49 rm_ = new RoutingManual();
50 Routing::SetRouting(rm_);
55 map<int, Linkp2p*>::iterator it;
56 for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
59 while (!gtnets_links_.empty())
60 gtnets_links_.erase(gtnets_links_.begin());
62 map<int, Uniform*>::iterator it2;
63 for (it2 = uniform_jitter_generator_.begin(); it2 != uniform_jitter_generator_.end(); it2++){
66 while (!uniform_jitter_generator_.empty())
67 uniform_jitter_generator_.erase(uniform_jitter_generator_.begin());
69 map<int, Node*>::iterator it3;
70 for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
73 while (!gtnets_nodes_.empty())
74 gtnets_nodes_.erase(gtnets_nodes_.begin());
76 map<int, TCPServer*>::iterator it4;
77 for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
80 while (!gtnets_servers_.empty())
81 gtnets_servers_.erase(gtnets_servers_.begin());
83 map<int, TCPSend*>::iterator it5;
84 for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
87 while (!gtnets_clients_.empty())
88 gtnets_clients_.erase(gtnets_clients_.begin());
99 int GTSim::add_router(int id){
100 xbt_assert1(!(topo_->add_router(id) < 0), "can't add router %d. already exists", id);
103 //bandwidth: in bytes.
104 //latency: in seconds.
105 int GTSim::add_link(int id, double bandwidth, double latency){
106 double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS).
107 xbt_assert1(!(topo_->add_link(id) < 0),"Can't add link %d. already exists", id);
108 DEBUG3("Creating a new P2P, linkid %d, bandwidth %gl, latency %gl", id, bandwidth, latency);
109 gtnets_links_[id] = new Linkp2p(bw, latency);
111 DEBUG2("Using jitter %f, and seed %u", jitter_, jitter_seed_);
112 double min = -1*jitter_*latency;
113 double max = jitter_*latency;
114 //initialize the random seed only once, when adding the first link
115 if(uniform_jitter_generator_.empty()){
116 Random::GlobalSeed(jitter_seed_ , jitter_seed_+1, jitter_seed_+2,
117 jitter_seed_+3, jitter_seed_+4, jitter_seed_+5);
119 uniform_jitter_generator_[id] = new Uniform(min,max);
120 gtnets_links_[id]->Jitter((const Random &) *(uniform_jitter_generator_[id]));
125 // if gtnets_nodes_ includes id, return true, otherwise return false.
126 bool GTSim::node_include(int id){
127 if (gtnets_nodes_.find(id) != gtnets_nodes_.end()) return true;
131 // if gtnets_link_ includes id, return true, otherwise return false.
132 bool GTSim::link_include(int id){
133 if (gtnets_links_.find(id) != gtnets_links_.end()) return true;
137 int GTSim::add_onehop_route(int src, int dst, int link){
138 xbt_assert3(!(topo_->add_onehop_route(src, dst, link) < 0), "Cannot add a route, src: %d, dst: %d, link: %d", src, dst, link);
142 // Generate the gtnets nodes according to topo_.
143 void GTSim::add_nodes(){
144 static unsigned int address = IPAddr("192.168.0.1");
145 IPAddr helper = IPAddr();
146 vector<GTNETS_Node*> nodes = topo_->nodes();
147 vector<GTNETS_Node*>::iterator it;
149 for (it = nodes.begin(); it != nodes.end(); it++){
151 gtnets_nodes_[id] = new Node();
152 gtnets_nodes_[id]->SetIPAddr(address++);
153 DEBUG2("In GTSim, add_node: %d, with IPAddr %s", id, helper.ToDotted(address-1));
158 void GTSim::node_connect(){
160 map<int, GTNETS_Link*> links = topo_->links();
161 map<int, GTNETS_Link*>::iterator it;
162 int linkid, srcid, dstid;
163 for (it = links.begin(); it != links.end(); it++){
164 linkid = it->second->id();
165 //if link is used in a route, connect the two nodes.
166 if (it->second->src_node() && it->second->dst_node()){
168 srcid = it->second->src_node()->id();
169 dstid = it->second->dst_node()->id();
171 gtnets_nodes_[srcid]->
172 AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
173 DEBUG3("Setting DuplexLink, src %d, dst %d, linkid %d", srcid, dstid, linkid);
178 // Create nodes and routes from the temporary topology, GTNETS_Topolgy.
179 void GTSim::create_gtnets_topology(){
184 void GTSim::print_topology(){
185 topo_->print_topology();
188 // Add a route that includes more than one hop. All one hop
189 // routes must have been added. When this function is called
190 // for the first time, all gtnets nodes are generated.
191 int GTSim::add_route(int src, int dst, int* links, int nlink){
192 if (is_topology_ == 0){
193 create_gtnets_topology();
197 IPAddr_t mymask = IPAddr("255.255.255.255");
199 int src_node = topo_->nodeid_from_hostid(src);
200 int dst_node = topo_->nodeid_from_hostid(dst);
202 xbt_assert1(!(gtnets_nodes_.find(src_node) == gtnets_nodes_.end()), "Node %d not found", src_node);
203 xbt_assert1(!(gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()), "Node %d not found", dst_node);
205 Node* tmpsrc = gtnets_nodes_[src_node];
206 Node* tmpdst = gtnets_nodes_[dst_node];
208 int next_node, cur_node;
211 for (int i = 0; i < nlink; i++){
212 xbt_assert1(!(gtnets_nodes_.find(cur_node) == gtnets_nodes_.end()), "Node %d not found", cur_node);
213 next_node = topo_->peer_node_id(links[i], cur_node);
214 xbt_assert0(!(next_node < 0), "Peer node not found");
215 xbt_assert1(!(gtnets_nodes_.find(next_node) == gtnets_nodes_.end()), "Node %d not found", next_node);
218 Node* tmpcur = gtnets_nodes_[cur_node];
219 Node* tmpnext = gtnets_nodes_[next_node];
221 tmpcur->AddRoute(tmpdst->GetIPAddr(),
223 tmpcur->GetIfByNode(tmpnext),
224 tmpnext->GetIPAddr());
226 tmpnext->AddRoute(tmpsrc->GetIPAddr(),
228 tmpnext->GetIfByNode(tmpcur),
229 tmpcur->GetIPAddr());
231 cur_node = next_node;
234 xbt_assert2(!(cur_node != dst_node), "Route inconsistency, last: %d, dst: %d",cur_node, dst_node);
241 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
242 //if no route with more than one links, topology has not been generated.
244 if (is_topology_ == 0){
245 create_gtnets_topology();
249 int src_node = topo_->nodeid_from_hostid(src);
250 xbt_assert1(!(src_node < 0), "Src %d not found", src_node);
252 int dst_node = topo_->nodeid_from_hostid(dst);
253 xbt_assert1(!(dst_node < 0), "Dst %d not found", dst_node);
255 gtnets_servers_[nflow_] = (TCPServer*) gtnets_nodes_[dst_node]->
256 AddApplication(TCPServer(TCPReno()));
257 gtnets_servers_[nflow_]->BindAndListen(1000+nflow_);
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);
265 gtnets_action_to_flow_[metadata] = nflow_;
271 Time_t GTSim::get_time_to_next_flow_completion(){
278 //remain needs to be updated in the future
285 if ( (soon_pid=fork()) != 0){
286 read(pfds[0], &t1, sizeof(Time_t));
287 waitpid(soon_pid, &status, 0);
290 t = sim_->RunUntilNextCompletion();
291 write(pfds[1], (const void*)&t, sizeof(Time_t));
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();
303 int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
306 meta_nflow = number_of_flows;
309 Time_t t1 = sim_->RunUntilNextCompletion();
311 *metadata = (meta_flows.empty() ? NULL : &meta_flows[0]);
315 int GTSim::run(double delta){
321 void GTSim::set_jitter(double d){
322 xbt_assert1(((0 <= d)&&(d <= 1)), "The jitter value must be within interval [0.0;1.0], got %f", d);
326 void GTSim::set_jitter_seed(int s){
330 void static tcp_sent_callback(void* action, double completion_time){
331 // Schedule the flow complete event.
333 new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
334 Simulator::instance->Schedule(e, 0, Simulator::instance);
337 meta_flows.push_back(action);