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"; } } }