Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix bugs...
authorkayof <kayof@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 4 Jun 2007 10:11:58 +0000 (10:11 +0000)
committerkayof <kayof@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 4 Jun 2007 10:11:58 +0000 (10:11 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@3551 48e7efb5-ca39-0410-a469-dd3cf9ba447f

src/surf/gtnets/gtnets_interface.cc
src/surf/gtnets/gtnets_interface.h
src/surf/gtnets/gtnets_simulator.cc
src/surf/gtnets/gtnets_simulator.h
src/surf/gtnets/gtnets_topology.cc
src/surf/gtnets/gtnets_topology.h

index c7df7d2..ab9b0aa 100644 (file)
@@ -1,3 +1,8 @@
+/*     $Id$     */
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include "gtnets_simulator.h"
 #include "gtnets_interface.h"
@@ -14,29 +19,34 @@ int gtnets_initialize(){
   return 0;
 }
 
-// adds a link (argument link is just an index starting at 0... 
+// add a link (argument link is just an index starting at 0... 
 // add link 0, add link 1, etc.)
 int gtnets_add_link(int id, double bandwidth, double latency){
-  printf("gtnets_add_link: %d, %f, %f\n", id, bandwidth, latency);
   return gtnets_sim->add_link(id, bandwidth, latency);
 }
 
-// adds a route between a source and a destination as an array of link indices
+// add a route between a source and a destination as an array of link indices
 // (note that there is no gtnets_add_network_card(), as we discover them
 // on the fly via calls to gtnets_add_route()
 int gtnets_add_route(int src, int dst, int* links, int nlink){
-  int i;
-  printf("gtnets_add_route: %d, %d\n", src, dst);
-  for (i = 0; i < nlink; i++){
-    printf("%d: %d\n", i, *links++);
-  }
   return gtnets_sim->add_route(src, dst, links, nlink);
 }
 
+// add a router
+int gtnets_add_router(int id){
+  return gtnets_sim->add_router(id);
+}
+
+// add a route between a source and a destination as an array of link indices
+// (note that there is no gtnets_add_network_card(), as we discover them
+// on the fly via calls to gtnets_add_route()
+int gtnets_add_onehop_route(int src, int dst, int link){
+  return gtnets_sim->add_onehop_route(src, dst, link);
+}
+
 // create a new flow on a route
 // one can attach arbitrary metadata to a flow
 int gtnets_create_flow(int src, int dst, long datasize, void* metadata){
-  printf("gtnets_create_flow: %d, %d, %d\n", src, dst, datasize);
   return gtnets_sim->create_flow(src, dst, datasize, metadata);
 }
 
@@ -60,7 +70,6 @@ int gtnets_run(Time_t deltat){
 // clean up
 int gtnets_finalize(){
   if (!gtnets_sim) return -1;
-  gtnets_sim->finalize();
   delete gtnets_sim;
   gtnets_sim = 0;
   return 0;
index 8936fa0..aa3f2d2 100644 (file)
@@ -1,6 +1,10 @@
-// Interface for GTNetS.
-// Kayo Fujiwara 1/8/2007
+/*     $Id$     */
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
 
+// Interface for GTNetS.
 #ifndef _GTNETS_INTERFACE_H
 #define _GTNETS_INTERFACE_H
 
@@ -11,6 +15,8 @@ extern "C" {
   int gtnets_initialize();
   int gtnets_add_link(int id, double bandwidth, double latency);
   int gtnets_add_route(int src, int dst, int* links, int nlink);
+  int gtnets_add_router(int id);
+  int gtnets_add_onehop_route(int src, int dst, int link);
   int gtnets_create_flow(int src, int dst, long datasize, void* metadata);
   double gtnets_get_time_to_next_flow_completion();
   int gtnets_run_until_next_flow_completion(void*** metadata, int* number_of_flows);
index 7feb325..eac36f4 100644 (file)
@@ -1,4 +1,9 @@
-//Kayo Fujiwara 1/8/2007
+/*     $Id$     */
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
 #include "gtnets_simulator.h"
 #include "gtnets_topology.h"
 #include <map>
@@ -19,7 +24,7 @@ GTSim::GTSim(){
   is_topology_ = 0;
   nflow_ = 0;
   sim_ = new Simulator();
-  topo_ = new SGTopology();
+  topo_ = new GTNETS_Topology();
 
   // Set default values.
   TCP::DefaultAdvWin(wsize);
@@ -27,117 +32,228 @@ GTSim::GTSim(){
   TCP::DefaultTxBuffer(128000);
   TCP::DefaultRxBuffer(128000);
 
+  // Manual routing
+  rm_ = new RoutingManual();
+  Routing::SetRouting(rm_);
 }
+
 GTSim::~GTSim(){
 
   map<int, Linkp2p*>::iterator it;
   for (it = gtnets_links_.begin(); it != gtnets_links_.end(); it++){
     delete it->second;
   }
-  map<int, SGLink*>::iterator it2;
-  for (it2 = tmp_links_.begin(); it2 != tmp_links_.end(); it2++){
-    delete it2->second;
-  }
+  while (!gtnets_links_.empty())
+    gtnets_links_.erase(gtnets_links_.begin());
+
   map<int, Node*>::iterator it3;
   for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
     delete it3->second;
   }
+  while (!gtnets_nodes_.empty())
+    gtnets_nodes_.erase(gtnets_nodes_.begin());
+
   map<int, TCPServer*>::iterator it4;
   for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
     delete it4->second;
   }
+  while (!gtnets_servers_.empty())
+    gtnets_servers_.erase(gtnets_servers_.begin());
+
   map<int, TCPSend*>::iterator it5;
   for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
     delete it5->second;
   }
-  //TODO delete other objects!
+  while (!gtnets_clients_.empty())
+    gtnets_clients_.erase(gtnets_clients_.begin());
+
+  is_topology_ = 0;
+  delete sim_;
+  delete topo_;
+  delete rm_;
+  sim_ = 0;
+  topo_ = 0;
+  rm_ = 0;
 }
 
+int GTSim::add_router(int id){
+  if (topo_->add_router(id) < 0){
+    fprintf(stderr, "can't add router %d. already exists.\n", id);
+    return -1;
+  }
+}
 
+//bandwidth: in bytes.
+//latency: in seconds.
 int GTSim::add_link(int id, double bandwidth, double latency){
-  if (gtnets_links_.find(id) != gtnets_links_.end()){
+  double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS).
+  if (topo_->add_link(id) < 0){
     fprintf(stderr, "can't add link %d. already exists.\n", id);
     return -1;
   }
-  gtnets_links_[id] = new Linkp2p(bandwidth, latency);
+  gtnets_links_[id] = new Linkp2p(bw, latency);
   return 0;
 }
 
-int GTSim::add_route(int src, int dst, int* links, int nlink){
-  topo_->add_link(src, dst, links, nlink);
-  //  topo_->create_tmplink(src, dst, links, nlink);
+// if gtnets_nodes_ includes id, return true, otherwise return false.
+bool GTSim::node_include(int id){
+  if (gtnets_nodes_.find(id) != gtnets_nodes_.end()) return true;
+  else return false;
+}
+
+// if gtnets_link_ includes id, return true, otherwise return false.
+bool GTSim::link_include(int id){
+  if (gtnets_links_.find(id) != gtnets_links_.end()) return true;
+  else return false;
+}
+
+int GTSim::add_onehop_route(int src, int dst, int link){
+  if (topo_->add_onehop_route(src, dst, link) < 0){
+    fprintf(stderr, "Cannot add a route, src: %d, dst: %d, link: %d\n",
+           src, dst, link);
+    return -1;
+  }
   return 0;
 }
 
-void GTSim::create_gtnets_topology(){
-  //TODO: add manual routing
-  //TODO: is this addressing fine?
+// Generate the gtnets nodes according to topo_.
+void GTSim::add_nodes(){
   static unsigned int address = IPAddr("192.168.0.1");
-  tmp_links_ = topo_->get_links();
-  map<int, SGLink*>::iterator it;
-
-  //By now, all links has two nodes.
-  //Connect left and right with the link.
-  for (it = tmp_links_.begin(); it != tmp_links_.end(); it++){
-    it->second->print();
-    //both nodes must be not null. TODO check it!
-    int linkid = it->second->id();
-    int leftid = it->second->left_node()->id();
-    int rightid = it->second->right_node()->id();
-
-    cout << "linkid: " << linkid << endl;
-    cout << "leftid: " << leftid << endl;
-    cout << "rightid: " << rightid << endl;
-
-
-    map<int, Node*>::iterator nodeit = gtnets_nodes_.find(leftid);
-    // if the nodes don't exist, add one.
-    if (nodeit == gtnets_nodes_.end()){
-      gtnets_nodes_[leftid] = new Node();
-      gtnets_nodes_[leftid]->SetIPAddr(address++);
-      //add host-node relationships.
-      vector<int> tmphosts = it->second->left_node()->hosts();
-
-      for (int i = 0; i < tmphosts.size(); i++){
-       gtnets_hosts_[tmphosts[i]] = leftid;
-       cout << "host: " << tmphosts[i] << " node: " << leftid << endl;
-      }
+  vector<GTNETS_Node*> nodes = topo_->nodes();
+  vector<GTNETS_Node*>::iterator it;
+  int id;
+  for (it = nodes.begin(); it != nodes.end(); it++){
+    id = (*it)->id();
+    gtnets_nodes_[id] = new Node();
+    gtnets_nodes_[id]->SetIPAddr(address++);
+    //    printf("In GTSim, add_node: %d\n", id);
+  }
+}
 
+void GTSim::node_connect(){
+
+  map<int, GTNETS_Link*> links = topo_->links();
+  map<int, GTNETS_Link*>::iterator it;
+  int linkid, srcid, dstid;
+  for (it = links.begin(); it != links.end(); it++){
+    linkid = it->second->id();
+    //if link is used in a route, connect the two nodes.
+    if (it->second->src_node() && it->second->dst_node()){
+
+      srcid = it->second->src_node()->id();
+      dstid = it->second->dst_node()->id();
+
+      gtnets_nodes_[srcid]->
+       AddDuplexLink(gtnets_nodes_[dstid], *(gtnets_links_[linkid]));
     }
-    nodeit = gtnets_nodes_.find(rightid);
-    if (nodeit == gtnets_nodes_.end()){//new entry
-      gtnets_nodes_[rightid] = new Node();
-      gtnets_nodes_[rightid]->SetIPAddr(address++);
-
-      //add host-node relationships.
-      vector<int> tmphosts = it->second->right_node()->hosts();
-
-      for (int i = 0; i < tmphosts.size(); i++){
-       gtnets_hosts_[tmphosts[i]] = rightid;
-       cout << "host: " << tmphosts[i] << " node: " << rightid << endl;
-      }
-    }
+  }
+}
+
+// Create nodes and routes from the temporary topology, GTNETS_Topolgy.
+void GTSim::create_gtnets_topology(){
+  add_nodes();
+  node_connect();
+}
+
+// Add a route that includes more than one hop. All one hop
+// routes must have been added. When this function is called
+// for the first time, all gtnets nodes are generated.
+int GTSim::add_route(int src, int dst, int* links, int nlink){
+  if (is_topology_ == 0){
+    create_gtnets_topology();
+    //    topo_->print_topology();
+    is_topology_ = 1;
+  }  
+
+  IPAddr_t mymask = IPAddr("255.255.255.255");
 
-    gtnets_nodes_[leftid]->
-      AddDuplexLink(gtnets_nodes_[rightid], *gtnets_links_[linkid]);
+  int src_node = topo_->nodeid_from_hostid(src);
+  int dst_node = topo_->nodeid_from_hostid(dst);
+
+  if (gtnets_nodes_.find(src_node) == gtnets_nodes_.end()){
+    fprintf(stderr, "node %d not found\n", src_node);
+    return -1;
+  }
+  if (gtnets_nodes_.find(dst_node) == gtnets_nodes_.end()){
+    fprintf(stderr, "node %d not found\n", dst_node);
+    return -1;
+  }
+
+  Node* tmpsrc = gtnets_nodes_[src_node];
+  Node* tmpdst = gtnets_nodes_[dst_node];
+
+  int next_node, cur_node;
+  
+  cur_node = src_node;
+  for (int i = 0; i < nlink; i++){
+    if (gtnets_nodes_.find(cur_node) == gtnets_nodes_.end()){
+      fprintf(stderr, "node %d not found\n", cur_node);
+      return -1;
+    }
+    next_node = topo_->peer_node_id(links[i], cur_node);
+    if (next_node < 0){
+      fprintf(stderr, "peer node not found\n");
+      return -1;
+    }
+    if (gtnets_nodes_.find(next_node) == gtnets_nodes_.end()){
+      fprintf(stderr, "node %d not found\n", next_node);
+      return -1;
+    }
+    
+    //add route
+    Node* tmpcur = gtnets_nodes_[cur_node];
+    Node* tmpnext = gtnets_nodes_[next_node];
+
+    tmpcur->AddRoute(tmpdst->GetIPAddr(),
+                    mymask,
+                    tmpcur->GetIfByNode(tmpnext),
+                    tmpnext->GetIPAddr());
+
+    tmpnext->AddRoute(tmpsrc->GetIPAddr(),
+                     mymask,
+                     tmpnext->GetIfByNode(tmpcur),
+                     tmpcur->GetIPAddr());
+    
+    cur_node = next_node;
+  }
 
+  if (cur_node != dst_node){
+    fprintf(stderr, "Route inconsistency, last: %d, dst: %d\n",
+           cur_node, dst_node);
+    return -1;
   }
+
+  return 0;
 }
 
+
+
 int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
+  //if no route with more than one links, topology has not been generated.
+  //generate it here.
   if (is_topology_ == 0){
     create_gtnets_topology();
+    //    topo_->print_topology();
     is_topology_ = 1;
   }
-  //TODO: what if more than two flows?
-  //TODO: check if src and dst exists.
-  //TODO: should use "flowID" to name servers and clients.
-  gtnets_servers_[nflow_] = (TCPServer*)gtnets_nodes_[gtnets_hosts_[dst]]->
-    AddApplication(TCPServer(TCPReno()));
+
+  int src_node = topo_->nodeid_from_hostid(src);
+  if (src_node < 0){
+    fprintf(stderr, "src %d not found\n");
+    return -1;
+  }
+  int dst_node = topo_->nodeid_from_hostid(dst);
+  if (dst_node < 0){
+    fprintf(stderr, "dst %d not found\n");
+    return -1;
+  }
+
+  gtnets_servers_[nflow_] = (TCPServer*)gtnets_nodes_[dst_node]->
+       AddApplication(TCPServer(TCPReno()));
   gtnets_servers_[nflow_]->BindAndListen(80);
 
-  gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[gtnets_hosts_[src]]->
-    AddApplication(TCPSend(metadata, gtnets_nodes_[gtnets_hosts_[dst]]->GetIPAddr(), 
+  gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[src_node]->
+    AddApplication(TCPSend(metadata, gtnets_nodes_[dst_node]->GetIPAddr(), 
                           80, Constant(datasize), TCPReno()));
   gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
   gtnets_clients_[nflow_]->Start(0);
@@ -164,6 +280,7 @@ Time_t GTSim::get_time_to_next_flow_completion(){
     write(pfds[1], (const void*)&t, sizeof(Time_t));
     exit(0);
   }
+
   return t1;
 }
 
@@ -184,14 +301,6 @@ int GTSim::run(double delta){
   return 0;
 }
 
-// Clean up.
-int GTSim::finalize(){
-  //TODO
-  is_topology_ = 0;
-  delete sim_;
-  delete topo_;
-  return 0;
-}
 
 void static tcp_sent_callback(void* action, double completion_time){
   // Schedule the flow complete event.
index b5a34fd..4194383 100644 (file)
@@ -1,4 +1,8 @@
-//Kayo Fujiwara 1/8/2007
+/*     $Id$     */
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #ifndef _GTNETS_SIM_H
 #define _GTNETS_SIM_H
@@ -22,6 +26,7 @@
 #include "tcp-newreno.h"
 #include "validation.h"
 #include "event.h"
+#include "routing-manual.h"
 
 using namespace std;
 
@@ -33,17 +38,24 @@ public:
   ~GTSim();
 public:   
   int add_link(int id, double bandwidth, double latency);
+  int add_onehop_route(int src, int dst, int link);
   int add_route(int src, int dst, int* links, int nlink);
+  int add_router(int id);
   int create_flow(int src, int dst, long datasize, void* metadata);
   double get_time_to_next_flow_completion();
   int run_until_next_flow_completion(void*** metadata, int* number_of_flows);
   int run(double deltat);
-  int finalize();
 
   void create_gtnets_topology();
 private:
+  void add_nodes();
+  void node_connect();
+
+  bool node_include(int);
+  bool link_include(int);
   Simulator* sim_;
-  SGTopology* topo_;
+  GTNETS_Topology* topo_;
+  RoutingManual* rm_;
   int nnode_;
   int is_topology_;
   int nflow_;
@@ -52,8 +64,7 @@ private:
   map<int, Node*>      gtnets_nodes_;
   map<int, TCPServer*> gtnets_servers_;
   map<int, TCPSend*>   gtnets_clients_;
-  map<int, SGLink*>    tmp_links_;
-  map<int, int>        gtnets_hosts_; //<hostid, nodeid>
+
   map<int, void*>      gtnets_metadata_;
 };
 
index 16f019e..16f9748 100644 (file)
+/* $ID$ */
 
-//SGNode, SGTopology: tmporary classes for GTNetS topology.
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+//GTNETS_Link, GTNETS_Node, GTNETS_Topology: 
+//Temporary classes for generating GTNetS topology
 
 #include "gtnets_topology.h"
 
 // 
-//  SGNode
+//  GTNETS_Node
 // 
-//  TODO when merging a node, remember to add the existing "hosts".
-SGNode::SGNode(int id, int hostid){
-  ID_ = id;
-  if (hostid >= 0)
-    hosts_.push_back(hostid);
-}
 
-SGNode::~SGNode(){
-  //TODO
+// Constructor
+GTNETS_Node::GTNETS_Node(int id):ID_(id),is_router_(false){}
+// Copy constructor
+GTNETS_Node::GTNETS_Node(const GTNETS_Node& node){
+  ID_ = node.ID_;
+  is_router_ = node.is_router_;
+  hosts_ = node.hosts_;
 }
 
-void SGNode::add_link(SGLink* newlink){
-  links_.push_back(newlink);
-}
+GTNETS_Node::~GTNETS_Node(){
 
-
-SGLink* SGNode::other_link(int linkid){
-  for (int i = 0; i < links_.size(); i++){
-    if (links_[i]->id() != linkid)
-      return links_[i];
-  }
-  return NULL;
 }
 
-bool SGNode::has_link(SGLink* link){
-  for (int i = 0; i < links_.size(); i++){
-    //TODO can compare by object itself?
-    if ((links_[i]->id()) == (link->id()))
-      return true;
+// hostid = network_card_id
+int GTNETS_Node::add_host(int hostid){
+  if (is_router_){
+    fprintf(stderr, "Cannot add a host to a router node.\n");
+    return -1;
   }
-  return false;
+  hosts_.insert(hostid);
+  return 0;
 }
 
-void SGNode::print_hosts(){
-  cout << "hosts[";
-  for (int i = 0; i < hosts_.size(); i++){
-    cout << hosts_[i] << ",";
+// Add a router. If this node already has a router/host,
+// return -1.
+int GTNETS_Node::add_router(int routerid){
+  if (hosts_.size() > 1){
+    fprintf(stderr, "Router node should have only one router.\n");
+    return -1;
+  }else if (hosts_.size() == 1){
+    if (hosts_.find(routerid) != hosts_.end()){
+      //printf("the router already exists\n");
+      return 0;
+    }else{
+      fprintf(stderr, "Node %d is a different router.\n");
+      return -1;
+    }
   }
-  cout << "] ";
+  is_router_ = true;
+  hosts_.insert(routerid);
+  return 0;
 }
 
-void SGNode::print_links(){
-  cout << "links[";
-  for (int i = 0; i < links_.size(); i++){
-    cout << links_[i]->id() << ",";
-  }
-  cout << "]" << endl;
+bool GTNETS_Node::is_router(){
+  return is_router_;
 }
 
-vector<SGLink*>& SGNode::links(){
-  return links_;
+bool GTNETS_Node::include(int hostid){
+  if (hosts_.find(hostid) == hosts_.end()) return false;
+  else return true;
 }
-vector<int>& SGNode::hosts(){
-  return hosts_;
+
+void GTNETS_Node::print_hosts(){
+  set<int>::iterator it;
+  printf("[");
+  for (it = hosts_.begin(); it != hosts_.end(); it++){
+    printf(" %d", *it);
+  }
+  printf("]");
 }
 
 //
-//  SGLink
+//  GTNETS_Link
 //
-SGLink::SGLink(int id, SGNode* left, SGNode* right)
-  :ID_(id),
-   left_node_(left),
-   right_node_(right){}
 
+// Constructor
+GTNETS_Link::GTNETS_Link(){
+  ID_=-1;
+  src_node_ = 0;
+  dst_node_ = 0;
+}
+GTNETS_Link::GTNETS_Link(int id):ID_(id), src_node_(0), dst_node_(0){}
 
-SGLink::~SGLink(){
+// Copy constructor
+GTNETS_Link::GTNETS_Link(const GTNETS_Link& link){
+  ID_ = link.ID_;
+  src_node_ = link.src_node_;
+  dst_node_ = link.dst_node_;
+}
 
+GTNETS_Link::~GTNETS_Link(){
+  
 }
 
-// add_left_linK: tow things.
-// add the link to the corresponding node.
-// add the corresponding node to the new link. 
-//  (change from the tmp node to the correct node)
-void SGLink::add_left_link(SGLink* newlink, int side){
-  if (!left_node_){
-    //if alllinks don't have a node, then copy it from
-    //tmporary link.
-    if (side == LEFTSIDE){
-      left_node_ = newlink->left_node_;
-    } else if (side == RIGHTSIDE){
-      left_node_ = newlink->right_node_;
-    } else {
-      cout << "should not come here. side: " << side << endl;
-    }
-  } else {
-    // if already exists, then add the new link to the existing node.
-    left_node_->add_link(newlink);
+void GTNETS_Link::print_link_status(){
+  printf("== LINKID: %d\n", ID_);
+  if (src_node_){
+    printf("  [SRC] ID: %d, router?: %d, hosts[]: ",
+          src_node_->id(), src_node_->is_router());
+    src_node_->print_hosts();
+    printf("\n");
   }
 
-  if (side == LEFTSIDE){
-    newlink->left_node_ = left_node_;
-    //printf("link[%d] new left node: %d\n", link.ID, @left_node.ID)
-  }else if (side == RIGHTSIDE){
-    newlink->right_node_ = left_node_;
-    //printf("link[%d] new left node: %d\n", link.ID, @left_node.ID)
-  }else{
-    cout << "should not come here. side: " << side << endl;
+  if (dst_node_){
+    printf("  [DST] ID: %d, router?: %d, hosts[]: ", 
+          dst_node_->id(), dst_node_->is_router());
+    dst_node_->print_hosts();
+    printf("\n");
   }
+}
 
+GTNETS_Node* GTNETS_Link::src_node(){
+  return src_node_;
 }
 
-void SGLink::add_right_link(SGLink* newlink, int side){
-  if (!right_node_) {
-    //if alllinks doesn't have a node, then copy it from
-    //tmporary link.
-    if (side == LEFTSIDE){
-      right_node_ = newlink->left_node_;
-    }else if (side == RIGHTSIDE){
-      right_node_ = newlink->right_node_;
-    }else{
-      cout << "should not come here. side: " << side << endl;
-    }
-  }else{
-    right_node_->add_link(newlink);
-  }
+GTNETS_Node* GTNETS_Link::dst_node(){
+  return dst_node_;
+}
 
-  if (side == LEFTSIDE){
-    newlink->left_node_ = right_node_;
-    //printf("link[%d] new left node: %d\n", link.ID, @right_node.ID)
-  }else if (side == RIGHTSIDE){
-    newlink->right_node_ = right_node_;
-    //printf("link[%d] new right node: %d\n", link.ID, @right_node.ID)
-  }else{
-    cout << "should not come here. side: " << side << endl;
+bool GTNETS_Link::route_exists(){
+  if (src_node_ && dst_node_) return true;
+  else return false;
+}
+
+// return the peer node id
+int GTNETS_Link::peer_node(int cur_id){
+  if (cur_id ==  src_node_->id()) return dst_node_->id();
+  else if (cur_id == dst_node_->id()) return src_node_->id();
+  else {
+    fprintf(stderr, "node not found\n");
+    return -1;
   }
 }
 
-bool SGLink::is_inleft(SGLink* link){
-  if (!left_node_)
-    return false;
-  else
-    return left_node_->has_link(link);
+int GTNETS_Link::add_src(GTNETS_Node* src){
+  src_node_ = src;
 }
 
-bool SGLink::is_inright(SGLink* link){
-  if (!right_node_)
-    return false;
-  else
-    return right_node_->has_link(link);
+int GTNETS_Link::add_dst(GTNETS_Node* dst){
+  dst_node_ = dst;
 }
 
 
-//return the pointer for the left link.
-SGLink* SGLink::left_link(){
-  if (!left_node_){
-    return NULL;
-  }else{
-    return left_node_->other_link(ID_);
-  }
+//
+//  GTNETS_Topology
+//
+
+// Constructor
+GTNETS_Topology::GTNETS_Topology(){
+  nodeID_ = 0;
 }
 
-SGLink* SGLink::right_link(){
-  if (!right_node_){
-    return NULL;
-  }else{
-    return right_node_->other_link(ID_);
+// Destructor
+GTNETS_Topology::~GTNETS_Topology(){
+  map<int, GTNETS_Link*>::iterator it1;
+  for (it1 = links_.begin(); it1 != links_.end(); it1++){
+    delete it1->second;
+  }
+  vector<GTNETS_Node*>::iterator it2;
+  for (it2 = nodes_.begin(); it2 != nodes_.end(); it2++){
+    delete *it2;
   }
-
 }
 
-SGNode* SGLink::left_node(){
-  return left_node_;
-}
 
+int GTNETS_Topology::link_size(){
+  return links_.size();
+}
 
-SGNode* SGLink::right_node(){
-  return right_node_;
+int GTNETS_Topology::node_size(){
+  return nodes_.size();
 }
 
+int GTNETS_Topology::add_link(int id){
+  map<int,GTNETS_Link*>::iterator iter = links_.find(id);
 
-void SGLink::print(){
-  printf("link[%d]:\n", ID_);
-  if (left_node_){
-    printf("   left  node: %d ", left_node_->id());
-    left_node_->print_hosts();
-    left_node_->print_links();
-  }
-  
-  if (right_node_){
-    printf("   right node: %d ", right_node_->id());
-    right_node_->print_hosts();
-    right_node_->print_links();
+  if(iter == links_.end()) {
+    GTNETS_Link* link= new GTNETS_Link(id);
+    //printf("link %d is added: %d\n", id, link->id());
+    //links_.insert(make_pair(id, link));
+    links_[id] = link;
+    return 0;
+  }else{
+    fprintf(stderr, "Link %d already exists.\n", id);
+    return -1;
   }
 }
 
+int GTNETS_Topology::add_router(int id){
+  set<int>::iterator iter = routers_.find(id);
 
-SGTopology::SGTopology(){
-  nodeID_ = 0;
+  if(iter == routers_.end()) {
+    //printf("router %d is inserted\n", id);
+    routers_.insert(id);
+    return 0;
+  }else{
+    fprintf(stderr, "Router %d already exists.\n", id);
+    return -1;
+  }
 }
 
-SGTopology::~SGTopology(){
+bool GTNETS_Topology::is_router(int id){
+  set<int>::iterator iter = routers_.find(id);
+  if(iter == routers_.end()) return false;
+  else return true;
+}
 
+//return the node id of the peer of cur_id by linkid.
+int GTNETS_Topology::peer_node_id(int linkid, int cur_id){
+  //printf("linkid: %d, cur_id: %d\n", linkid, cur_id);
+  GTNETS_Link* link = links_[linkid];
+  if (!link) {
+    fprintf(stderr, "link %d not found\n", linkid);
+    return -1;
+  }
+  if ((cur_id < 0) || (cur_id > nodes_.size()-1)){
+    fprintf(stderr, "node %d not found\n", cur_id);
+    return -1;
+  }
+  int peer  = link->peer_node(nodes_[cur_id]->id());
+  if (peer < 0){
+    fprintf(stderr, "peer not found\n");
+    return -1;
+  }
+  return peer;
 }
 
+int GTNETS_Topology::add_onehop_route(int src, int dst, int linkid){
+  GTNETS_Link* link;
 
-// TODO: assume that all router-route 1-hop routes are set.
-void SGTopology::add_link(int src, int dst, int* links, int nsize){
-  if (nsize == 1){
-    map<int, SGNode*>::iterator it;
-    it = nodes_.find(src);
-    //if not exists, add one.
-    if (it == nodes_.end()){    
-      nodes_[src] = new SGNode(src, src);
-    }
-    it = nodes_.find(dst);
-    //if not exists, add one.
-    if (it == nodes_.end()){    
-      nodes_[dst] = new SGNode(dst, dst);
-    }
+  map<int, GTNETS_Link*>::iterator iter = links_.find(linkid);
 
-    map<int, SGLink*>::iterator itl;
-    itl = links_.find(links[0]);
-    //if not exists, add one.
-    if (itl == links_.end()){
-      links_[links[0]] = new SGLink(links[0], nodes_[src], nodes_[dst]);
-    }
+  if(iter == links_.end()) {
+    fprintf(stderr, "Link %d not found.\n", linkid);
+    return -1;
+  }else{
+    link = iter->second;
   }
-}
 
+  //  printf("add_onehop_route: src: %d, dst: %d, linkid: %d, %d\n",
+  //    src, dst, linkid, link->id());
 
-//create a temporary link set. (one route)
-// not used now. should clean up...
-void SGTopology::create_tmplink(int src, int dst, int* links, int nsize){
-  map<int, SGLink*> tmplinks;
+  GTNETS_Node *src_node, *dst_node;
+  src_node = link->src_node();
+  dst_node = link->dst_node();
 
-  SGNode* n1;
-  SGNode* n2;
 
-  int cur = -1;
-  int nex;
+  // If not exists a route, add one.
+  if (!link->route_exists()){
+    //check whether there exists a node for the src host/router.
+    int s_node_id = nodeid_from_hostid(src);
+    int node_id;
+
+    if (s_node_id < 0){//not exist, create one.
+      s_node_id = nodeID_;
+      GTNETS_Node* node1 = new GTNETS_Node(s_node_id);
+      nodes_.push_back(node1);
+      hosts_[src] = nodes_[s_node_id]->id();
 
-  for (int i = 0; i < nsize; i++){
-    if (i == 0) {
-      nodeID_++;  //new node
-      n1   = new SGNode(nodeID_, src);
-    }else 
-      n1   = n2; //current
-    
-    cur = links[i];
-    
-    if (i == (nsize-1)){
       nodeID_++;
-      n2  = new SGNode(nodeID_, dst);
-    }else{
-      nex = links[i+1];
-      nodeID_++;  //new node
-      n2  = new SGNode(nodeID_, -1);
     }
 
-    tmplinks[cur] = new SGLink(cur, n1, n2);
-    if (n1) n1->add_link(tmplinks[cur]);
-    if (n2) n2->add_link(tmplinks[cur]);
+    if (is_router(src))
+      nodes_[s_node_id]->add_router(src);
+    else
+      nodes_[s_node_id]->add_host(src);
+
+    link->add_src(nodes_[s_node_id]);
+
+    //check whether there exists a node for the dst host/router.
+    int d_node_id = nodeid_from_hostid(dst);
+    if (d_node_id < 0){//not exist, create one.
+      d_node_id = nodeID_;
+      GTNETS_Node* node2 = new GTNETS_Node(d_node_id);
+      nodes_.push_back(node2);
+      hosts_[dst] = nodes_[d_node_id]->id();
+      nodeID_++;
+    }
+
+    if (is_router(dst))
+      nodes_[d_node_id]->add_router(dst);
+    else
+      nodes_[d_node_id]->add_host(dst);
+
+    link->add_dst(nodes_[d_node_id]);
+
+  // other: has either src or dst (error)
+  }else if (!src_node || !dst_node){
+    fprintf(stderr, "Either src or dst is null\n");
+    return -1;
   }
 
-  for (int i = 0; i < nsize; i++){
-    //tmplinks[links[i]]->print();
-    merge_link(tmplinks[links[i]]);
+  // case 1: link has two routers
+  else if (src_node->is_router() && dst_node->is_router()){
+    int tmpsrc1 = src_node->id();
+    int tmpsrc2 = nodeid_from_hostid(src);
+    int tmpdst1 = dst_node->id();
+    int tmpdst2 = nodeid_from_hostid(dst);
+    if (((tmpsrc1 == tmpsrc2) && (tmpdst1 == tmpdst2)) ||
+       ((tmpsrc1 == tmpdst2) && (tmpdst1 == tmpsrc2))){
+      fprintf(stderr, "Route already exists\n");
+    }else{
+      fprintf(stderr, "Different one hop route defined\n");
+      return -1;
+    }
   }
-  add_tmplink_to_links(tmplinks);
-}
+  // case 2: link has one router and one host
+  else if (src_node->is_router() && !dst_node->is_router()){
+    int newsrc, newdst;
+    if (is_router(src)){
+      newsrc = src;
+      newdst = dst;
+    }else if (is_router(dst)){
+      newsrc = dst;
+      newdst = src;
+    }else{
+      fprintf(stderr, "one of nodes should be a router\n");
+      return -1;
+    }
 
-void SGTopology::merge_link(SGLink* link){
-  map<int, SGLink*>::iterator iter;
-  iter = links_.find(link->id());
-  if (iter == links_.end()){
-    //if the link has not been added to the topology.links_, then
-    //printf("link %d doesn't exist in alllinks. No action.\n", link->id());
-    return;
-  }else{
-    int ncommon = 0;
-    int comleft = -1;  //if tmplink.left == @alllinks.link.left, 0, otherwise, 1.
-    int comright = -1; //if tmplink.right == @alllinks.link.left, 0, otherwise, 1.
-    //since link is from tmplinks, each link has at most two neibours.
-
-    if (link->left_link()){
-      //printf("common neibor: left_first: %d\n", link->left_link()->id());
-      if (links_[link->id()]->is_inleft(link->left_link())){
-       comleft = 0;
-       ncommon += 1;
-      }
-      if (links_[link->id()]->is_inright(link->left_link())){
-       comleft = 1;
-       ncommon += 1;
-      }
+    if (src_node->id() != nodeid_from_hostid(newsrc)){
+      fprintf(stderr, "The router should be identical\n");
+      return -1;
     }
 
-    if (link->right_link()){
-      //printf("common neibor: right_first: %d\n", link->right_link()->id());
-      if (links_[link->id()]->is_inleft(link->right_link())){
-       comright = 0;
-       ncommon += 1;
-      }
-      if (links_[link->id()]->is_inright(link->right_link())){
-       comright = 1;
-       ncommon += 1;
-      }
+    //now, to add dst to dst_node, dst should be a host.
+
+    if (is_router(newdst)){
+      fprintf(stderr, "dst %d is not an endpoint. cannot add it to dst_node\n");
+      return -1;
     }
 
-    //printf("common: %d, comright: %d, comleft: %d\n",ncommon, comright, comleft);
+    if (!dst_node->include(newdst)){
+      dst_node->add_host(newdst);
+      hosts_[newdst] = dst_node->id();
+    }
+  }
+  else if (!src_node->is_router() && dst_node->is_router()){
+    int newsrc, newdst;
+    if (is_router(src)){
+      newsrc = dst;
+      newdst = src;
+    }else if (is_router(dst)){
+      newsrc = src;
+      newdst = dst;
+    }else{
+      fprintf(stderr, "one of nodes should be a router\n");
+      return -1;
+    }
 
-    if (ncommon == 0){
-      //merge link.n1 with @alllink.n1, link.n2 with @alllink.n2
-      if (link->left_link())
-       links_[link->id()]->add_left_link(link->left_link(), RIGHTSIDE);
 
-      if (link->right_link())
-       links_[link->id()]->add_right_link(link->right_link(), LEFTSIDE);
-      
-    }else if (ncommon == 1){
-      printf("ncommon %d\n", links_[link->id()]->id());
-      //left --> right
-      if ((comleft == -1) && (comright == 0)){
-       if (link->left_link())
-         links_[link->id()]->add_right_link(link->left_link(), RIGHTSIDE);
-      }else if ((comleft == -1) && (comright == 1)){
-       //left --> left
-       if (link->left_link())
-         links_[link->id()]->add_left_link(link->left_link(), RIGHTSIDE);
-      }else if ((comright == -1) && (comleft == 0)){
-       //right --> right
-       if (link->right_link())
-         links_[link->id()]->add_right_link(link->right_link(), LEFTSIDE);
-      }else if ((comright == -1) && (comleft == 1)){
-       //right --> left
-       if (link->right_link())
-         links_[link->id()]->add_left_link(link->right_link(), LEFTSIDE);
-      }else{
-       fprintf(stderr, "should not come here\n");
-      }
+    if (dst_node->id() != hosts_[newdst]){
+      fprintf(stderr, "The router should be identical\n");
+      return -1;
+    }
 
-    }else if (ncommon == 2){
-      //no change
+    //now, to add dst to src_node, dst should be a host.
 
-    }else{
-      fprintf(stderr, "error, common links are more than 2. %d\n", ncommon);
+    if (is_router(newsrc)){
+      fprintf(stderr, "dst %d is not an endpoint. cannot add it to src_node\n");
+      return -1;
+    }
+
+    if (!src_node->include(newsrc)){
+      src_node->add_host(newsrc);
+      hosts_[newsrc] = src_node->id();
     }
   }
-}
 
-void SGTopology::add_tmplink_to_links(map<int, SGLink*> tmplink){
-  map<int, SGLink*>::iterator iter;
+  // case 3: link has two hosts
+  else if (!src_node->is_router() && !dst_node->is_router()){
 
-  for (iter = tmplink.begin(); iter != tmplink.end(); iter++){
-    map<int, SGLink*>::iterator alliter = links_.find(iter->first);
-    if (alliter == links_.end()){
-      // cout << "tmplink " << iter->first << " not found in links_, adding."
-      // << endl;
-      links_[iter->first] = iter->second;
+    if (is_router(src) || is_router(dst)){
+      fprintf(stderr, "Cannot add a router to host-host link\n");
+      return -1;
     }
-    //    cout << "tmplink: " << iter->second->id() << endl;
+
+    //if both are hosts, the order doesn't matter.
+    if (src_node->include(src)){
+      if (dst_node->include(dst)){
+       //nothing
+      }else{
+       dst_node->add_host(dst);
+       hosts_[dst] = dst_node->id();
+      }
+    }else if (src_node->include(dst)){
+      if (dst_node->include(src)){
+       //nothing
+      }else{
+       dst_node->add_host(src);
+       hosts_[src] = dst_node->id();
+      }
+    }else if (dst_node->include(src)){
+      if (src_node->include(dst)){
+       //nothing
+      }else{
+       src_node->add_host(dst);
+       hosts_[dst] = src_node->id();
+      }
+    }else if (dst_node->include(dst)){
+      if (src_node->include(src)){
+       //nothing
+      }else{
+       src_node->add_host(src);
+       hosts_[src] = src_node->id();
+      }
+    }else{
+      src_node->add_host(src);
+      dst_node->add_host(dst);
+      hosts_[src] = src_node->id();
+      hosts_[dst] = dst_node->id();
+    }   
+      
+  }
+  else{
+    fprintf(stderr, "Shouldn't be here\n");
+    return -1;
   }
-                                                              
+  return 0;
 }
 
-void SGTopology::print_topology(){
-  map<int, SGLink*>::iterator iter;
-  for (iter = links_.begin(); iter != links_.end(); iter++){
-    iter->second->print();
-  }
+int GTNETS_Topology::nodeid_from_hostid(int hostid){
+  map<int,int>::iterator it = hosts_.find(hostid);
+  if (it == hosts_.end())
+    return -1;
+  else return it->second;
 }
 
-void SGTopology::create_gtnets_topology(){
-  map<int, SGLink*>::iterator it;
+void GTNETS_Topology::print_topology(){
+  map<int, GTNETS_Link*>::iterator it;
   for (it = links_.begin(); it != links_.end(); it++){
-    
+    it->second->print_link_status();
   }
 }
 
-map<int, SGLink*>& SGTopology::get_links(){
+const vector<GTNETS_Node*>& GTNETS_Topology::nodes(){
+  return nodes_;
+}
+
+const map<int, GTNETS_Link*>& GTNETS_Topology::links(){
   return links_;
 }
 
index 6202438..b233d7e 100644 (file)
@@ -1,3 +1,9 @@
+/* $ID$ */
+
+/* Copyright (c) 2007 Kayo Fujiwara. All rights reserved.                  */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
 
 
 #ifndef _GTNETS_TOPOLOGY_H
 
 #include <map>
 #include <vector>
+#include <set>
 #include <iostream>
 
-#define LEFTSIDE 0
-#define RIGHTSIDE 1
-
 using namespace std;
 
-class SGLink;
+class GTNETS_Link;
 
-class SGNode{
+class GTNETS_Node{
 
  public:
-  SGNode(int id, int hostid);
-  ~SGNode();
-
-  void add_link(SGLink*);
+  GTNETS_Node(int);
+  GTNETS_Node(const GTNETS_Node& node);
+  ~GTNETS_Node();
 
-  //get other link than the link with the given id.
-  //Note it's only for the case the node has two links.
-  SGLink* other_link(int);
-
-  bool has_link(SGLink*); //TODO can do const SGLink*?
-  void print_links();
-  void print_hosts();
-  
-  vector<SGLink*>& links();
-  vector<int>& hosts();
+  int add_host(int);
+  int add_router(int);
   int id(){return ID_;};
+  bool is_router();
+  bool include(int);
+  void print_hosts();
 
  private:
   int ID_;
-  bool ishost_;
-  vector<int> hosts_; //simgrid hosts
-  vector<SGLink*> links_;
+  int is_router_;
+  set<int> hosts_; //simgrid hosts
 };
 
-class SGLink{
+class GTNETS_Link{
 
  public:
-  SGLink(int id, SGNode* left, SGNode* right);
-  ~SGLink();
-
-  //for a temporary link set, that is, a link has at most two neibours.
-  SGLink* left_link();
-  SGLink* right_link();
-
-
-  SGNode* left_node();
-  SGNode* right_node();
-
-  bool is_inleft(SGLink*);
-  bool is_inright(SGLink*);
-
-  void add_left_link(SGLink*, int side);
-  void add_right_link(SGLink*, int side);
-
+  GTNETS_Link();
+  GTNETS_Link(int id);
+  GTNETS_Link(const GTNETS_Link&);
+  ~GTNETS_Link();
+
+  GTNETS_Node* src_node();
+  GTNETS_Node* dst_node();
+  int peer_node(int);
   int id(){return ID_;};
-
-  void print();
+  void print_link_status();
+  int add_src(GTNETS_Node*);
+  int add_dst(GTNETS_Node*);
+  bool route_exists();
 
  private:
   int ID_;
-  SGNode* left_node_;
-  SGNode* right_node_;
+  GTNETS_Node* src_node_;
+  GTNETS_Node* dst_node_;
 
 };
 
-
-class SGTopology{
+// To create a topology:
+// 1. add links
+// 2. add routers
+// 3. add onehop links
+class GTNETS_Topology{
  public:
-  SGTopology();
-  ~SGTopology();
-
-  void add_link(int src, int dst, int* links, int nsize);
-
-  void create_tmplink(int src, int dst, int* links, int nsize);
-
-  void merge_link(SGLink*);
-
-  void add_tmplink_to_links(map<int, SGLink*> tmplink); //???
-
+  GTNETS_Topology();
+  ~GTNETS_Topology();
+
+  bool is_router(int id);
+  int peer_node_id(int linkid, int cur_id);
+  int add_link(int id);
+  int add_router(int id);
+  int add_onehop_route(int src, int dst, int link);
+  
+  int nodeid_from_hostid(int);
+  int link_size();
+  int node_size();
   void print_topology();
+  const vector<GTNETS_Node*>& nodes();
+  const map<int, GTNETS_Link*>& links();
   
-  void create_gtnets_topology();
-
-  map<int, SGLink*>& get_links();
-
  private:
+
   int nodeID_;
-  map<int, SGLink*> links_;
-  map<int, SGNode*> nodes_;
+  map<int, GTNETS_Link*> links_;
+  vector<GTNETS_Node*> nodes_;
+
+  map<int, int> hosts_; //hostid->nodeid
+
+  set<int> routers_;
 };
 
 #endif