Commit a364642f authored by Tarun Prabhu's avatar Tarun Prabhu

Added support for specifying a link with more than 2 interfaces. assign would...

Added support for specifying a link with more than 2 interfaces. assign would automatically treat this as a LAN.
parent 0bd58582
......@@ -4,7 +4,7 @@
* All rights reserved.
*/
static const char rcsid[] = "$Id: annotate_rspec.cc,v 1.8 2009-10-08 20:27:24 tarunp Exp $";
static const char rcsid[] = "$Id: annotate_rspec.cc,v 1.9 2009-10-21 20:49:26 tarunp Exp $";
#ifdef WITH_XML
......@@ -35,11 +35,41 @@ using namespace std;
annotate_rspec :: annotate_rspec ()
{
// this->doc = doc;
this->virtual_root = request_root;
this->physical_elements = advertisement_elements;
vector<DOMElement*> lan_links = getElementsHavingAttribute(this->virtual_root, "link", "is_lan");
vector<DOMElement*>::iterator it;
for (it = lan_links.begin(); it < lan_links.end(); it++)
{
DOMElement* lan_link = *it;
// Removing annotations inserted earlier
lan_link->removeAttribute(XStr("is_lan").x());
string lan_link_id = string(XStr(lan_link->getAttribute(XStr("virtual_id").x())).c());
set<string> virtual_interface_ids;
DOMNodeList* interfaces = lan_link->getElementsByTagName(XStr("interface_ref").x());
for (int j = 0; j < interfaces->getLength(); j++)
{
DOMElement* interface = dynamic_cast<DOMElement*>(interfaces->item(j));
virtual_interface_ids.insert(string(XStr(interface->getAttribute(XStr("virtual_interface_id").x())).c()));
}
this->lan_links_map.insert(pair< string, set<string> >(lan_link_id, virtual_interface_ids));
}
}
// Annotate a trivial link
// NOTE: Are there other ways of specifying trivial links?
// void annotate_rspec::annotate_trivial_link (const char* v_name)
// {
// DOMElement* vlink = getElementByAttributeValue(this->virtual_root, "link", "virtual_id", v_name);
// DOMNodeList* interfaces = vlink->getElementByTagName(XStr("interface_ref").x());
// // We only really care about any one interface because both will be identical
// DOMElement* interface = dynamic_cast<DOMElement*>(interfaces->item(0));
// string virtual_node_id = string(XStr(interface->getAttribute(XStr("virtual_node_id").x())).c());
// DOMElement* vnode = getElementByAttributeValue(this->virtual_root, "node", "virtual_id", virtual_node_id.c_str());
// string
// }
// This will get called when a node or a direct link needs to be annotated
void annotate_rspec::annotate_element (const char* v_name, const char* p_name)
{
......@@ -49,18 +79,38 @@ void annotate_rspec::annotate_element (const char* v_name, const char* p_name)
// because direct links are never really going to happen
if (vnode != NULL)
{
DOMElement* pnode = (this->physical_elements->find(p_name))->second;
copy_component_spec(pnode, vnode);
if (!vnode->hasAttribute(XStr("generated_by_assign").x()))
{
DOMElement* pnode = (this->physical_elements->find(p_name))->second;
copy_component_spec(pnode, vnode);
}
}
else
{
DOMElement* vlink = getElementByAttributeValue(this->virtual_root, "link", "virtual_id", v_name);
DOMElement* plink = (this->physical_elements->find(p_name))->second;
// If plink is NULL, then it must be a trivial link
if (plink == NULL)
{
}
annotate_interface (plink, vlink, 0);
annotate_interface (plink, vlink, 1);
create_component_hop(plink, vlink, BOTH, NULL);
if (vlink->hasAttribute(XStr("generated_by_assign").x()))
{
string str_lan_link = string(XStr(vlink->getAttribute(XStr("lan_link").x())).c());
DOMElement* lan_link = getElementByAttributeValue(this->virtual_root, "link", "virtual_id", str_lan_link.c_str());
DOMNodeList* component_hops = vlink->getElementsByTagName(XStr("component_hop").x());
for (int i = 0; i < component_hops->getLength(); i++)
{
DOMElement* component_hop = dynamic_cast<DOMElement*>(component_hops->item(i));
copy_component_hop(lan_link, component_hop);
}
}
}
}
......@@ -167,32 +217,78 @@ DOMElement* annotate_rspec::create_component_hop (const DOMElement* plink, DOMEl
return (component_hop);
}
// Annotates the interface element on a link and updates the node which is the end point of the link as well
// Copies the component_hop from the generated_link to the requsted_link
// Also strips the unnecessary annotations from the component_hop after copying it
// The "unnecessary annotations" specify the end point of the link to be the auto-generated lan node
// We could just assume that the second interface_ref in the hop is contains these
// "unnecessary annotations" since we have generated it in the first place
// and we can sure that it will always be in exactly that same position,
// but it sounds like a dirty way of doing it and is not exactly robust,
// so we shall use the slower, but more robust method
void annotate_rspec::copy_component_hop(DOMElement* lan_link, DOMElement* component_hop)
{
string lan_link_id = string(XStr(lan_link->getAttribute(XStr("virtual_id").x())).c());
DOMNodeList* interfaces = component_hop->getElementsByTagName(XStr("interface_ref").x());
for (int i = 0; i < interfaces->getLength(); i++)
{
DOMElement* interface = dynamic_cast<DOMElement*>(interfaces->item(i));
if (interface->hasAttribute(XStr("virtual_interface_id").x()))
{
string str_virtual_interface_id = string(XStr(interface->getAttribute(XStr("virtual_interface_id").x())).c());
if (!has_interface_with_id (lan_link_id, str_virtual_interface_id))
{
interface->removeAttribute(XStr("virtual_interface_id").x());
interface->removeAttribute(XStr("virtual_node_id").x());
}
}
}
lan_link->appendChild(dynamic_cast<DOMElement*>(doc->importNode(component_hop, true)));
}
// Checks if the link contains an interface with virtual_interface_id = id
bool annotate_rspec::has_interface_with_id (string link_virtual_id, string id)
{
map< string, set<string> >::iterator map_it;
set<string>::iterator set_it;
map_it = lan_links_map.find(link_virtual_id);
if (map_it == this->lan_links_map.end())
return false;
set<string> virtual_ids = map_it->second;
set_it = virtual_ids.find(id);
if (set_it == virtual_ids.end())
return false;
return true;
}
// Updates the node which is the end point of the link
// 1) Find the interface_ref from the list of interface_refs on the link and it's virtual_interface_id
// 2) Find the virtual node to which the interface_ref is referring and its corresponding interface
// 3) Use this to find the physical node (component_node_uuid/urn) to which the virtual node has been mapped
// 4) Find the corresponding interface_ref on the physical link to which the virtual link has been mapped
// and get its component_interface_id
// 5) Annotate the interface on the virtual node obtained in 2) with the interface_id obtained in 4)
void annotate_rspec::annotate_interface (const DOMElement* plink, DOMElement* vlink, int interface_number)
{
DOMNodeList* vinterfaces = vlink->getElementsByTagName(XStr("interface_ref").x());
DOMElement* vlink_iface = dynamic_cast<DOMElement*>(vinterfaces->item(interface_number));
XStr vlink_iface_virtual_interface_id (vlink_iface->getAttribute(XStr("virtual_interface_id").x()));
// Get the virtual_id on the end points of the interface
XStr vlink_iface_virtual_id (vlink_iface->getAttribute(XStr("virtual_node_id").x()));
DOMElement* vnode = getElementByAttributeValue(this->virtual_root, "node", "virtual_id", vlink_iface_virtual_id.c());
XStr node_component_uuid (find_urn(vnode, "component"));
// Get the virtual_id of the node to which the interface belongs
XStr vlink_iface_virtual_node_id (vlink_iface->getAttribute(XStr("virtual_node_id").x()));
DOMElement* vnode = getElementByAttributeValue(this->virtual_root, "node", "virtual_id", vlink_iface_virtual_node_id.c());
DOMElement* vnode_iface_decl = getElementByAttributeValue(vnode, "interface", "virtual_id", vlink_iface_virtual_interface_id.c());
XStr component_node_uuid (find_urn(vnode, "component"));
// XStr node_component_uuid (vnode->getAttribute(XStr("component_uuid").x()));
DOMElement* p_iface = getElementByAttributeValue(plink, "interface_ref", "component_node_uuid", node_component_uuid.c());
if (p_iface == NULL)
{
p_iface = getElementByAttributeValue(plink, "interface_ref", "component_node_urn", node_component_uuid.c());
}
DOMElement* p_iface = getElementByAttributeValue(plink, "interface_ref", "component_node_uuid", component_node_uuid.c());
if (p_iface == NULL)
{
p_iface = getElementByAttributeValue(plink, "interface_ref", "component_node_urn", component_node_uuid.c());
}
// vlink_iface->setAttribute(XStr("component_node_uuid").x(), p_iface->getAttribute(XStr("component_node_uuid").x()));
// vlink_iface->setAttribute(XStr("component_interface_id").x(), p_iface->getAttribute(XStr("component_interface_id").x()));
XStr component_interface_id (p_iface->getAttribute(XStr("component_interface_id").x()));
XStr virtual_interface_id (vlink_iface->getAttribute(XStr("virtual_interface_id").x()));
// Get the interface for the node and update
DOMElement* vnode_iface_decl = getElementByAttributeValue(vnode, "interface", "virtual_id", virtual_interface_id.c());
vnode_iface_decl->setAttribute (XStr("component_id").x(), component_interface_id.x());
}
......@@ -237,4 +333,43 @@ DOMElement* annotate_rspec::find_next_link_in_path (DOMElement *prev, list<const
return link;
}
void annotate_rspec::cleanup()
{
vector<DOMElement*>::iterator it;
// Remove generated links
vector<DOMElement*> generated_links = getElementsHavingAttribute(this->virtual_root, "link", "generated_by_assign");
for (it = generated_links.begin(); it < generated_links.end(); it++)
{
DOMNode* generated_link = dynamic_cast<DOMNode*>(*it);
dynamic_cast<DOMNode*>(this->virtual_root)->removeChild(generated_link);
}
// Remove generated nodes
vector<DOMElement*> generated_nodes = getElementsHavingAttribute(this->virtual_root, "node", "generated_by_assign");
for (it = generated_nodes.begin(); it < generated_nodes.end(); it++)
{
DOMNode* generated_link = dynamic_cast<DOMNode*>(*it);
dynamic_cast<DOMNode*>(this->virtual_root)->removeChild(generated_link);
}
// Remove additional attributes added to elements
// Remove the is_lan attribute
vector<DOMElement*> lan_links = getElementsHavingAttribute(this->virtual_root, "link", "is_lan");
for (it = lan_links.begin(); it < lan_links.end(); it++)
{
DOMElement* lan_link = *it;
lan_link->removeAttribute(XStr("is_lan").x());
}
}
bool annotate_rspec::is_generated_element(const char* tag, const char* attr_name, const char* attr_value)
{
DOMElement* element = getElementByAttributeValue(this->virtual_root, tag, attr_name, attr_value);
if (element == NULL)
return false;
return (element->hasAttribute(XStr("generated_by_assign").x()));
}
#endif
......@@ -19,6 +19,7 @@
#include <list>
#include <map>
#include <set>
#include <utility>
#include <string>
......@@ -29,6 +30,7 @@ class annotate_rspec : public annotate
private:
// Enumeration of which interface in a hop is an interface to a link end point
enum endpoint_interface_enum { NEITHER, SOURCE, DESTINATION, BOTH };
std::map< std::string, std::set<std::string> > lan_links_map;
public:
annotate_rspec ();
......@@ -42,6 +44,9 @@ class annotate_rspec : public annotate
// Annotates an interface element on a link
void annotate_interface (const xercesc::DOMElement* plink, xercesc::DOMElement* vlink, int interface_number);
// Annotate a trivial link
void annotate_trivial_link (const char* v_name);
// Creates a hop from a switch till the next end point. Adds the hop to the vlink and returns the hop element that was created
xercesc::DOMElement* create_component_hop (const xercesc::DOMElement* plink, xercesc::DOMElement* vlink, int endpoint_interface, const xercesc::DOMElement* prev_component_hop);
......@@ -53,7 +58,19 @@ class annotate_rspec : public annotate
xercesc::DOMElement* find_next_link_in_path (xercesc::DOMElement *prev, std::list<const char*>* links);
// Copies the component spec from the source to the destination
void annotate_rspec::copy_component_spec(const xercesc::DOMElement* src, xercesc::DOMElement* dst);
void copy_component_spec(const xercesc::DOMElement* src, xercesc::DOMElement* dst);
// Copies the component hop from the auto-generated link to the requested link
void copy_component_hop(xercesc::DOMElement* requested_link, xercesc::DOMElement* component_hop);
// Checks if the link contains an interface with virtual_interface_id = id
bool has_interface_with_id (std::string link_virtual_id, std::string id);
// Removes all the extra tags and generated elements from the XML document
void cleanup ();
// Checks whether an element of type tag with attr_name = attr_value is a generated element
bool is_generated_element (const char* tag, const char* attr_name, const char* attr_value);
};
#endif //for __ANNOTATE_RSPEC_H
......
......@@ -8,7 +8,7 @@
* XML Parser for RSpec ptop files
*/
static const char rcsid[] = "$Id: parse_advertisement_rspec.cc,v 1.6 2009-10-08 00:31:59 tarunp Exp $";
static const char rcsid[] = "$Id: parse_advertisement_rspec.cc,v 1.7 2009-10-21 20:49:26 tarunp Exp $";
#ifdef WITH_XML
......@@ -518,10 +518,10 @@ bool populate_links_rspec(DOMElement *root, tb_pgraph &pg, tb_sgraph &sg,
interface_spec source = parse_interface_rspec_xml(dynamic_cast<DOMElement*>(interfaces->item(0)));
interface_spec dest = parse_interface_rspec_xml(dynamic_cast<DOMElement*>(interfaces->item(1)));
src_node = source.component_node_uuid;
src_iface = source.component_interface_name;
dst_node = dest.component_node_uuid;
dst_iface = dest.component_interface_name;
src_node = source.component_node_id;
src_iface = source.component_interface_id;
dst_node = dest.component_node_id;
dst_iface = dest.component_interface_id;
if (src_node.compare("") == 0 || src_iface.compare("") == 0)
{
......
This diff is collapsed.
......@@ -4,7 +4,7 @@
* All rights reserved.
*/
static const char rcsid[] = "$Id: solution.cc,v 1.14 2009-07-09 23:19:27 gtw Exp $";
static const char rcsid[] = "$Id: solution.cc,v 1.15 2009-10-21 20:49:26 tarunp Exp $";
#include "solution.h"
#include "vclass.h"
......@@ -51,6 +51,7 @@ void print_solution(const solution &s) {
tb_vnode *vn;
#ifdef WITH_XML
bool is_generated = false;
both_inputs_xml = ptop_xml_input && vtop_xml_input;
both_inputs_rspec = ptop_rspec_input && vtop_rspec_input;
......@@ -65,24 +66,26 @@ void print_solution(const solution &s) {
cout << "Nodes:" << endl;
tie(vit,veit) = vertices(VG);
for (;vit != veit;++vit) {
vn = get(vvertex_pmap,*vit);
if (! s.is_assigned(*vit)) {
cout << "unassigned: " << vn->name << endl;
} else {
cout << vn->name << " " << get(pvertex_pmap,s.get_assignment(*vit))->name << endl;
#ifdef WITH_XML
const char* node_name = XStr(vn -> name).c();
const char* assigned_to = XStr (get(pvertex_pmap,s.get_assignment(*vit))->name).c() ;
if (both_inputs_rspec == true)
{
rspec_annotater->annotate_element(node_name, assigned_to);
}
else if (both_inputs_xml == true)
{
vtop_annotater->annotate_element(node_name, assigned_to);
vn = get(vvertex_pmap,*vit);
if (! s.is_assigned(*vit)) {
cout << "unassigned: " << vn->name << endl;
} else {
#ifdef WITH_XML
const char* node_name = XStr(vn -> name).c();
const char* assigned_to = XStr (get(pvertex_pmap,s.get_assignment(*vit))->name).c() ;
if (both_inputs_rspec == true)
{
rspec_annotater->annotate_element(node_name, assigned_to);
if (rspec_annotater->is_generated_element("node", "virtual_id", node_name))
continue;
}
else if (both_inputs_xml == true)
{
vtop_annotater->annotate_element(node_name, assigned_to);
}
#endif
cout << vn->name << " " << get(pvertex_pmap,s.get_assignment(*vit))->name << endl;
}
#endif
}
}
cout << "End Nodes" << endl;
......@@ -95,8 +98,19 @@ void print_solution(const solution &s) {
for (;eit!=eendit;++eit) {
tb_vlink *vlink = get(vedge_pmap,*eit);
#ifdef WITH_XML
if (both_inputs_rspec == true)
{
is_generated = rspec_annotater->is_generated_element("link", "virtual_id", (vlink->name).c_str());
if (!is_generated)
cout << vlink->name;
}
else
cout << vlink->name;
#else
cout << vlink->name;
#endif
list<const char*> links;
if (vlink->link_info.type_used == tb_link_info::LINK_DIRECT) {
......@@ -106,39 +120,43 @@ void print_solution(const solution &s) {
// XXX: This is not correct because it contradicts the comment earlier
// It seems that it will work because the front and back of the list will have the same node
// But it needs to be checked anyway.
cout << " direct " << p->name << " (" <<
p->srcmac << "," << p->dstmac << ") " <<
p2->name << " (" << p2->srcmac << "," << p2->dstmac << ")";
#ifdef WITH_XML
if (both_inputs_rspec == true)
{
rspec_annotater->annotate_element((vlink->name).c_str(), (p->name).c_str());
if (is_generated)
continue;
}
else if (both_inputs_xml == true)
{
// annotate_vtop((vlink->name).c_str(), (p->name).c_str());
}
#endif
cout << " direct " << p->name << " (" <<
p->srcmac << "," << p->dstmac << ") " <<
p2->name << " (" << p2->srcmac << "," << p2->dstmac << ")";
} 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 << ")";
#ifdef WITH_XML
links.push_back((p->name).c_str());
links.push_back((p2->name).c_str());
if (both_inputs_rspec == true)
{
rspec_annotater->annotate_element((vlink->name).c_str(), &links);
if (is_generated)
continue;
}
else if (both_inputs_xml == true)
{
vtop_annotater->annotate_element((vlink->name).c_str(), &links);
vtop_annotater->annotate_element((vlink->name).c_str(), &links);
}
#endif
cout << " intraswitch " << p->name << " (" <<
p->srcmac << "," << p->dstmac << ") " <<
p2->name << " (" << p2->srcmac << "," << p2->dstmac << ")";
} else if (vlink->link_info.type_used ==
tb_link_info::LINK_INTERSWITCH) {
// Interswitch link - iterate through each intermediate link
......@@ -147,8 +165,11 @@ void print_solution(const solution &s) {
tb_plink *p = get(pedge_pmap,*it);
#ifdef WITH_XML
links.push_back((p->name).c_str());
#endif
if (!is_generated)
cout << " " << p->name << " (" << p->srcmac << "," << p->dstmac << ")";
#else
cout << " " << p->name << " (" << p->srcmac << "," << p->dstmac << ")";
#endif
}
#ifdef WITH_XML
if (both_inputs_rspec == true)
......@@ -159,8 +180,6 @@ void print_solution(const solution &s) {
{
vtop_annotater->annotate_element((vlink->name).c_str(), &links);
}
#endif
} else if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
// Trivial link - we really don't have useful information to
......@@ -170,6 +189,14 @@ void print_solution(const solution &s) {
tb_vnode *vnode = get(vvertex_pmap,vv);
pvertex pv = vnode->assignment;
tb_pnode *pnode = get(pvertex_pmap,pv);
/*#ifdef WITH_XML
if (both_inputs_rspec == true)
{
rspec_annotater->annotate_trivial_link((vlink->name).c_str(), (pnode->name).c_str());
if (is_generated)
continue;
}
#endif*/
cout << " trivial " << pnode->name << ":loopback" <<
" (" << pnode->name << "/null,(null)) " <<
pnode->name << ":loopback" << " (" << pnode->name <<
......@@ -183,6 +210,12 @@ void print_solution(const solution &s) {
}
cout << "End Edges" << endl;
cout << "End solution" << endl;
#ifdef WITH_XML
if (both_inputs_rspec == true)
{
rspec_annotater->cleanup();
}
#endif
}
/* Print out the current solution and annotate the rspec */
......@@ -194,12 +227,12 @@ void print_solution (const solution &s, const char* output_filename)
// and the objects have been created there
if (both_inputs_rspec == true)
{
cout << "Writing annotated file to " << output_filename << endl;
cout << "Writing annotated rspec to " << output_filename << endl;
rspec_annotater->write_annotated_file (output_filename);
}
else if (both_inputs_xml == true)
{
cout << "Writing annotated file to " << output_filename << endl;
cout << "Writing annotated xml to " << output_filename << endl;
vtop_annotater->write_annotated_file (output_filename);
}
#endif
......
......@@ -84,6 +84,18 @@ vector<const DOMElement*> getElementsByAttributeValue (const DOMElement* root, c
return elements;
}
vector<DOMElement*> getElementsHavingAttribute(const DOMElement* root, const char* tag, const char* attribute_name)
{
DOMNodeList* list = root->getElementsByTagName(XStr(tag).x());
vector<DOMElement*> elements;
for (int i = 0; i < list->getLength(); ++i)
{
DOMElement* ele = dynamic_cast<DOMElement*>(list->item(i));
if (ele->hasAttribute(XStr(attribute_name).x()))
elements.push_back(ele);
}
return elements;
}
/* This will only work if there is only one element with that tag within the root
* It is the callers responsibility to ensure that this is the case before calling this function
......
......@@ -48,6 +48,10 @@ xercesc::DOMElement* getElementByAttributeValue (std::vector<const xercesc::DOME
*/
std::vector<const xercesc::DOMElement*> getElementsByAttributeValue (const xercesc::DOMElement* root, const char* tag, const char* attribute_name, const char* attribute_value);
/* Returns a std::vector of elements which are children of root with name tag and which have an attribute, attribute_name
*/
std::vector<xercesc::DOMElement*> getElementsHavingAttribute(const xercesc::DOMElement* root, const char* tag, const char* attribute_name);
/* This will only work if there is only one element with that tag within the root
* It is the callers responsibility to ensure that this is the case before calling this function
*/
......@@ -104,10 +108,10 @@ component_spec parse_component_spec (const xercesc::DOMElement* element);
*/
typedef struct interface_spec
{
string virtual_node_uuid;
string virtual_interface_name;
string component_node_uuid;
string component_interface_name;
string virtual_node_id;
string virtual_interface_id;
string component_node_id;
string component_interface_id;
};
/*
* Parse the component spec attributes
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment