diff --git a/assign/assign.cc b/assign/assign.cc
index 3110020dccd59aa31b286437cba7151ed8fb1dd2..de6bf189f7fa3802b9d7e5d06e2d4d259d3112d3 100644
--- a/assign/assign.cc
+++ b/assign/assign.cc
@@ -333,7 +333,8 @@ void print_help()
       << endl;
   cout << "  -u          - Print a summary of the solution." << endl;
   cout << "  -c <float>  - Use the 'connected' pnode finding algorithm " <<
-      "<float>% of the time." << endl;
+      "<float>*100% of the time." << endl;
+  cout << "  -n          - Don't anneal - just do the prechecks." << endl;
   exit(EXIT_FATAL);
 }
  
@@ -386,7 +387,7 @@ int type_precheck() {
     }
 
     if (ok) {
-      cout << "Type preecheck passed." << endl;
+      cout << "Type precheck passed." << endl;
       return 1;
     } else {
       cout << "Type precheck failed!" << endl;
@@ -424,12 +425,16 @@ int mapping_precheck() {
 
 	// This constitutes a list of the number of ptypes that matched the
 	// criteria. We use to guess what's wrong with the vnode.
-	int matched_links = 0;
 	int matched_bw = 0;
 	// Keep track of desires had how many 'hits', so that we can tell
 	// if any simply were not matched
 	tb_vnode::desires_count_map matched_desires;
 
+	// Keep track of which link types had how many 'hits', so that we can
+	// tell which type(s) caused this node to fail
+	tb_vnode::link_counts_map matched_link_counts;
+	map<crope,bool> matched_links;
+
 	tb_vclass *vclass = v->vclass;
 	tb_vclass::members_map::iterator mit;
 	if (vclass) {
@@ -452,6 +457,7 @@ int mapping_precheck() {
 		// Grab the first node of the pclass as a representative sample
 		tb_pnode *pnode = *((*it)->members[this_type]->L.begin());
 
+#if 0
 		// Check the number of interfaces - if the pnode is a switch,
 		// for now, we don't check this, since it can end up with more
 		// 'interfaces' due to the fact that it can have interswitch
@@ -462,6 +468,10 @@ int mapping_precheck() {
 		} else {
 		    potential_match = false;
 		}
+#endif
+
+		// Check to see if any of the link that this pnode has are of
+		// the correct type for the virtual node
 
 		// Check bandwidth on emulated links
 		if (pnode->total_bandwidth >= v->total_bandwidth) {
@@ -528,6 +538,26 @@ int mapping_precheck() {
 		    }
 		}
 
+		// Check link types
+		tb_vnode::link_counts_map::iterator vit;
+		for (vit = v->link_counts.begin(); vit != v->link_counts.end();
+		    vit++) {
+		  crope type = vit->first;
+		  int count = vit->second;
+		  if (pnode->link_counts.find(type) !=
+			pnode->link_counts.end()) {
+		    // Found at least one link of this type
+		    matched_links[type] = true;
+		    if (pnode->link_counts[type] >= count) {
+		      // Great, there are enough, too
+		      matched_link_counts[type]++;
+		    } else {
+		      potential_match = false;
+		    }
+		  } else {
+		    potential_match = false;
+		  }
+		}
 
 		if (potential_match) {
 		    vec->push_back(*it);
@@ -553,8 +583,20 @@ int mapping_precheck() {
 	if (vnode_type_table[v->name].first == 0) {
 	    cout << "  *** No possible mapping for " << v->name << endl;
 	    // Make an attempt to figure out why it didn't match
-	    if (!matched_links) {
-		cout << "      Too many links!" << endl;
+	    
+	    // Check all of its link types
+	    tb_vnode::link_counts_map::iterator lit;
+	    for (lit = v->link_counts.begin(); lit != v->link_counts.end();
+		lit++) {
+	      crope type = lit->first;
+	      if (!matched_links[type]) {
+		cout << "      No links of type " << type << " found!" << endl;
+	      } else {
+		if (!matched_link_counts[type]) {
+		  cout << "      Too many links of type " << type << "!"
+		    << endl;
+		}
+	      }
 	    }
 
 	    if (!matched_bw) {
@@ -612,12 +654,13 @@ int main(int argc,char **argv)
   int seed = 0;
   crope viz_prefix;
   bool scoring_selftest = false;
+  bool prechecks_only = false;
   
   // Handle command line
   char ch;
   timelimit = 0.0;
   timetarget = 0.0;
-  while ((ch = getopt(argc,argv,"s:v:l:t:rpPTdH:oguc:")) != -1) {
+  while ((ch = getopt(argc,argv,"s:v:l:t:rpPTdH:oguc:n")) != -1) {
     switch (ch) {
     case 's':
       if (sscanf(optarg,"%d",&seed) != 1) {
@@ -674,6 +717,10 @@ int main(int argc,char **argv)
 	print_help();
       }
       break;
+    case 'n':
+      prechecks_only = true;
+      cout << "Doing only prechecks, exiting early" << endl;
+      break;
     default:
       print_help();
     }
@@ -753,6 +800,11 @@ int main(int argc,char **argv)
       exit(EXIT_UNRETRYABLE);
   }
 
+  // Bomb out early if we're only doing the prechecks
+  if (prechecks_only) {
+      exit(EXIT_SUCCESS);
+  }
+
 #ifdef PER_VNODE_TT
   if (prune_pclasses) {
       prune_unusable_pclasses();
diff --git a/assign/parse_ptop.cc b/assign/parse_ptop.cc
index b1864ed37bff4f4fff39de4457c3054ba6782f16..93ba170ed0d3f265c0ccbc4c223aa722d78e1f8a 100644
--- a/assign/parse_ptop.cc
+++ b/assign/parse_ptop.cc
@@ -178,27 +178,21 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
 	pname2vertex[name] = pv;
       }
     } else if (command.compare("link") == 0) {
-      if (parsed_line.size() < 7) {
+      if (parsed_line.size() < 8) {
 	ptop_error("Bad link line, too few arguments.");
       }
       int num = 1;
 #ifdef PENALIZE_BANDWIDTH
       float penalty;
-      if (parsed_line.size() == 8) {
-	if (sscanf(parsed_line[7].c_str(),"%f",&penalty) != 1) {
-	  ptop_error("Bad number argument: " << parsed_line[7] << ".");
+      if (parsed_line.size() == 9) {
+	if (sscanf(parsed_line[8].c_str(),"%f",&penalty) != 1) {
+	  ptop_error("Bad number argument: " << parsed_line[8] << ".");
 	  penalty=1.0;
 	}
       }
-#else
-      if (parsed_line.size() == 8) {
-	if (sscanf(parsed_line[7].c_str(),"%d",&num) != 1) {
-	  ptop_error("Bad number argument: " << parsed_line[7] << ".");
-	  num=1;
-	}
-      }
 #endif
 
+#if 0
 #ifdef FIX_PLINK_ENDPOINTS
       bool fixends;
 #ifdef FIX_PLINKS_DEFAULT
@@ -206,16 +200,18 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
 #else
       fixends = false;
 #endif
-      if (parsed_line.size() == 9) {
-	  if (parsed_line[8].compare("fixends") == 0) {
+      if (parsed_line.size() == 10) {
+	  if (parsed_line[9].compare("fixends") == 0) {
 	      fixends = true;
 	  }
       }
 #else
-      if (parsed_line.size() > 8) {
+      if (parsed_line.size() > 9) {
 	ptop_error("Bad link line, too many arguments.");
       }
 #endif
+#endif
+
       crope name = parsed_line[1];
       crope src,srcmac;
       split_two(parsed_line[2],':',src,srcmac,"(null)");
@@ -224,6 +220,7 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
       crope bw = parsed_line[4];
       crope delay = parsed_line[5];
       crope loss = parsed_line[6];
+      crope link_type = parsed_line[7];
       int ibw,idelay;
       double gloss;
 
@@ -252,14 +249,17 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
       
       for (int cur = 0;cur<num;++cur) {
 	pedge pe = (add_edge(srcv,dstv,PG)).first;
-	tb_plink *pl = new tb_plink(name,tb_plink::PLINK_NORMAL,srcmac,dstmac);
+	tb_plink *pl = new
+	    tb_plink(name,tb_plink::PLINK_NORMAL,link_type,srcmac,dstmac);
 	put(pedge_pmap,pe,pl);
 	pl->delay_info.bandwidth = ibw;
 	pl->delay_info.delay = idelay;
 	pl->delay_info.loss = gloss;
+#if 0
 #ifdef FIX_PLINK_ENDPOINTS
 	pl->fixends = fixends;
 #endif
+#endif
 #ifdef PENALIZE_BANDWIDTH
 	pl->penalty = penalty;
 #endif
@@ -275,11 +275,19 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
 	    tb_slink *sl = new tb_slink();
 	    put(sedge_pmap,swedge,sl);
 	    sl->mate = pe;
-	    pl->type = tb_plink::PLINK_INTERSWITCH;
+	    pl->is_type = tb_plink::PLINK_INTERSWITCH;
 	  }
 	}
 	srcnode->total_interfaces++;
 	dstnode->total_interfaces++;
+	srcnode->link_counts[link_type]++;
+	dstnode->link_counts[link_type]++;
+	for (int i = 8; i < parsed_line.size(); i++) {
+	  crope link_type = parsed_line[i];
+	  pl->types.insert(link_type);
+	  srcnode->link_counts[link_type]++;
+	  dstnode->link_counts[link_type]++;
+	}
 	if (ISSWITCH(srcnode) &&
 	    ! ISSWITCH(dstnode)) {
 	  dstnode->switches.insert(srcv);
diff --git a/assign/parse_top.cc b/assign/parse_top.cc
index dfa6520f57efcac9c5868e50577c5075b9844ccd..ea41e24583efdd956bf4acf275ffb6460d3e3567 100644
--- a/assign/parse_top.cc
+++ b/assign/parse_top.cc
@@ -158,12 +158,13 @@ int parse_top(tb_vgraph &VG, istream& i)
 	}
       }
     } else if (command.compare("link") == 0) {
-      if (parsed_line.size() < 7) {
+      if (parsed_line.size() < 8) {
 	top_error("Bad link line, too few arguments.");
       } else {
 	crope name = parsed_line[1];
 	crope src = parsed_line[2];
 	crope dst = parsed_line[3];
+	crope link_type = parsed_line[7];
 	crope bw,bwunder,bwover;
 	crope delay,delayunder,delayover;
 	crope loss,lossunder,lossover;
@@ -238,6 +239,7 @@ int parse_top(tb_vgraph &VG, istream& i)
 	tb_vlink *l = new tb_vlink();
 	l->src = node1;
 	l->dst = node2;
+	l->type = link_type;
 	put(vedge_pmap,e,l);
 
 	if ((sscanf(bw.c_str(),"%d",&(l->delay_info.bandwidth)) != 1) ||
@@ -264,7 +266,7 @@ int parse_top(tb_vgraph &VG, istream& i)
 #endif
 	l->emulated = false;
 	
-	for (unsigned int i = 7;i < parsed_line.size();++i) {
+	for (unsigned int i = 8;i < parsed_line.size();++i) {
 	  if (parsed_line[i].compare("nodelay") == 0) {
 	    l->allow_delayed = false;
 	  } else if (parsed_line[i].compare("emulated") == 0) {
@@ -288,6 +290,8 @@ int parse_top(tb_vgraph &VG, istream& i)
 	} else {
 	    vnode1->num_links++;
 	    vnode2->num_links++;
+	    vnode1->link_counts[link_type]++;
+	    vnode2->link_counts[link_type]++;
 	}
 #endif
       }
diff --git a/assign/pclass.cc b/assign/pclass.cc
index 8e9ebf26eaecfff9fd8473767dde0e4899abbcef..7ea07ba45e1aa1d0dedff527a2350cf6a781187c 100644
--- a/assign/pclass.cc
+++ b/assign/pclass.cc
@@ -11,7 +11,7 @@
 #include <hash_map>
 #include <rope>
 #include <queue>
-#include <slist>
+#include <list>
 #include <algorithm>
 
 #include <boost/config.hpp>
@@ -48,26 +48,15 @@ extern pclass_list pclasses;
 // length of the array.
 extern pclass_types type_table;
 
-typedef pair<pvertex,int> link_info; // dst, bw
-
-struct hashlinkinfo {
-  size_t operator()(link_info const &A) const {
-    hashptr<void *> ptrhash;
-    return ptrhash(A.first)/2+A.second;
-  }
-};
-
 // returns 1 if a and b are equivalent.  They are equivalent if the
 // type and features information match and if there is a one-to-one
 // mapping between links that preserves bw, and destination.
 int pclass_equiv(tb_pgraph &PG, tb_pnode *a,tb_pnode *b)
 {
-  typedef hash_multiset<link_info,hashlinkinfo> link_set;
-
   // The unique flag is used to signify that there is some reason that assign
   // is not aware of that the node is unique, and shouldn't be put into a
   // pclass. The usual reason for doing this is for scoring purposes - ie.
-  // don't prefer one just because it's the same pclass as another that, in
+  // don't prefer one just because it's the same pclass over another that, in
   // reality, is very different.
   if (a->unique || b->unique) {
       return 0;
@@ -129,33 +118,51 @@ int pclass_equiv(tb_pgraph &PG, tb_pnode *a,tb_pnode *b)
     }
   }
 
-  // check links - to do this we first create sets of every link in b.
-  // we then loop through every link in a, find a match in the set, and
-  // remove it from the set.
+  // Check links
   pvertex an = pnode2vertex[a];
   pvertex bn = pnode2vertex[b];
 
-  link_set b_links;
+  // Make a list of all links for node b
+  typedef list<pedge> link_list;
+  link_list b_links;
 
   poedge_iterator eit,eendit;
   tie(eit,eendit) = out_edges(bn,PG);
   for (;eit != eendit;++eit) {
     pvertex dst = target(*eit,PG);
-    if (dst == bn)
-      dst = source(*eit,PG);
-    b_links.insert(link_info(dst,get(pedge_pmap,*eit)->delay_info.bandwidth));
+    b_links.push_back(*eit);
   }
+  
+  // Go through all of a's links, trying to find matches on node b. If we find
+  // a match, we remove it from the list
   tie(eit,eendit) = out_edges(an,PG);
   for (;eit != eendit;++eit) {
-    pvertex dst = target(*eit,PG);
-    if (dst == an)
-      dst = source(*eit,PG);
-    int bw = get(pedge_pmap,*eit)->delay_info.bandwidth;
-    link_info tomatch = link_info(dst,bw);
-    link_set::iterator found = b_links.find(tomatch);
-    if (found == b_links.end()) return 0;
-    else b_links.erase(found);
+    tb_plink *plink_a = get(pedge_pmap,*eit);
+    pvertex dest_pv_a = target(*eit,PG);
+    if (dest_pv_a == a)
+      dest_pv_a = source(*eit,PG);
+
+    link_list::iterator bit;
+    for (bit = b_links.begin(); bit != b_links.end(); bit++) {
+      tb_plink *plink_b = get(pedge_pmap,*bit);
+      pvertex dest_pv_b = target(*bit,PG);
+      if (dest_pv_b == b)
+	dest_pv_b = source(*bit,PG);
+
+      // If links are equivalent, remove this link in b from further
+      // consideration, and go to the next link in a
+      if ((dest_pv_a == dest_pv_b) && plink_a->is_equiv(*plink_b)) {
+	b_links.erase(bit);
+	break;
+      }
+    }
+    // If we never found a match, these nodes aren't equivalent
+    if (bit == b_links.end()) {
+      return 0;
+    }
   }
+
+  // Make sure node b has no extra links
   if (b_links.size() != 0) return 0;
   return 1;
 }
diff --git a/assign/physical.h b/assign/physical.h
index e8b8c41f414708b72a0d90d51769087f15fcdee7..81d6e420396f881ff23471527ba006b975350dd2 100644
--- a/assign/physical.h
+++ b/assign/physical.h
@@ -61,6 +61,8 @@ typedef hash_map<svertex,switch_dist_map*>switch_dist_map_map;
 typedef list<pedge> pedge_path;
 typedef list<pvertex> pvertex_list;
 
+typedef hash_map<crope,int> link_type_count_map;
+
 // Globals, declared in assign.cc
 
 extern tb_pgraph_vertex_pmap pvertex_pmap;
@@ -156,6 +158,9 @@ public:
 
   bool is_switch;		// Indicates whether or not this pnode is a
                                 // switch
+				//
+  link_type_count_map link_counts; // Counts how many links of each type this
+  				   // node has 
 	
   bool set_current_type(crope type) {
       if (types.find(type) == types.end()) {
@@ -228,17 +233,22 @@ typedef hash_map<nodepair,int,pairhash<crope> > nodepair_count_map;
 class tb_plink {
 public:
   typedef enum {PLINK_NORMAL,PLINK_INTERSWITCH,PLINK_LAN} plinkType;
+  typedef hash_set<crope> type_set;
 
-  tb_plink(crope _name, plinkType _type, crope _srcmac, crope _dstmac)
-    : name(_name), srcmac(_srcmac), dstmac(_dstmac), type(_type),
+  tb_plink(crope _name, plinkType _is_type, crope _type, crope _srcmac, crope
+      _dstmac)
+    : name(_name), srcmac(_srcmac), dstmac(_dstmac), is_type(_is_type),
       delay_info(), bw_used(0), emulated(0), nonemulated(0),
       penalty(0.0), fixends(false), current_endpoints(), current_count(0),
-      vedge_counts() {;}
+      vedge_counts() {
+	  types.insert(_type);
+      }
 
   crope name;			// the name
   crope srcmac,dstmac;		// source and destination MAC addresses.
 
-  plinkType type;		// type of the link
+  plinkType is_type;		// inter-switch type of the link
+  type_set types;		// type (ie. ethernet) of the link
   tb_delay_info delay_info;	// the delay characteristics of this link
   int bw_used;			// how much is used
 
@@ -258,7 +268,7 @@ public:
   {
     o << "tb_plink: " << link.name << " (" << &link << ")" << endl;
     o << "  type: ";
-    switch (link.type) {
+    switch (link.is_type) {
     case tb_plink::PLINK_NORMAL:
       o << "normal" << endl;
       break;
@@ -276,6 +286,21 @@ public:
     o << link.delay_info;
     return o;
   }
+
+  // Return true if the two plinks are equivalent, in terms of type and
+  // bandwidth.
+  // NOTE: should probably use a helper function in delay_info, but right now,
+  // we only care about bandwidth
+  const bool is_equiv(const tb_plink& link) {
+      if (types == link.types) {
+	  return false;
+      }
+      if (delay_info.bandwidth != link.delay_info.bandwidth) {
+	  return false;
+      }
+
+      return true;
+  }
 };
 
 class tb_slink {
diff --git a/assign/score.cc b/assign/score.cc
index b5352af4c4a5a044c1c398b27ba2f29a2beddfef..3e952adaaedc524371b54b02cbaa385d1bbf7f4f 100644
--- a/assign/score.cc
+++ b/assign/score.cc
@@ -129,7 +129,7 @@ void init_score()
   tie(vedge_it,end_vedge_it) = edges(VG);
   for (;vedge_it!=end_vedge_it;++vedge_it) {
     tb_vlink *vlink=get(vedge_pmap,*vedge_it);
-    vlink->link_info.type=tb_link_info::LINK_UNKNOWN;
+    vlink->link_info.type_used=tb_link_info::LINK_UNMAPPED;
     vlink->no_connection=false;
   }
   pvertex_iterator pvertex_it,end_pvertex_it;
@@ -166,7 +166,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
 
   // Handle vnodes that are not allowed to have a mix of trivial and
   // non-trivial links
-  if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
+  if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
       src_vnode->trivial_links--;
       dst_vnode->trivial_links--;
       if (src_vnode->disallow_trivial_mix &&
@@ -185,7 +185,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
 	  violated--;
 	  vinfo.trivial_mix--;
       }
-  } else if (vlink->link_info.type != tb_link_info::LINK_UNKNOWN) {
+  } else if (vlink->link_info.type_used != tb_link_info::LINK_UNMAPPED) {
       src_vnode->nontrivial_links--;
       dst_vnode->nontrivial_links--;
       if (src_vnode->disallow_trivial_mix &&
@@ -207,7 +207,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
   }
 
   // Unscore the link itself
-  if (vlink->link_info.type == tb_link_info::LINK_DIRECT) {
+  if (vlink->link_info.type_used == tb_link_info::LINK_DIRECT) {
     // DIRECT LINK
     SDEBUG(cerr << "   direct link" << endl);
     src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
@@ -216,7 +216,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
     SSUB(SCORE_DIRECT_LINK);
     unscore_link(vlink->link_info.plinks.front(),ve,src_pnode,dst_pnode);
     vlink->link_info.plinks.clear();
-  } else if (vlink->link_info.type == tb_link_info::LINK_INTERSWITCH) {
+  } else if (vlink->link_info.type_used == tb_link_info::LINK_INTERSWITCH) {
     // INTERSWITCH LINK
     SDEBUG(cerr << "  interswitch link" << endl);
     src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
@@ -253,7 +253,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
       the_switch->nontrivial_bw_used -= vlink->delay_info.bandwidth * 2;
     }
     vlink->link_info.switches.clear();
-  } else if (vlink->link_info.type == tb_link_info::LINK_INTRASWITCH) {
+  } else if (vlink->link_info.type_used == tb_link_info::LINK_INTRASWITCH) {
     // INTRASWITCH LINK
     SDEBUG(cerr << "   intraswitch link" << endl);
     src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
@@ -276,7 +276,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
   }
 
 #ifdef TRIVIAL_LINK_BW
-  else if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
+  else if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
       // Trivial link - we may get to remove violations
       SDEBUG(cerr << "  trivial bandwidth used " <<
 	      src_pnode->trivial_bw_used << " max is " <<
@@ -539,7 +539,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
 {
   tb_vlink *vlink = get(vedge_pmap,ve);
   tb_pnode *the_switch;
-  switch (vlink->link_info.type) {
+  switch (vlink->link_info.type_used) {
   case tb_link_info::LINK_DIRECT:
     SADD(SCORE_DIRECT_LINK);
     src_pnode->nontrivial_bw_used += vlink->delay_info.bandwidth;
@@ -628,7 +628,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
     }
     break;
 #endif
-  case tb_link_info::LINK_UNKNOWN:
+  case tb_link_info::LINK_UNMAPPED:
     cout << "Internal error: Should not be here either." << endl;
     exit(EXIT_FATAL);
     break;
@@ -636,7 +636,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
 
   // Handle vnodes that are not allowed to have a mix of trivial and
   // non-trivial links
-  if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
+  if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
       src_vnode->trivial_links++;
       dst_vnode->trivial_links++;
       if (src_vnode->disallow_trivial_mix &&
@@ -849,7 +849,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 	    seen_loopback_links.insert(vlink);
 	}
 	if (allow_trivial_links && vlink->allow_trivial) {
-	    vlink->link_info.type = tb_link_info::LINK_TRIVIAL;
+	    vlink->link_info.type_used = tb_link_info::LINK_TRIVIAL;
 	    // XXX - okay, this is really bad, but score_link_info doesn't
 	    // usually get called for trivial links, and letting them fall
 	    // through into the 'normal' link code below is disatrous!
@@ -875,7 +875,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 	pedge pe;
 	// Direct link
 	if (find_best_link(dest_pv,pv,vlink,pe)) {
-	  resolutions[resolution_index].type = tb_link_info::LINK_DIRECT;
+	  resolutions[resolution_index].type_used = tb_link_info::LINK_DIRECT;
 	  resolutions[resolution_index].plinks.push_back(pe);
 	  resolution_index++;
 	  total_weight += LINK_RESOLVE_DIRECT;
@@ -924,7 +924,8 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 	      }
 
 
-	    resolutions[resolution_index].type = tb_link_info::LINK_INTRASWITCH;
+	    resolutions[resolution_index].type_used =
+		tb_link_info::LINK_INTRASWITCH;
 	    if (flipped) { // Order these need to go in depends on flipped bit
 	      if (second_link) {
 		resolutions[resolution_index].plinks.push_back(second);
@@ -997,7 +998,8 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 		}
 	      }
 
-	      resolutions[resolution_index].type = tb_link_info::LINK_INTERSWITCH;
+	      resolutions[resolution_index].type_used =
+		  tb_link_info::LINK_INTERSWITCH;
 	      if (flipped) { // Order these need to go in depends on flipped bit
 		if (second_link) {
 		  resolutions[resolution_index].plinks.push_front(second);
@@ -1033,7 +1035,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 	  SADD(SCORE_NO_CONNECTION);
 	  vlink->no_connection=true;
 	  vinfo.no_connection++;
-	  vlink->link_info.type = tb_link_info::LINK_UNKNOWN;
+	  vlink->link_info.type_used = tb_link_info::LINK_UNMAPPED;
 	  violated++;
 	} else {
 	  // Check to see if we are fixing a violation
@@ -1051,14 +1053,14 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
 	    float choice;
 	    choice = std::random()%(int)total_weight;
 	    for (index = 0;index < resolution_index;++index) {
-	      switch (resolutions[index].type) {
+	      switch (resolutions[index].type_used) {
 	      case tb_link_info::LINK_DIRECT:
 		choice -= LINK_RESOLVE_DIRECT; break;
 	      case tb_link_info::LINK_INTRASWITCH:
 		choice -= LINK_RESOLVE_INTRASWITCH; break;
 	      case tb_link_info::LINK_INTERSWITCH:
 		choice -= LINK_RESOLVE_INTERSWITCH; break;
-	      case tb_link_info::LINK_UNKNOWN:
+	      case tb_link_info::LINK_UNMAPPED:
 	      case tb_link_info::LINK_TRIVIAL:
 		cerr << "Internal error: Should not be here." << endl;
 		exit(EXIT_FATAL);
@@ -1194,6 +1196,11 @@ bool find_best_link(pvertex pv,pvertex switch_pv,tb_vlink *vlink,
     if (dest_pv == switch_pv) {
       tb_plink *plink = get(pedge_pmap,*pedge_it);
 
+      // Skip any links whose type is wrong (ie. doesn't match the vlink)
+      if (plink->types.find(vlink->type) == plink->types.end()) {
+	  continue;
+      }
+
       // Get delay characteristics - NOTE: Currently does not actually do
       // anything
       tb_delay_info physical_delay;
@@ -1303,7 +1310,7 @@ void score_link(pedge pe,vedge ve,tb_pnode *src_pnode, tb_pnode *dst_pnode)
   cerr << *vlink;
 #endif
   
-  if (plink->type == tb_plink::PLINK_NORMAL) {
+  if (plink->is_type == tb_plink::PLINK_NORMAL) {
     // need to account for three things here, the possiblity of a new plink
     // the user of a new emulated link, and a possible violation.
     if (vlink->emulated) {
@@ -1367,7 +1374,7 @@ void score_link(pedge pe,vedge ve,tb_pnode *src_pnode, tb_pnode *dst_pnode)
   }
 #endif
 
-  if (plink->type != tb_plink::PLINK_LAN) {
+  if (plink->is_type != tb_plink::PLINK_LAN) {
     tb_delay_info physical_delay;
     physical_delay.bandwidth = plink->delay_info.bandwidth - plink->bw_used;
     physical_delay.delay = plink->delay_info.delay;
@@ -1414,7 +1421,7 @@ void unscore_link(pedge pe,vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode)
   // This is not in the slightest bit graceful! This function was not designed
   // for use with trivial links (which have no plink,) but I would like to call
   // it for symmetry
-  if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
+  if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
     goto UNSCORE_TRIVIAL;
   }
 
@@ -1429,7 +1436,7 @@ void unscore_link(pedge pe,vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode)
   cerr << *vlink;
 #endif
 
-  if (plink->type == tb_plink::PLINK_NORMAL) {
+  if (plink->is_type == tb_plink::PLINK_NORMAL) {
     if (vlink->emulated) {
       plink->emulated--;
       SSUB(SCORE_EMULATED_LINK);
@@ -1508,7 +1515,7 @@ void unscore_link(pedge pe,vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode)
 #endif
   
   // bandwidth check
-  if (plink->type != tb_plink::PLINK_LAN) {
+  if (plink->is_type != tb_plink::PLINK_LAN) {
 #ifdef PENALIZE_BANDWIDTH
     SSUB(plink->penalty * (vlink->delay_info.bandwidth * 1.0) / (plink->delay_info.bandwidth));
 #endif
@@ -1543,7 +1550,7 @@ void unscore_link(pedge pe,vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode)
   }
 
 UNSCORE_TRIVIAL:
-  vlink->link_info.type = tb_link_info::LINK_UNKNOWN;
+  vlink->link_info.type_used = tb_link_info::LINK_UNMAPPED;
 }
 
 double fd_score(tb_vnode *vnode,tb_pnode *pnode,int &fd_violated,
@@ -1792,125 +1799,3 @@ void remove_global_fds(tb_vnode *vnode,tb_pnode *pnode) {
     }
   }
 }
-
-/* make_lan_node(vvertex vv)
- * This routines create a physical lan node and connects it to a switch
- * with a LAN plink.  Most of the code is in determining which switch to
- * connect the LAN node to.  Specifically, it connects it to the switch
- * which will maximize the number of intra (rather than inter) links for
- * assigned adjancent nodes of vv.
- *
- * NOTE: This function is deprecated, since there are no longer special
- * physical LAN nodes.
- *
- */
-pvertex make_lan_node(vvertex vv)
-{
-  typedef hash_map<pvertex,int,hashptr<void *> > switch_int_map;
-  switch_int_map switch_counts;
-
-  tb_vnode *vnode = get(vvertex_pmap,vv);
-
-  SDEBUG(cerr << "make_lan_node(" << vnode->name << ")" << endl);
-  
-  // Choose switch
-  pvertex largest_switch;
-  int largest_switch_count=0;
-  voedge_iterator vedge_it,end_vedge_it;
-  tie(vedge_it,end_vedge_it) = out_edges(vv,VG);
-  for (;vedge_it!=end_vedge_it;++vedge_it) {
-    vvertex dest_vv = target(*vedge_it,VG);
-    if (dest_vv == vv)
-      dest_vv = source(*vedge_it,VG);
-    tb_vnode *dest_vnode = get(vvertex_pmap,dest_vv);
-    if (dest_vnode->assigned) {
-      pvertex dest_pv = dest_vnode->assignment;
-      tb_pnode *dest_pnode = get(pvertex_pmap,dest_pv);
-      for (pvertex_set::iterator switch_it = dest_pnode->switches.begin();
-	   switch_it != dest_pnode->switches.end();switch_it++) {
-	if (switch_counts.find(*switch_it) != switch_counts.end()) {
-	  switch_counts[*switch_it]++;
-	} else {
-	  switch_counts[*switch_it]=1;
-	}
-	if (switch_counts[*switch_it] > largest_switch_count) {
-	  largest_switch = *switch_it;
-	  largest_switch_count = switch_counts[*switch_it];
-	}
-      }
-    }
-  }
-
-  SDEBUG(cerr << "  largest_switch=" << largest_switch <<
-	 " largest_switch_count=" << largest_switch_count << endl);
-  
-  pvertex pv = add_vertex(PG);
-  tb_pnode *p = new tb_pnode(vnode->name);
-  put(pvertex_pmap,pv,p);
-  p->types["lan"] = new tb_pnode::type_record(1,false);
-  p->set_current_type("lan");
-  
-  // If the below is false then we have an orphaned lan node which will
-  // quickly be destroyed when add_node fails.
-  if (largest_switch_count != 0) {
-    pedge pe = (add_edge(pv,largest_switch,PG)).first;
-
-    p->name = "lan-";
-    p->name += get(pvertex_pmap,largest_switch)->name;
-    p->name += "-";
-    p->name += vnode->name;
-
-    // Build a link name that looks like the ones we used to supply in the ptop
-    // file
-    crope link_name = "link-";
-    link_name += p->name;
-    tb_plink *pl = new tb_plink(link_name, tb_plink::PLINK_LAN,
-	    p->name, "(null)");
-
-    p->switches.insert(largest_switch);
-    put(pedge_pmap,pe,pl);
-
-#ifdef FIX_PLINK_ENDPOINTS
-    pl->fixends = false;
-#endif
-  } else {
-    p->name += "orphan";
-  }
-
-  return pv;
-}
-
-/* delete_lan_node(pvertex pv)
- * Removes the physical lan node and the physical lan link.  Assumes that
- * nothing is assigned to it.
- *
- * NOTE: This function is deprecated, since there are no longer special
- * physical LAN nodes.
- *
- */
-void delete_lan_node(pvertex pv)
-{
-  tb_pnode *pnode = get(pvertex_pmap,pv);
-
-  SDEBUG(cerr << "delete_lan_node(" << pnode->name << ")" << endl);
-
-  // delete LAN link
-  typedef list<pedge> pedge_list;
-  pedge_list to_free;
-  
-  poedge_iterator pedge_it,end_pedge_it;
-  tie(pedge_it,end_pedge_it) = out_edges(pv,PG);
-  // We need to copy because removing edges invalidates out iterators.
-  for (;pedge_it != end_pedge_it;++pedge_it) {
-    to_free.push_front(*pedge_it);
-  }
-  for (pedge_list::iterator free_it = to_free.begin();
-       free_it != to_free.end();++free_it) {
-    delete(get(pedge_pmap,*free_it));
-    remove_edge(*free_it,PG);
-  }
-
-  remove_vertex(pv,PG);
-  delete pnode;
-}
-
diff --git a/assign/solution.cc b/assign/solution.cc
index bef8d541668d65b59d789af1108e42c189e3061f..2b776ce06f096680c762fadd6bd8c2f01454fae6 100644
--- a/assign/solution.cc
+++ b/assign/solution.cc
@@ -49,21 +49,23 @@ void print_solution()
 
 	cout << vlink->name;
 
-	if (vlink->link_info.type == tb_link_info::LINK_DIRECT) {
+	if (vlink->link_info.type_used == tb_link_info::LINK_DIRECT) {
 	    // Direct link - just need the source and destination
 	    tb_plink *p = get(pedge_pmap,vlink->link_info.plinks.front());
 	    tb_plink *p2 = get(pedge_pmap,vlink->link_info.plinks.back());
 	    cout << " direct " << p->name << " (" <<
 		p->srcmac << "," << p->dstmac << ") " <<
 		p2->name << " (" << p2->srcmac << "," << p2->dstmac << ")";
-	} else if (vlink->link_info.type == tb_link_info::LINK_INTRASWITCH) {
+	} else if (vlink->link_info.type_used ==
+		tb_link_info::LINK_INTRASWITCH) {
 	    // Intraswitch link - need to grab the plinks to both nodes
 	    tb_plink *p = get(pedge_pmap,vlink->link_info.plinks.front());
 	    tb_plink *p2 = get(pedge_pmap,vlink->link_info.plinks.back());
 	    cout << " intraswitch " << p->name << " (" <<
 		p->srcmac << "," << p->dstmac << ") " <<
 		p2->name << " (" << p2->srcmac << "," << p2->dstmac << ")";
-	} else if (vlink->link_info.type == tb_link_info::LINK_INTERSWITCH) {
+	} else if (vlink->link_info.type_used ==
+		tb_link_info::LINK_INTERSWITCH) {
 	    // Interswitch link - interate through each intermediate link
 	    cout << " interswitch ";
 	    for (pedge_path::iterator it=vlink->link_info.plinks.begin();
@@ -72,7 +74,7 @@ void print_solution()
 		cout << " " << p->name << " (" << p->srcmac << "," <<
 		    p->dstmac << ")";
 	    }
-	} else if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
+	} else if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
 	    // Trivial link - we really don't have useful information to
 	    // print, but we'll fake a bunch of output here just to make it
 	    // consistent with other (ie. intraswitch) output
@@ -211,7 +213,7 @@ void pedge_writer::operator()(ostream &out,const pedge &p) const {
     out << plink->delay_info.bandwidth << "/" <<
 	plink->delay_info.delay << "/" << plink->delay_info.loss << "\"";
 #endif
-    if (plink->type == tb_plink::PLINK_INTERSWITCH) {
+    if (plink->is_type == tb_plink::PLINK_INTERSWITCH) {
 	out << " style=dashed";
     }
     tb_pnode *src = get(pvertex_pmap,source(p,PG));
@@ -259,8 +261,8 @@ void solution_edge_writer::operator()(ostream &out,const vedge &v) const {
     crope style;
     crope color;
     crope label;
-    switch (linfo.type) {
-	case tb_link_info::LINK_UNKNOWN: style="dotted";color="red"; break;
+    switch (linfo.type_used) {
+	case tb_link_info::LINK_UNMAPPED: style="dotted";color="red"; break;
 	case tb_link_info::LINK_DIRECT: style="dashed";color="black"; break;
 	case tb_link_info::LINK_INTRASWITCH:
 	    style="solid";color="black";
diff --git a/assign/test.ptop b/assign/test.ptop
index d3880e4f248c726b0dd4c0d8d61f6460491df090..75ab987a1b47945cae3f09f15fdd4ef8547beb71 100644
--- a/assign/test.ptop
+++ b/assign/test.ptop
@@ -3,9 +3,11 @@ node pa pc:1
 node pb pc:1
 node pc pc:1
 node pd pc:1
-link l1 pa S 100 0 0
-link l2 pa S 100 0 0
-link l3 pb S 100 0 0
-link l4 pb S 100 0 0
-link l5 pc S 100 0 0
-link l6 pc S 100 0 0
+link l1 pa S 100 0 0 ethernet
+link l2 pa S 100 0 0 ethernet 
+link l3 pb S 100 0 0 ethernet
+link l4 pb S 100 0 0 ethernet
+link l5 pc S 100 0 0 ethernet
+link l6 pc S 100 0 0 ethernet
+link l7 pd S 100 0 0 80211
+link l8 pd S 100 0 0 80211
diff --git a/assign/test.top b/assign/test.top
index c3049fd6418615293f41b451ef471ba33cb0970d..148f0860ef2751bfdb75ed009fb3bc100b21dfca 100644
--- a/assign/test.top
+++ b/assign/test.top
@@ -1,6 +1,6 @@
 node A pc
 node B pc
 node C pc
-link vl1 A B 100 0 0
-link vl2 A C 100 0 0
-link vl3 B C 100 0 0
+link vl1 A B 100 0 0 ethernet
+link vl2 A C 100 0 0 ethernet
+link vl3 B C 100 0 0 ethernet
diff --git a/assign/virtual.h b/assign/virtual.h
index 06bae3d0419cfdbe483f82dec6d27e0a530d6aae..94b1d208be359827dc601ef3774cfff0ed5daaaa 100644
--- a/assign/virtual.h
+++ b/assign/virtual.h
@@ -30,20 +30,22 @@ typedef graph_traits<tb_vgraph>::vertex_iterator vvertex_iterator;
 typedef graph_traits<tb_vgraph>::edge_iterator vedge_iterator;
 typedef graph_traits<tb_vgraph>::out_edge_iterator voedge_iterator;
 
+
 class tb_link_info {
 public:
-  typedef enum {LINK_UNKNOWN, LINK_DIRECT,
+  typedef enum {LINK_UNMAPPED, LINK_DIRECT,
 		LINK_INTRASWITCH, LINK_INTERSWITCH,
 		LINK_TRIVIAL, LINK_DELAYED} linkType;
-  linkType type;
+  linkType type_used;		// type of physical link used to satisfy this
+  				// virtual link
   pedge_path plinks;		// the path of pedges
   pvertex_list switches;	// what switches were used
 
   friend ostream &operator<<(ostream &o, const tb_link_info& link)
   {
     o << "  Type: ";
-    switch (link.type) {
-    case LINK_UNKNOWN : o << "LINK_UNKNOWN"; break;
+    switch (link.type_used) {
+    case LINK_UNMAPPED : o << "LINK_UNMAPPED"; break;
     case LINK_DIRECT : o << "LINK_DIRECT"; break;
     case LINK_INTRASWITCH : o << "LINK_INTRASWITCH"; break;
     case LINK_INTERSWITCH : o << "LINK_INTERSWITCH"; break;
@@ -115,6 +117,10 @@ public:
   subnode_list subnodes;
   crope subnode_of_name;
 
+  // Counts how many links of each type this virtual node has
+  typedef hash_map<crope,int> link_counts_map;
+  link_counts_map link_counts;
+
 };
 
 class tb_vlink {
@@ -134,6 +140,7 @@ public:
   tb_delay_info delay_info;	// the delay characteristics of the link
   tb_link_info link_info;	// what it's mapped to
   crope name;			// name
+  crope type;			// type of this link
   bool emulated;		// is this an emulated link, i.e. can it
 				// share a plink withouter emulated vlinks
   bool no_connection;		// true if this link should be satisfied
diff --git a/tbsetup/assign_wrapper.in b/tbsetup/assign_wrapper.in
index df0b248a66b56c93790106aaf3c77c0716f53b8b..f57020d8a9ee773fbd05deda626f9fcfa753c76a 100644
--- a/tbsetup/assign_wrapper.in
+++ b/tbsetup/assign_wrapper.in
@@ -3890,7 +3890,8 @@ sub CreateTopFile()
 		my ($node) = (split(":",$member))[0];
 		my $bandwidth = &getbandwidth($node, $lan, $bw);
 		    
-		print TOPFILE "link $plink $node fakelan/$lan $bandwidth 0 0\n";
+		print TOPFILE "link $plink $node fakelan/$lan $bandwidth " .
+		    "0 0 wireless\n";
 	    }
 	}
 	elsif ($#members == 1) {
@@ -3940,7 +3941,7 @@ sub CreateTopFile()
 		    my $plink = "linksimple/$lan/$nodeport0,$nodeport1";
 		    
 		    print(TOPFILE "link $plink $node0 $node1 ".
-			  max($bw,$rbw) . " 0 0" .
+			  max($bw,$rbw) . " 0 0 ethernet " .
 			  ($emulated ? " emulated" : "") .
 			  ($trivial_ok ? " trivial_ok\n" : "\n"));
 
@@ -3970,10 +3971,10 @@ sub CreateTopFile()
 		    print TOPFILE "node $delayname delay\n";
 		    print TOPFILE
 			"link linksdelaysrc/$lan/$nodeport0,$nodeport1 ".
-			"$node0 $delayname $bandwidth 0 0\n";
+			"$node0 $delayname $bandwidth 0 0 ethernet\n";
 		    print TOPFILE
 			"link linksdelaydst/$lan/$nodeport1,$nodeport0 ".
-			"$node1 $delayname $bandwidth 0 0\n";
+			"$node1 $delayname $bandwidth 0 0 ethernet\n";
 
 		    $delaynodes{$delayname} = $delayname;
 		    
@@ -3994,10 +3995,10 @@ sub CreateTopFile()
 		
 		print TOPFILE "link $plink $node0 $node1";
 		if ($emulated) {
-		    print TOPFILE " " . max($bw,$rbw) . " 0 0 emulated";
+		    print TOPFILE " " . max($bw,$rbw) . " 0 0 ethernet emulated";
 		}
 		else {
-		    print TOPFILE " $bandwidth 0 0";
+		    print TOPFILE " $bandwidth 0 0 ethernet";
 		}
 		if ($trivial_ok) {
 		    print TOPFILE " trivial_ok";
@@ -4061,7 +4062,7 @@ sub CreateTopFile()
 			     $member,$rdelay,$rbw,$rloss,0];
 
 			print(TOPFILE "link $plink $node lan/$lan " .
-			      max($bw,$rbw) . " 0 0" .
+			      max($bw,$rbw) . " 0 0 ethernet" .
 			      ($emulated ? " emulated" : "") .
 			      ($trivial_ok ? " trivial_ok\n" : "\n"));
 
@@ -4078,9 +4079,9 @@ sub CreateTopFile()
 			
 			print TOPFILE "node $delayname delay\n";
 			print TOPFILE "link linkdelaysrc/$lan/$member" .
-			    " $node $delayname $bandwidth 0 0\n";
+			    " $node $delayname $bandwidth 0 0 ethernet\n";
 			print TOPFILE "link linkdelaydst/$lan/$member" .
-			    " lan/$lan $delayname $bandwidth 0 0\n";
+			    " lan/$lan $delayname $bandwidth 0 0 ethernet\n";
 			
 			$delaynodes{$delayname} = $delayname;
 
@@ -4098,7 +4099,8 @@ sub CreateTopFile()
 		else {
 		    my $plink = "linklan/$lan/$member";
 		    
-		    print TOPFILE "link $plink $node lan/$lan $bandwidth 0 0";
+		    print TOPFILE "link $plink $node lan/$lan $bandwidth " .
+			"0 0 ethernet";
 		    if ($emulated) {
 			print TOPFILE " emulated";
 		    }
diff --git a/tbsetup/ptopgen.in b/tbsetup/ptopgen.in
index 0afe8cd212b8ec086eebb019cfd061ed6683c8f3..a1a03a9fb8915aa8fc45a63aef101ea6b827fd44 100644
--- a/tbsetup/ptopgen.in
+++ b/tbsetup/ptopgen.in
@@ -413,6 +413,15 @@ foreach $node (keys(%nodes)) {
 # physnode. 
 #
 if ($widearea) {
+    #
+    # If we are spposed to exempt a certain eid from being considered down,
+    # build up a clause to do that - we consider all nodes already used by that
+    # experiment to be available
+    #
+    my $exempt_condition = "0";
+    if (defined($exempt_eid)) {
+	$free_condition = "(r.pid='$pid' and r.eid='$exempt_eid')"; 
+    }
     $result =
 	DBQueryFatal("select count(a.node_id),a.phys_nodeid,aa.type, ".
 		     "  ns.status,m.pid,m.eid,wn.site ".
@@ -576,7 +585,7 @@ while (($node1,$card1,$port1,$node2,$card2,$port2) =
 	    # !!! - Here we use our knowledge that in the wires table links
 	    # to the switch always come as node2.
 	    print "link link-$node1:$iface1-$node2:$iface2 $node1:$node1/$iface1" .
-		" $node2:$iface2 $bw 0 0 1\n";
+		" $node2:$iface2 $bw 0 0 1 ethernet\n";
 	}
     } 
 }
@@ -632,7 +641,8 @@ if ($TRACK_INTERSWITCH_BANDWIDTH) {
 
 foreach $interconnect (keys(%interconnects)) {
     ($src,$dst) = split(":",$interconnect);
-    print "link link-$interconnect $src $dst $interconnects{$interconnect} 0 0 1\n";
+    print "link link-$interconnect $src $dst $interconnects{$interconnect} " .
+	"0 0 1 ethernet\n";
 }
 
 #
@@ -659,7 +669,7 @@ foreach my $switchtype (("80211a", "80211b", "80211g")) {
 		#print "$node $card $port $type $proto\n";
 		
 		print "link link-$node:$iface-$switchname:(null) ".
-		    "$node:$node/$iface $switchname:(null) $ifacebw 0 0 1\n";
+		    "$node:$node/$iface $switchname:(null) $ifacebw 0 0 1 80211\n";
 	    }
 	}
     }