Commit 34d18441 authored by Tarun Prabhu's avatar Tarun Prabhu

Add extension and vclass support. It should be working correctly now. There's...

Add extension and vclass support. It should be working correctly now. There's a lot of ugliness w.r.t. hardware types and sliver types, while dealing with switches, nodes and vclasses. I have tried to hide most of it in rspec_parser_v2.cc and rspec_parser_helper.cc.
parent 742f3035
...@@ -84,21 +84,20 @@ struct property emulab_extensions_parser::readProperty (const DOMElement* tag) ...@@ -84,21 +84,20 @@ struct property emulab_extensions_parser::readProperty (const DOMElement* tag)
struct hardness emulab_extensions_parser::readHardness (const DOMElement* tag) struct hardness emulab_extensions_parser::readHardness (const DOMElement* tag)
{ {
struct hardness hardnessObject; struct hardness hardnessObject;
if (this->hasChild(tag, "hard")) { string strWeight = this->getAttribute(tag, "weight");
// XXX: This is a temporary fix. We will need to deal with hard
// vclasses correctly at some point if (strWeight == "hard") {
hardnessObject.type = HARD_VCLASS; hardnessObject.type = HARD_VCLASS;
} }
else /* (this->hasChildTag(tag, "soft")) */ { else {
hardnessObject.weight
= rspec_parser_helper::stringToNum (this->readChild(tag, "weight"));
hardnessObject.type = SOFT_VCLASS; hardnessObject.type = SOFT_VCLASS;
hardnessObject.weight = rspec_parser_helper::stringToNum(strWeight);
} }
return hardnessObject; return hardnessObject;
} }
vector<struct vclass> vector<struct vclass>
emulab_extensions_parser::readAllVClasses (const DOMElement* elem) emulab_extensions_parser::readVClasses (const DOMElement* elem)
{ {
DOMNodeList* vclassNodes DOMNodeList* vclassNodes
= elem->getElementsByTagName(XStr("emulab:vclass").x()); = elem->getElementsByTagName(XStr("emulab:vclass").x());
...@@ -113,10 +112,31 @@ emulab_extensions_parser::readAllVClasses (const DOMElement* elem) ...@@ -113,10 +112,31 @@ emulab_extensions_parser::readAllVClasses (const DOMElement* elem)
struct vclass emulab_extensions_parser::readVClass (const DOMElement* tag) struct vclass emulab_extensions_parser::readVClass (const DOMElement* tag)
{ {
vector<string> physTypes;
DOMNodeList* physNodes
= tag->getElementsByTagName(XStr("emulab:physical_type").x());
for (int i = 0; i < physNodes->getLength(); i++) {
DOMElement* physNode = dynamic_cast<DOMElement*>(physNodes->item(i));
// XXX: This is nasty because the type name that we give assign
// has to be the concatation of the hardware type and sliver type
// It's not clear which is the best place to do this
// i.e. whether to generate this concatenated type here in the parser
// (in which case any time the formula to convert the single type to
// a hardware type and sliver type changes, it will have to be updated
// both here and in libvtop) or to do it just once in libvtop in which
// case the reverse holds true i.e. when we change the way we concatenate
// the types and present it to assign, we will have to change the code
// in libvtop
string physNodeName = this->getAttribute(physNode, "name");
cerr << "Converted vclass name to "
<< rspec_parser_helper::convertType(physNodeName) << endl;
physTypes.push_back(rspec_parser_helper::convertType(physNodeName));
}
struct vclass vclassObject = { struct vclass vclassObject = {
this->getAttribute(tag, "name"), rspec_parser_helper::convertType(this->getAttribute(tag, "name")),
this->readHardness(tag), this->readHardness(tag),
this->readChild(tag, "physical_type") physTypes
}; };
return vclassObject; return vclassObject;
} }
...@@ -163,4 +183,72 @@ emulab_extensions_parser::readTypeLimits (const DOMElement* tag, int& count) ...@@ -163,4 +183,72 @@ emulab_extensions_parser::readTypeLimits (const DOMElement* tag, int& count)
return rv; return rv;
} }
string emulab_extensions_parser::readSubnodeOf (const DOMElement* tag,
bool& isSubnode)
{
string rv = "";
DOMNodeList* subnodes
= tag->getElementsByTagName(XStr("emulab:subnode_of").x());
isSubnode = (subnodes->getLength() > 0);
if (isSubnode) {
DOMElement* subnode = dynamic_cast<DOMElement*>(subnodes->item(0));
rv = this->getAttribute(subnode, "parent");
}
return rv;
}
bool emulab_extensions_parser::readDisallowTrivialMix (const DOMElement* tag)
{
DOMNodeList* trivialMix
= tag->getElementsByTagName(XStr("emulab:disallow_trivial_mix").x());
return (trivialMix->getLength() > 0);
}
bool emulab_extensions_parser::readUnique (const DOMElement* tag)
{
DOMNodeList* uniques = tag->getElementsByTagName(XStr("emulab:unique").x());
return (uniques->getLength() > 0);
}
int emulab_extensions_parser::readTrivialBandwidth(const DOMElement* tag,
bool& hasTrivialBw)
{
int trivialBw = 0;
DOMNodeList* bws
= tag->getElementsByTagName(XStr("emulab:trivial_bandwidth").x());
hasTrivialBw = (bws->getLength() > 0);
if (hasTrivialBw) {
trivialBw =(int)this->stringToNum(this->getAttribute
(dynamic_cast<DOMElement*>(bws->item(0)),
"value"));
}
return trivialBw;
}
string emulab_extensions_parser::readHintTo (const DOMElement* tag,
bool& hasHint)
{
string hint = "";
DOMNodeList* hints = tag->getElementsByTagName(XStr("emulab:hint_to").x());
hasHint = (hints->getLength() > 0);
if (hasHint) {
hint = this->getAttribute(dynamic_cast<DOMElement*>(hints->item(0)),
"value");
}
return hint;
}
bool emulab_extensions_parser::readNoDelay (const DOMElement* tag)
{
DOMNodeList* nodelays= tag->getElementsByTagName(XStr("emulab:nodelay").x());
return (nodelays->getLength() > 0);
}
bool emulab_extensions_parser::readTrivialOk (const DOMElement* tag)
{
DOMNodeList* trivial_oks
= tag->getElementsByTagName(XStr("emulab:trivial_ok").x());
return (trivial_oks->getLength() > 0);
}
#endif // WITH_XML #endif // WITH_XML
...@@ -61,7 +61,7 @@ namespace rspec_emulab_extension { ...@@ -61,7 +61,7 @@ namespace rspec_emulab_extension {
struct vclass { struct vclass {
std::string name; std::string name;
struct hardness type; struct hardness type;
std::string physicalType; std::vector<std::string> physicalTypes;
}; };
struct property { struct property {
...@@ -96,14 +96,21 @@ namespace rspec_emulab_extension { ...@@ -96,14 +96,21 @@ namespace rspec_emulab_extension {
std::vector<struct property> readProperties std::vector<struct property> readProperties
(const xercesc::DOMElement* elem); (const xercesc::DOMElement* elem);
struct property readProperty (const xercesc::DOMElement* tag); struct property readProperty (const xercesc::DOMElement* tag);
std::vector<struct vclass> readAllVClasses (const xercesc::DOMElement*); std::vector<struct vclass> readVClasses (const xercesc::DOMElement*);
struct vclass readVClass (const xercesc::DOMElement* tag); struct vclass readVClass (const xercesc::DOMElement* tag);
std::string readAssignedTo (const xercesc::DOMElement* tag); std::string readAssignedTo (const xercesc::DOMElement* tag);
std::string readHintTo (const xercesc::DOMElement* tag); std::string readHintTo (const xercesc::DOMElement* tag);
std::string readTypeSlots (const xercesc::DOMElement* tag); std::string readTypeSlots (const xercesc::DOMElement* tag);
bool readStaticType (const xercesc::DOMElement* tag); bool readStaticType (const xercesc::DOMElement* tag);
std::vector<struct type_limit> readTypeLimits(const xercesc::DOMElement* tag, std::vector<struct type_limit> readTypeLimits(const xercesc::DOMElement*,
int& count); int& count);
std::string readSubnodeOf (const xercesc::DOMElement* tag, bool&);
virtual bool readDisallowTrivialMix (const xercesc::DOMElement* tag);
virtual bool readUnique (const xercesc::DOMElement* tag);
virtual int readTrivialBandwidth (const xercesc::DOMElement* tag, bool&);
virtual std::string readHintTo (const xercesc::DOMElement* tag, bool&);
virtual bool readNoDelay (const xercesc::DOMElement* tag);
virtual bool readTrivialOk (const xercesc::DOMElement* tag);
}; };
} // namespace rspec_emulab_extension } // namespace rspec_emulab_extension
......
...@@ -139,7 +139,7 @@ int parse_advertisement(tb_pgraph &pg, tb_sgraph &sg, char *filename) { ...@@ -139,7 +139,7 @@ int parse_advertisement(tb_pgraph &pg, tb_sgraph &sg, char *filename) {
rspecParser = new rspec_parser_v2(RSPEC_TYPE_ADVT); rspecParser = new rspec_parser_v2(RSPEC_TYPE_ADVT);
break; break;
default: default:
cerr << "ERROR: Unsupported rspec ver. " << rspecVersion cerr << "*** Unsupported rspec ver. " << rspecVersion
<< " ... Aborting " << endl; << " ... Aborting " << endl;
exit(EXIT_FATAL); exit(EXIT_FATAL);
} }
...@@ -162,21 +162,21 @@ int parse_advertisement(tb_pgraph &pg, tb_sgraph &sg, char *filename) { ...@@ -162,21 +162,21 @@ int parse_advertisement(tb_pgraph &pg, tb_sgraph &sg, char *filename) {
*/ */
XMLDEBUG("starting node population" << endl); XMLDEBUG("starting node population" << endl);
if (!populate_nodes(advt_root,pg,sg,unavailable)) { if (!populate_nodes(advt_root,pg,sg,unavailable)) {
cerr << "Error reading nodes from physical topology " cerr << "*** Error reading nodes from physical topology "
<< filename << endl; << filename << endl;
exit(EXIT_FATAL); exit(EXIT_FATAL);
} }
XMLDEBUG("finishing node population" << endl); XMLDEBUG("finishing node population" << endl);
XMLDEBUG("starting link population" << endl); XMLDEBUG("starting link population" << endl);
if (!populate_links(advt_root,pg,sg,unavailable)) { if (!populate_links(advt_root,pg,sg,unavailable)) {
cerr << "Error reading links from physical topology " cerr << "*** Error reading links from physical topology "
<< filename << endl; << filename << endl;
exit(EXIT_FATAL); exit(EXIT_FATAL);
} }
XMLDEBUG("finishing link population" << endl); XMLDEBUG("finishing link population" << endl);
XMLDEBUG("setting type limits" << endl); XMLDEBUG("setting type limits" << endl);
if (!populate_type_limits(advt_root, pg, sg)) { if (!populate_type_limits(advt_root, pg, sg)) {
cerr << "Error setting type limits " << filename << endl; cerr << "*** Error setting type limits " << filename << endl;
exit(EXIT_FATAL); exit(EXIT_FATAL);
} }
XMLDEBUG("finishing setting type limits" << endl); XMLDEBUG("finishing setting type limits" << endl);
...@@ -219,7 +219,7 @@ bool populate_nodes(DOMElement *root, ...@@ -219,7 +219,7 @@ bool populate_nodes(DOMElement *root,
bool hasCMId; bool hasCMId;
string componentId = rspecParser->readPhysicalId(elt, hasComponentId); string componentId = rspecParser->readPhysicalId(elt, hasComponentId);
string componentManagerId = rspecParser->readComponentManagerId(elt,hasCMId); string componentManagerId = rspecParser->readComponentManagerId(elt,hasCMId);
if (!hasComponentId || !hasCMId) { if (!hasComponentId || !hasCMId) {
is_ok = false; is_ok = false;
continue; continue;
...@@ -228,28 +228,29 @@ bool populate_nodes(DOMElement *root, ...@@ -228,28 +228,29 @@ bool populate_nodes(DOMElement *root,
// Maintain a list of componentId's seen so far to ensure no duplicates // Maintain a list of componentId's seen so far to ensure no duplicates
insert_ret = advertisement_elements->insert insert_ret = advertisement_elements->insert
(pair<string, DOMElement*>(componentId, elt)); (pair<string, DOMElement*>(componentId, elt));
if (insert_ret.second == false) if (insert_ret.second == false) {
{ cerr << "*** " << componentId << " already exists" << endl;
cerr << componentId << " already exists" << endl; is_ok = false;
is_ok = false; }
}
// XXX: This should not have to be called manually // XXX: This should not have to be called manually
bool allUnique; bool allUnique;
rspecParser->readInterfacesOnNode(elt, allUnique); rspecParser->readInterfacesOnNode(elt, allUnique);
// XXX: We don't ever do anything with this, so I am commenting it out
/* Deal with the location tag */ // /* Deal with the location tag */
int locationDataCount; // int locationDataCount;
vector<string> locationData // vector<string> locationData
= rspecParser->readLocation(elt, locationDataCount); // = rspecParser->readLocation(elt, locationDataCount);
string country = locationData[0]; // string country = locationData[0];
string latitude = ""; // string latitude = "";
string longitude = ""; // string longitude = "";
if (locationDataCount == 3) { // if (locationDataCount == 3) {
latitude = locationData[1]; // latitude = locationData[1];
longitude = locationData[2]; // longitude = locationData[2];
} // }
pvertex pv; pvertex pv;
...@@ -268,13 +269,14 @@ bool populate_nodes(DOMElement *root, ...@@ -268,13 +269,14 @@ bool populate_nodes(DOMElement *root,
pname2vertex[componentId.c_str()] = pv; pname2vertex[componentId.c_str()] = pv;
int typeCount; int typeCount;
vector<struct node_type> types = rspecParser->readNodeTypes(elt, typeCount); vector<struct node_type>types = rspecParser->readNodeTypes(elt, typeCount);
bool switchAdded = false;
for (int i = 0; i < typeCount; i++) { for (int i = 0; i < typeCount; i++) {
node_type type = types[i]; node_type type = types[i];
const char* typeName = type.typeName.c_str(); const char* typeName = type.typeName.c_str();
int typeSlots = type.typeSlots; int typeSlots = type.typeSlots;
bool isStatic = type.isStatic; bool isStatic = type.isStatic;
// Add the type into assign's data structures // Add the type into assign's data structures
if (ptypes.find(typeName) == ptypes.end()) { if (ptypes.find(typeName) == ptypes.end()) {
ptypes[typeName] = new tb_ptype(typeName); ptypes[typeName] = new tb_ptype(typeName);
...@@ -290,6 +292,7 @@ bool populate_nodes(DOMElement *root, ...@@ -290,6 +292,7 @@ bool populate_nodes(DOMElement *root,
* else! * else!
*/ */
if (strcmp(typeName, "switch") == 0) { if (strcmp(typeName, "switch") == 0) {
// if (rspecParser->checkIsSwitch(componentId) && !switchAdded) {
p->is_switch = true; p->is_switch = true;
p->types["switch"] = new tb_pnode::type_record(1,false,ptype); p->types["switch"] = new tb_pnode::type_record(1,false,ptype);
svertex sv = add_vertex(sg); svertex sv = add_vertex(sg);
...@@ -324,13 +327,26 @@ bool populate_nodes(DOMElement *root, ...@@ -324,13 +327,26 @@ bool populate_nodes(DOMElement *root,
(tb_node_featuredesire(XStr(componentManagerId.c_str()).f(), (tb_node_featuredesire(XStr(componentManagerId.c_str()).f(),
1.0, false, featuredesire::FD_TYPE_NORMAL)); 1.0, false, featuredesire::FD_TYPE_NORMAL));
bool isSubnode; // This has to be at the end becuase if we don't populate
string subnodeOf = rspecParser->readSubnodeOf (elt, isSubnode); // at least the interfaces, we get all kinds of crappy errors
bool isAvailable;
string available = rspecParser->readAvailable(elt, isAvailable);
if (available == "false") {
unavailable.insert(componentId);
continue;
}
++availableCount;
bool isSubnode = false;
int subnodeCnt;
string subnodeOf = rspecParser->readSubnodeOf (elt, isSubnode, subnodeCnt);
if (isSubnode) { if (isSubnode) {
if (!p->subnode_of_name.empty()){ if (subnodeCnt > 1) {
cerr << "*** Too many \"subnode\" relations found in "
<< componentId << "Allowed 1 ... " << endl;
is_ok = false; is_ok = false;
continue; continue;
} }
else { else {
// Just store the name for now, we'll do late binding to // Just store the name for now, we'll do late binding to
// an actual pnode later // an actual pnode later
...@@ -338,16 +354,6 @@ bool populate_nodes(DOMElement *root, ...@@ -338,16 +354,6 @@ bool populate_nodes(DOMElement *root,
} }
} }
// This has to be at the end becuase if we don't populate
// at least the interfaces, we get all kinds of crappy errors
bool isAvailable;
string available = rspecParser->readAvailable(elt, isAvailable);
if (available == "false") {
unavailable.insert(componentId);
continue;
}
++availableCount;
// Deal with features // Deal with features
int fdsCount; int fdsCount;
vector<struct fd> fds = rspecParser->readFeaturesDesires(elt, fdsCount); vector<struct fd> fds = rspecParser->readFeaturesDesires(elt, fdsCount);
...@@ -377,6 +383,17 @@ bool populate_nodes(DOMElement *root, ...@@ -377,6 +383,17 @@ bool populate_nodes(DOMElement *root,
(p->features).push_front(node_fd); (p->features).push_front(node_fd);
} }
// Read extensions for emulab-specific flags
bool hasTrivialBw;
int trivialBw = rspecParser->readTrivialBandwidth(elt, hasTrivialBw);
if (hasTrivialBw) {
p->trivial_bw = trivialBw;
}
if (rspecParser->readUnique(elt)) {
p->unique = true;
}
/* /*
* XXX: Is this really necessary? * XXX: Is this really necessary?
*/ */
...@@ -423,8 +440,7 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg, ...@@ -423,8 +440,7 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg,
string cmId = rspecParser->readComponentManagerId(elt, hasCMId); string cmId = rspecParser->readComponentManagerId(elt, hasCMId);
if (!hasComponentId || !hasCMId) { if (!hasComponentId || !hasCMId) {
cerr << "All elements must have a component_uuid/component_urn " cerr << "*** Require component ID and component manager ID" << endl;
<< "and a component_manager_uuid/component_manager_urn" << endl;
is_ok = false; is_ok = false;
} }
else { else {
...@@ -432,11 +448,11 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg, ...@@ -432,11 +448,11 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg,
advertisement_elements->insert(pair<string, DOMElement*> advertisement_elements->insert(pair<string, DOMElement*>
(componentId, elt)); (componentId, elt));
if (insert_ret.second == false) { if (insert_ret.second == false) {
cerr << componentId << " already exists" << endl; cerr << "*** " << componentId << " already exists" << endl;
is_ok = false; is_ok = false;
} }
} }
/* /*
* Get source and destination interfaces - we use knowledge of the * Get source and destination interfaces - we use knowledge of the
* schema that there is awlays exactly one source and one destination * schema that there is awlays exactly one source and one destination
...@@ -447,26 +463,27 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg, ...@@ -447,26 +463,27 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg,
// Error handling // Error handling
switch (ifaceCount) { switch (ifaceCount) {
case RSPEC_ERROR_BAD_IFACE_COUNT:
cerr << "Incorrect number of interfaces found on link "
<< componentId << ". Expected 2 (found "
<< ifaceCount << ")" << endl;
is_ok = false;
continue;
case RSPEC_ERROR_UNSEEN_NODEIFACE_SRC: case RSPEC_ERROR_UNSEEN_NODEIFACE_SRC:
cerr << "Unseen node-interface pair on the source interface ref" cerr << "*** Unseen node-interface pair on the source interface ref"
<< endl; << endl;
is_ok = false; is_ok = false;
continue; continue;
case RSPEC_ERROR_UNSEEN_NODEIFACE_DST: case RSPEC_ERROR_UNSEEN_NODEIFACE_DST:
cerr << "Unseen node-interface pair on the destination interface ref" cerr << "*** Unseen node-interface pair on the destination interface ref"
<< endl; << endl;
is_ok = false; is_ok = false;
continue; continue;
} }
if (ifaceCount != 2) {
cerr << "*** Incorrect number of interfaces found on link "
<< componentId << ". Expected 2 (found "
<< ifaceCount << ")" << endl;
is_ok = false;
continue;
}
/* NOTE: In a request, we assume that each link has only two interfaces /* NOTE: In a request, we assume that each link has only two interfaces
* Although the order is immaterial, assign expects a source first * Although the order is immaterial, assign expects a source first
* and a destination second and we assume the same * and a destination second and we assume the same
...@@ -477,26 +494,26 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg, ...@@ -477,26 +494,26 @@ bool populate_links(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg,
string dst_iface = interfaces[1].physicalIfaceId; string dst_iface = interfaces[1].physicalIfaceId;
if (src_node == "" || src_iface == "") { if (src_node == "" || src_iface == "") {
cerr << "Physical link " << componentId cerr << "*** Physical link " << componentId
<< " must have a component id and component interface id " << " must have a component id and component interface id "
<< " specified for the source node" << endl; << " specified for the source node" << endl;
is_ok = false; is_ok = false;
continue; continue;
} }
if (dst_node == "" || dst_iface == "") { if (dst_node == "" || dst_iface == "") {
cerr << "Physical link " << componentId cerr << "*** Physical link " << componentId
<< " must have a component id and component interface id" << " must have a component id and component interface id"
<< " specified for the destination node" << endl; << " specified for the destination node" << endl;
is_ok = false; is_ok = false;
continue; continue;
} }
if( unavailable.count( src_node ) || if( unavailable.count( src_node ) ||
unavailable.count( dst_node ) ) unavailable.count( dst_node ) )
//one or both of the endpoints are unavailable; silently //one or both of the endpoints are unavailable; silently
//ignore the link //ignore the link
continue; continue;
/* /*
* Get standard link characteristics * Get standard link characteristics
*/ */
......
This diff is collapsed.
...@@ -99,25 +99,31 @@ vector<struct node_type> rspec_parser::readNodeTypes (const DOMElement* node, ...@@ -99,25 +99,31 @@ vector<struct node_type> rspec_parser::readNodeTypes (const DOMElement* node,
int& typeCount, int& typeCount,
int unlimitedSlots) int unlimitedSlots)
{ {
bool isSwitch = false;
DOMNodeList* nodeTypes = node->getElementsByTagName(XStr("node_type").x()); DOMNodeList* nodeTypes = node->getElementsByTagName(XStr("node_type").x());
vector<struct node_type> types; vector<struct node_type> types;
for (int i = 0; i < nodeTypes->getLength(); i++) for (int i = 0; i < nodeTypes->getLength(); i++) {
{ DOMElement *tag = dynamic_cast<DOMElement*>(nodeTypes->item(i));
DOMElement *tag = dynamic_cast<DOMElement*>(nodeTypes->item(i));
string typeName = XStr(tag->getAttribute(XStr("type_name").x())).c();
string typeName = XStr(tag->getAttribute(XStr("type_name").x())).c(); if (typeName == "switch") {
isSwitch = true;
int typeSlots;
string slot = XStr(tag->getAttribute(XStr("type_slots").x())).c();
if (slot == "unlimited")
typeSlots = unlimitedSlots;
else
typeSlots = (int)stringToNum(slot);
bool isStatic = tag->hasAttribute(XStr("static").x());
struct node_type type = {typeName, typeSlots, isStatic};
types.push_back(type);
} }
int typeSlots;
string slot = XStr(tag->getAttribute(XStr("type_slots").x())).c();
if (slot == "unlimited")
typeSlots = unlimitedSlots;
else
typeSlots = (int)stringToNum(slot);
bool isStatic = tag->hasAttribute(XStr("static").x());
struct node_type type = {typeName, typeSlots, isStatic};
types.push_back(type);
}
if (isSwitch) {
this->addSwitch(node);
}
typeCount = nodeTypes->getLength(); typeCount = nodeTypes->getLength();
return types; return types;
} }
...@@ -161,6 +167,7 @@ rspec_parser::readInterfacesOnNode (const DOMElement* node, ...@@ -161,6 +167,7 @@ rspec_parser::readInterfacesOnNode (const DOMElement* node,
} }
// Returns a link_characteristics element // Returns a link_characteristics element
// count should be 1 on success.
struct link_characteristics struct link_characteristics
rspec_parser :: readLinkCharacteristics (const DOMElement* link, rspec_parser :: readLinkCharacteristics (const DOMElement* link,
int& count, int& count,
...@@ -184,6 +191,7 @@ rspec_parser :: readLinkCharacteristics (const DOMElement* link, ...@@ -184,6 +191,7 @@ rspec_parser :: readLinkCharacteristics (const DOMElement* link,
latency = hasLatency ? atoi(strLat.c_str()) : 0 ; latency = hasLatency ? atoi(strLat.c_str()) : 0 ;
packetLoss = hasPacketLoss ? atof(strLoss.c_str()) : 0.0; packetLoss = hasPacketLoss ? atof(strLoss.c_str()) : 0.0;
count = 1;
struct link_characteristics rv = {bandwidth, latency, packetLoss}; struct link_characteristics rv = {bandwidth, latency, packetLoss};
return rv; return rv;
} }
...@@ -233,7 +241,6 @@ rspec_parser :: readLinkInterface (const DOMElement* link, int& ifaceCount) ...@@ -233,7 +241,6 @@ rspec_parser :: readLinkInterface (const DOMElement* link, int& ifaceCount)
return rv; return rv;
} }
vector<struct link_type> rspec_parser::readLinkTypes (const DOMElement* link, vector<struct link_type> rspec_parser::readLinkTypes (const DOMElement* link,
int& typeCount) int& typeCount)
{ {
...@@ -252,8 +259,32 @@ vector<struct link_type> rspec_parser::readLinkTypes (const DOMElement* link, ...@@ -252,8 +259,32 @@ vector<struct link_type> rspec_parser::readLinkTypes (const DOMElement* link,
return types; return types;
} }
string rspec_parser :: readSubnodeOf (const DOMElement* tag, bool& isSubnode) bool rspec_parser::checkIsSwitch (string nodeId)
{
return (((this->switches).find(nodeId)) != (this->switches).end());
}
void rspec_parser::addSwitch (const DOMElement* node)
{
bool dummy;
string nodeId = this->readPhysicalId(node, dummy);
if (this->rspecType == RSPEC_TYPE_REQ) {
nodeId = this->readVirtualId(node, dummy);
}
(this->switches).insert(nodeId);
}
vector<struct vclass>
rspec_parser :: readVClasses (const DOMElement* tag)
{
return vector<struct vclass>();
}
string rspec_parser :: readSubnodeOf (const DOMElement* tag,
bool& isSubnode,
int& count)
{ {
count = (tag->getElementsByTagName(XStr("subnode_of").x()))->getLength();
return (this->readChild(tag, "subnode_of", isSubnode)); return (this->readChild(tag, "subnode_of", isSubnode));
} }
...@@ -281,4 +312,38 @@ rspec_parser::readFeaturesDesires (const DOMElement* tag, int& count) ...@@ -281,4 +312,38 @@ rspec_parser::readFeaturesDesires (const DOMElement* tag, int& count)
return vector<struct fd>(); return vector<struct fd>();
} }
bool rspec_parser::readDisallowTrivialMix (const DOMElement* tag)
{
return false;
}
bool rspec_parser::readUnique (const DOMElement* tag)
{
return false;
}
int rspec_parser::readTrivialBandwidth (const DOMElement* tag,
bool& hasTrivialBw)
{
hasTrivialBw = false;
return 0;