Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
*** empty log message ***
authorkayof <kayof@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 2 May 2007 21:38:44 +0000 (21:38 +0000)
committerkayof <kayof@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 2 May 2007 21:38:44 +0000 (21:38 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@3473 48e7efb5-ca39-0410-a469-dd3cf9ba447f

configure.ac
src/surf/gtnets/gtnets_interface.cc [new file with mode: 0644]
src/surf/gtnets/gtnets_interface.h [new file with mode: 0644]
src/surf/gtnets/gtnets_simulator.cc [new file with mode: 0644]
src/surf/gtnets/gtnets_simulator.h [new file with mode: 0644]
src/surf/gtnets/gtnets_topology.cc [new file with mode: 0644]
src/surf/gtnets/gtnets_topology.h [new file with mode: 0644]

index 831dc0f..2acc34c 100644 (file)
@@ -189,6 +189,21 @@ else
 fi
 AM_CONDITIONAL(USE_SIMIX,test x$enable_simix != xno)
 
 fi
 AM_CONDITIONAL(USE_SIMIX,test x$enable_simix != xno)
 
+#########################################
+## Build optional modules (gtnets)
+##
+SG_CONFIGURE_PART(Optional modules)
+AC_ARG_ENABLE(gtnets,
+  AS_HELP_STRING([--enable-gtnets], [Use the new GTNetS module (default=no)]),
+  enable_gtnets=$enableval,enable_gtnets=no)
+if test "x$enable_gtnets" = "xyes" ; then
+  AC_MSG_RESULT("***** You have decided to use the experimental GTNetS. We hope you know what you're doing.. ****")
+  AC_DEFINE(USE_GTNETS, 1, [Indicates whether we should use GTNetS or not])
+else 
+  AC_MSG_RESULT(Eventually you will come to GTNetS: x$enable_gtnets)
+fi
+AM_CONDITIONAL(USE_GTNETS,test x$enable_gtnets != xno)
+
 #########################################
 ## Check for libraries extra-dependencies
 ##
 #########################################
 ## Check for libraries extra-dependencies
 ##
diff --git a/src/surf/gtnets/gtnets_interface.cc b/src/surf/gtnets/gtnets_interface.cc
new file mode 100644 (file)
index 0000000..c3626a4
--- /dev/null
@@ -0,0 +1,59 @@
+
+#include "gtnets_simulator.h"
+#include "gtnets_interface.h"
+
+static GTSim* gtnets_sim = 0;
+
+// initialize the GTNetS interface and environment
+int gtnets_initialize(){
+  if (gtnets_sim){
+    fprintf(stderr, "gtnets already initialized.\n");
+    return -1;
+  }
+  gtnets_sim = new GTSim();
+  return 1;
+}
+
+// adds 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){
+  return gtnets_sim->add_link(id, bandwidth, latency);
+}
+
+// adds 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){
+  return gtnets_sim->add_route(src, dst, links, nlink);
+}
+
+// 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){
+  return gtnets_sim->create_flow(src, dst, datasize, metadata);
+}
+
+// get the time (double) until a flow completes (the first such flow)
+// if no flows exist, return -1.0
+double gtnets_get_time_to_next_flow_completion(){
+  return gtnets_sim->get_time_to_next_flow_completion();
+}
+
+// run until a flow completes (returns that flow's metadata)
+int gtnets_run_until_next_flow_completion(void ***metadata, int *number_of_flows){
+  return gtnets_sim->run_until_next_flow_completion(metadata, number_of_flows);
+}
+
+// run for a given time (double)
+int gtnets_run(Time_t deltat){
+  gtnets_sim->run(deltat);
+}
+
+// clean up
+void gtnets_finalize(){
+  if (!gtnets_sim) return;
+  gtnets_sim->finalize();
+  delete gtnets_sim;
+  gtnets_sim = 0;
+}
+
diff --git a/src/surf/gtnets/gtnets_interface.h b/src/surf/gtnets/gtnets_interface.h
new file mode 100644 (file)
index 0000000..261d790
--- /dev/null
@@ -0,0 +1,25 @@
+// Interface for GTNetS.
+// Kayo Fujiwara 1/8/2007
+
+#ifndef _GTNETS_INTERFACE_H
+#define _GTNETS_INTERFACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+  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_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);
+  int gtnets_run(double delta);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/surf/gtnets/gtnets_simulator.cc b/src/surf/gtnets/gtnets_simulator.cc
new file mode 100644 (file)
index 0000000..498bb37
--- /dev/null
@@ -0,0 +1,192 @@
+//Kayo Fujiwara 1/8/2007
+#include "gtnets_simulator.h"
+#include "gtnets_topology.h"
+#include <map>
+
+void static tcp_sent_callback(int id, double completion_time);
+
+// Constructor.
+// TODO: check the default values.
+GTSim::GTSim(){
+  int wsize = 20000;
+  is_topology_ = 0;
+  nflow_ = 0;
+  sim_ = new Simulator();
+  topo_ = new SGTopology();
+
+  // Set default values.
+  TCP::DefaultAdvWin(wsize);
+  TCP::DefaultSegSize(1000);
+  TCP::DefaultTxBuffer(128000);
+  TCP::DefaultRxBuffer(128000);
+
+}
+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;
+  }
+  map<int, Node*>::iterator it3;
+  for (it3 = gtnets_nodes_.begin(); it3 != gtnets_nodes_.end(); it3++){
+    delete it3->second;
+  }
+  map<int, TCPServer*>::iterator it4;
+  for (it4 = gtnets_servers_.begin(); it4 != gtnets_servers_.end(); it4++){
+    delete it4->second;
+  }
+  map<int, TCPSend*>::iterator it5;
+  for (it5 = gtnets_clients_.begin(); it5 != gtnets_clients_.end(); it5++){
+    delete it5->second;
+  }
+  //TODO delete other objects!
+}
+
+
+int GTSim::add_link(int id, double bandwidth, double latency){
+  if (gtnets_links_.find(id) != gtnets_links_.end()){
+    fprintf(stderr, "can't add link %d. already exists.\n", id);
+    return -1;
+  }
+  gtnets_links_[id] = new Linkp2p(bandwidth, 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);
+  return 0;
+}
+
+void GTSim::create_gtnets_topology(){
+  //TODO: add manual routing
+  //TODO: is this addressing fine?
+  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;
+      }
+
+    }
+    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;
+      }
+    }
+
+    gtnets_nodes_[leftid]->
+      AddDuplexLink(gtnets_nodes_[rightid], *gtnets_links_[linkid]);
+
+  }
+}
+
+int GTSim::create_flow(int src, int dst, long datasize, void* metadata){
+  if (is_topology_ == 0){
+    create_gtnets_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()));
+  gtnets_servers_[nflow_]->BindAndListen(80);
+
+  gtnets_clients_[nflow_] = (TCPSend*)gtnets_nodes_[gtnets_hosts_[src]]->
+    AddApplication(TCPSend(nflow_, gtnets_nodes_[gtnets_hosts_[dst]]->GetIPAddr(), 
+                          80, Constant(datasize), TCPReno()));
+  gtnets_clients_[nflow_]->SetSendCallBack(tcp_sent_callback);
+  gtnets_clients_[nflow_]->Start(0);
+  nflow_++;
+
+  return 0;
+}
+
+Time_t GTSim::get_time_to_next_flow_completion(){
+  int status;
+  Time_t t1;
+  int pfds[2];
+  
+  pipe(pfds);
+  
+  t1 = 0;
+  if (fork() != 0){
+    read(pfds[0], &t1, sizeof(Time_t));
+    waitpid(-1, &status, 0);      
+  }else{
+    Time_t t;
+    t = sim_->RunUntilNextCompletion();
+    write(pfds[1], (const void*)&t, sizeof(Time_t));
+    exit(0);
+  }
+  return t1;
+}
+
+int GTSim::run_until_next_flow_completion(void ***metadata, int *number_of_flows){
+  Time_t t1 = sim_->RunUntilNextCompletion();
+  sim_->Run(t1);
+  //TODO set metadata and number of flows.
+  return 0;
+}
+
+int GTSim::run(double delta){
+  sim_->Run(delta);
+  return 0;
+}
+
+// Clean up.
+int GTSim::finalize(){
+  //TODO
+  is_topology_ = 0;
+  delete sim_;
+  delete topo_;
+  return 0;
+}
+
+void static tcp_sent_callback(int id, double completion_time){
+  // Schedule the flow complete event.
+  SimulatorEvent* e =
+    new SimulatorEvent(SimulatorEvent::FLOW_COMPLETE);
+  Simulator::instance->Schedule(e, 0, Simulator::instance);
+
+  //TODO: set metadata
+  printf("In tcp_sent_callback: flow id: %d, time: %f\n", id, completion_time);
+}
+
diff --git a/src/surf/gtnets/gtnets_simulator.h b/src/surf/gtnets/gtnets_simulator.h
new file mode 100644 (file)
index 0000000..b5a34fd
--- /dev/null
@@ -0,0 +1,64 @@
+//Kayo Fujiwara 1/8/2007
+
+#ifndef _GTNETS_SIM_H
+#define _GTNETS_SIM_H
+
+#ifdef __cplusplus
+#include "gtnets_topology.h"
+
+#include <iostream>
+#include <sys/wait.h>
+#include <map>
+
+//GTNetS include files
+#include "simulator.h"      // Definitions for the Simulator Object
+#include "node.h"           // Definitions for the Node Object
+#include "linkp2p.h"        // Definitions for point-to-point link objects
+#include "ratetimeparse.h"  // Definitions for Rate and Time objects
+#include "application-tcpserver.h" // Definitions for TCPServer application
+#include "application-tcpsend.h"   // Definitions for TCP Sending application
+#include "tcp-tahoe.h"      // Definitions for TCP Tahoe
+#include "tcp-reno.h"
+#include "tcp-newreno.h"
+#include "validation.h"
+#include "event.h"
+
+using namespace std;
+
+//Simulator s;
+class GTSim {
+
+public:
+  GTSim();
+  ~GTSim();
+public:   
+  int add_link(int id, double bandwidth, double latency);
+  int add_route(int src, int dst, int* links, int nlink);
+  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:
+  Simulator* sim_;
+  SGTopology* topo_;
+  int nnode_;
+  int is_topology_;
+  int nflow_;
+
+  map<int, Linkp2p*>   gtnets_links_;
+  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_;
+};
+
+#endif /* __cplusplus */
+
+#endif
+
+
diff --git a/src/surf/gtnets/gtnets_topology.cc b/src/surf/gtnets/gtnets_topology.cc
new file mode 100644 (file)
index 0000000..16f019e
--- /dev/null
@@ -0,0 +1,380 @@
+
+//SGNode, SGTopology: tmporary classes for GTNetS topology.
+
+#include "gtnets_topology.h"
+
+// 
+//  SGNode
+// 
+//  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
+}
+
+void SGNode::add_link(SGLink* newlink){
+  links_.push_back(newlink);
+}
+
+
+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;
+  }
+  return false;
+}
+
+void SGNode::print_hosts(){
+  cout << "hosts[";
+  for (int i = 0; i < hosts_.size(); i++){
+    cout << hosts_[i] << ",";
+  }
+  cout << "] ";
+}
+
+void SGNode::print_links(){
+  cout << "links[";
+  for (int i = 0; i < links_.size(); i++){
+    cout << links_[i]->id() << ",";
+  }
+  cout << "]" << endl;
+}
+
+vector<SGLink*>& SGNode::links(){
+  return links_;
+}
+vector<int>& SGNode::hosts(){
+  return hosts_;
+}
+
+//
+//  SGLink
+//
+SGLink::SGLink(int id, SGNode* left, SGNode* right)
+  :ID_(id),
+   left_node_(left),
+   right_node_(right){}
+
+
+SGLink::~SGLink(){
+
+}
+
+// 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);
+  }
+
+  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;
+  }
+
+}
+
+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);
+  }
+
+  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 SGLink::is_inleft(SGLink* link){
+  if (!left_node_)
+    return false;
+  else
+    return left_node_->has_link(link);
+}
+
+bool SGLink::is_inright(SGLink* link){
+  if (!right_node_)
+    return false;
+  else
+    return right_node_->has_link(link);
+}
+
+
+//return the pointer for the left link.
+SGLink* SGLink::left_link(){
+  if (!left_node_){
+    return NULL;
+  }else{
+    return left_node_->other_link(ID_);
+  }
+}
+
+SGLink* SGLink::right_link(){
+  if (!right_node_){
+    return NULL;
+  }else{
+    return right_node_->other_link(ID_);
+  }
+
+}
+
+SGNode* SGLink::left_node(){
+  return left_node_;
+}
+
+
+SGNode* SGLink::right_node(){
+  return right_node_;
+}
+
+
+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();
+  }
+}
+
+
+SGTopology::SGTopology(){
+  nodeID_ = 0;
+}
+
+SGTopology::~SGTopology(){
+
+}
+
+
+// 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, 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]);
+    }
+  }
+}
+
+
+//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;
+
+  SGNode* n1;
+  SGNode* n2;
+
+  int cur = -1;
+  int nex;
+
+  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]);
+  }
+
+  for (int i = 0; i < nsize; i++){
+    //tmplinks[links[i]]->print();
+    merge_link(tmplinks[links[i]]);
+  }
+  add_tmplink_to_links(tmplinks);
+}
+
+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 (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;
+      }
+    }
+
+    //printf("common: %d, comright: %d, comleft: %d\n",ncommon, comright, comleft);
+
+    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");
+      }
+
+    }else if (ncommon == 2){
+      //no change
+
+    }else{
+      fprintf(stderr, "error, common links are more than 2. %d\n", ncommon);
+    }
+  }
+}
+
+void SGTopology::add_tmplink_to_links(map<int, SGLink*> tmplink){
+  map<int, SGLink*>::iterator iter;
+
+  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;
+    }
+    //    cout << "tmplink: " << iter->second->id() << endl;
+  }
+                                                              
+}
+
+void SGTopology::print_topology(){
+  map<int, SGLink*>::iterator iter;
+  for (iter = links_.begin(); iter != links_.end(); iter++){
+    iter->second->print();
+  }
+}
+
+void SGTopology::create_gtnets_topology(){
+  map<int, SGLink*>::iterator it;
+  for (it = links_.begin(); it != links_.end(); it++){
+    
+  }
+}
+
+map<int, SGLink*>& SGTopology::get_links(){
+  return links_;
+}
+
diff --git a/src/surf/gtnets/gtnets_topology.h b/src/surf/gtnets/gtnets_topology.h
new file mode 100644 (file)
index 0000000..6202438
--- /dev/null
@@ -0,0 +1,101 @@
+
+
+#ifndef _GTNETS_TOPOLOGY_H
+#define _GTNETS_TOPOLOGY_H
+
+#include <map>
+#include <vector>
+#include <iostream>
+
+#define LEFTSIDE 0
+#define RIGHTSIDE 1
+
+using namespace std;
+
+class SGLink;
+
+class SGNode{
+
+ public:
+  SGNode(int id, int hostid);
+  ~SGNode();
+
+  void add_link(SGLink*);
+
+  //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 id(){return ID_;};
+
+ private:
+  int ID_;
+  bool ishost_;
+  vector<int> hosts_; //simgrid hosts
+  vector<SGLink*> links_;
+};
+
+class SGLink{
+
+ 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);
+
+  int id(){return ID_;};
+
+  void print();
+
+ private:
+  int ID_;
+  SGNode* left_node_;
+  SGNode* right_node_;
+
+};
+
+
+class SGTopology{
+ 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); //???
+
+  void print_topology();
+  
+  void create_gtnets_topology();
+
+  map<int, SGLink*>& get_links();
+
+ private:
+  int nodeID_;
+  map<int, SGLink*> links_;
+  map<int, SGNode*> nodes_;
+};
+
+#endif