Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
emulab
emulab-devel
Commits
abf45b15
Commit
abf45b15
authored
May 20, 2009
by
Tarun Prabhu
Browse files
Massive commit of all the work to get assign to read XML. Fingers crossed...
parent
085a8fe6
Changes
48
Hide whitespace changes
Inline
Side-by-side
assign/GNUmakefile.in
View file @
abf45b15
...
...
@@ -8,6 +8,7 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ..
SUBDIR = assign
MAKEFILE_IN = @srcdir@/GNUmakefile.in
HAVE_XERCES = @HAVE_XERCES@
include $(OBJDIR)/Makeconf
...
...
@@ -22,7 +23,7 @@ all: assign
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS=parse_top.o parse_ptop.o assign.o pclass.o vclass.o
config.o
score.o \
OBJS=parse_top.o parse_ptop.o assign.o pclass.o vclass.o score.o \
parser.o solution.o anneal.o featuredesire.o neighborhood.o fstring.o
LIBS+= -lm
LDFLAGS+= -pipe -O3
...
...
@@ -30,6 +31,12 @@ CXXFLAGS = -pipe -I/usr/local/include -ftemplate-depth-40
# For OSX w/ fink
CXXFLAGS += -I/sw/include
ifeq ($(HAVE_XERCES),yes)
CXXFLAGS += -DWITH_XML
LIBS += -L/usr/local/lib -lxerces-c
OBJS += parse_ptop_xml.o parse_vtop_xml.o parse_policy_xml.o parse_error_handler.o xmlhelpers.o parse_advertisement_rspec.o parse_request_rspec.o annotate_rspec.o annotate_vtop.o annotate.o
endif
# Pick either this
CXXFLAGS += -O3
# or this
...
...
@@ -65,6 +72,8 @@ CXXFLAGS += -DFIX_PLINK_ENDPOINTS
CXXFLAGS += -DTRIVIAL_LINK_BW
# Use the old acceptance criteria, which gives special treatment to violations
CXXFLAGS += -DSPECIAL_VIOLATION_TREATMENT
# Pass the Emulab installation root directory
CXXFLAGS += -DTBROOT='"$(TBROOT)"'
# If you're looking to turn on or off USE_OPTIMAL, its now a cmdline
# option. Use OP={0,1} on the command line at run time... :)
...
...
@@ -73,7 +82,7 @@ DEPLIBS=$(OBJS)
assign: ${MAKEFILE_IN} ${DEPLIBS} ${OBJS}
${CXX} -o assign ${LIBS} $(OBJS) ${LDFLAGS}
install: $(INSTALL_LIBEXECDIR)/assign
clean:
...
...
@@ -83,25 +92,69 @@ clean:
# All this crap generated with 'g++ -MM' - don't want to do all the makefile goo
# to make this automatic, since none of it ever changes
#
anneal.o: anneal.cc anneal.h port.h delay.h physical.h common.h \
config.h featuredesire.h pclass.h virtual.h maps.h score.h solution.h \
vclass.h ${MAKEFILE_IN}
assign.o: assign.cc port.h common.h config.h delay.h physical.h \
featuredesire.h virtual.h vclass.h pclass.h score.h solution.h maps.h \
anneal.h ${MAKEFILE_IN}
config.o: config.cc config.h ${MAKEFILE_IN}
featuredesire.o: featuredesire.cc featuredesire.h common.h config.h \
${MAKEFILE_IN}
parse_ptop.o: parse_ptop.cc port.h delay.h physical.h common.h \
config.h featuredesire.h parser.h ${MAKEFILE_IN}
parse_top.o: parse_top.cc port.h common.h config.h vclass.h delay.h \
physical.h featuredesire.h virtual.h parser.h anneal.h pclass.h ${MAKEFILE_IN}
parser.o: parser.cc parser.h port.h ${MAKEFILE_IN}
pclass.o: pclass.cc port.h common.h config.h delay.h physical.h \
featuredesire.h virtual.h pclass.h ${MAKEFILE_IN}
score.o: score.cc port.h common.h config.h vclass.h delay.h physical.h \
featuredesire.h virtual.h pclass.h score.h /usr/include/math.h ${MAKEFILE_IN}
anneal.o: anneal.cc anneal.h port.h delay.h physical.h common.h fstring.h \
featuredesire.h forwarding.h pclass.h virtual.h maps.h score.h \
solution.h vclass.h neighborhood.h
assign.o: assign.cc port.h common.h fstring.h delay.h physical.h \
featuredesire.h forwarding.h virtual.h vclass.h pclass.h score.h \
solution.h maps.h anneal.h config.h parse_advertisement_rspec.h parse_ptop_xml.h xmlhelpers.h \
xstr.h parse_request_rspec.h parse_vtop_xml.h
annotate.o: annotate.cc annotate.h
annotate_rspec.o: annotate.cc annotate.h annotate_rspec.cc annotate_rspec.h \
xmlhelpers.h xstr.h
annotate_vtop.o: annotate.cc annotate.h annotate_vtop.cc annotate_vtop.h \
xmlhelpers.h xstr.h
config.o: config.cc config.h common.h port.h fstring.h score.h physical.h \
delay.h featuredesire.h forwarding.h virtual.h anneal.h pclass.h
featuredesire.o: featuredesire.cc featuredesire.h common.h port.h \
fstring.h score.h physical.h delay.h forwarding.h virtual.h
forwarding.o: forwarding.cc forwarding.h port.h fstring.h physical.h \
common.h delay.h featuredesire.h
fstring.o: fstring.cc fstring.h port.h
fstringtest.o: fstringtest.cc fstring.h port.h
neighborhood.o: neighborhood.cc neighborhood.h port.h common.h fstring.h \
physical.h delay.h featuredesire.h forwarding.h vclass.h virtual.h \
pclass.h
parse_error_handler.o: parse_error_handler.cc parse_error_handler.h \
xmlhelpers.h featuredesire.h common.h port.h fstring.h xstr.h
parse_policy_xml.o: parse_policy_xml.cc parse_policy_xml.h physical.h \
common.h port.h fstring.h delay.h featuredesire.h forwarding.h \
xmlhelpers.h xstr.h parse_error_handler.h
parse_ptop.o: parse_ptop.cc port.h delay.h physical.h common.h fstring.h \
featuredesire.h forwarding.h parser.h
parse_ptop_xml.o: parse_ptop_xml.cc parse_ptop_xml.h physical.h common.h \
port.h fstring.h delay.h featuredesire.h forwarding.h xmlhelpers.h \
xstr.h parse_error_handler.h
parser.o: parser.cc parser.h port.h
parse_advertisement_rspec.o: parse_advertisement_rspec.cc parse_advertisement_rspec.h \
common.h port.h fstring.h delay.h featuredesire.h forwarding.h \
xmlhelpers.h xstr.h parse_error_handler.h anneal.h
parse_request_rspec.o: parse_request_rspec.cc parse_request_rspec.h \
common.h port.h fstring.h delay.h featuredesire.h forwarding.h \
virtual.h xmlhelpers.h xstr.h parse_error_handler.h anneal.h \
vclass.h
parse_top.o: parse_top.cc port.h common.h fstring.h vclass.h delay.h \
physical.h featuredesire.h forwarding.h virtual.h parser.h anneal.h \
pclass.h
parse_top_xml.o: parse_top_xml.cc port.h common.h fstring.h vclass.h \
delay.h physical.h featuredesire.h forwarding.h virtual.h parser.h \
anneal.h pclass.h parse_top_xml.h xmlhelpers.h xstr.h \
parse_error_handler.h
parse_vtop_rspec.o: parse_vtop_rspec.cc parse_vtop_rspec.h \
common.h port.h fstring.h delay.h featuredesire.h forwarding.h \
virtual.h xmlhelpers.h xstr.h parse_error_handler.h anneal.h \
vclass.h
parse_vtop_xml.o: parse_vtop_xml.cc port.h common.h fstring.h vclass.h \
delay.h physical.h featuredesire.h forwarding.h virtual.h parser.h \
anneal.h pclass.h parse_vtop_xml.h xmlhelpers.h xstr.h \
parse_error_handler.h
pclass.o: pclass.cc port.h common.h fstring.h delay.h physical.h \
featuredesire.h forwarding.h virtual.h pclass.h
score.o: score.cc port.h common.h fstring.h vclass.h delay.h physical.h \
featuredesire.h forwarding.h virtual.h pclass.h score.h
solution.o: solution.cc solution.h port.h delay.h physical.h common.h \
config.h featuredesire.h virtual.h maps.h vclass.h ${MAKEFILE_IN}
vclass.o: vclass.cc port.h common.h config.h vclass.h delay.h \
physical.h featuredesire.h virtual.h ${MAKEFILE_IN}
fstring.h featuredesire.h forwarding.h virtual.h maps.h vclass.h
vclass.o: vclass.cc port.h common.h fstring.h vclass.h delay.h physical.h \
featuredesire.h forwarding.h virtual.h
xmlhelpers.o: xmlhelpers.cc xmlhelpers.h featuredesire.h common.h port.h \
fstring.h xstr.h
assign/anneal.cc
View file @
abf45b15
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2003-200
6
University of Utah and the Flux Group.
* Copyright (c) 2003-200
9
University of Utah and the Flux Group.
* All rights reserved.
*/
static
const
char
rcsid
[]
=
"$Id: anneal.cc,v 1.46 2009-05-20 18:06:07 tarunp Exp $"
;
#include
"anneal.h"
#include
"virtual.h"
...
...
@@ -48,6 +50,35 @@ name_name_map node_hints;
extern
FILE
*
scoresout
,
*
tempout
,
*
deltaout
;
#endif
/*
* Parameters used to control annealing
*/
int
init_temp
=
10
;
int
temp_prob
=
130
;
#ifdef LOW_TEMP_STOP
float
temp_stop
=
.005
;
#else
float
temp_stop
=
2
;
#endif
int
CYCLES
=
20
;
// The following are basically arbitrary constants
// Initial acceptance ratio for melting
float
X0
=
.95
;
#ifdef LOCAL_DERIVATIVE
float
epsilon
=
0.0001
;
#else
float
epsilon
=
0.01
;
#endif
float
delta
=
2
;
// Number of runs to spend melting
int
melt_trans
=
1000
;
int
min_neighborhood_size
=
1000
;
float
temp_rate
=
0.9
;
// Determines whether to accept a change of score difference 'change' at
// temperature 'temperature'.
inline
bool
accept
(
double
change
,
double
temperature
)
{
...
...
@@ -171,8 +202,9 @@ void smart_unmap_part2() {
double
temp
;
/* When this is finished the state will reflect the best solution found. */
void
anneal
(
bool
scoring_selftest
,
double
scale_neighborhood
,
double
*
initial_temperature
,
double
use_connected_pnode_find
)
void
anneal
(
bool
scoring_selftest
,
bool
check_fixed_nodes
,
double
scale_neighborhood
,
double
*
initial_temperature
,
double
use_connected_pnode_find
)
{
cout
<<
"Annealing."
<<
endl
;
...
...
@@ -187,15 +219,10 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
double
scorediff
;
int
nnodes
=
num_vertices
(
VG
);
int
npnodes
=
num_vertices
(
PG
);
//
int npnodes = num_vertices(PG);
int
npclasses
=
pclasses
.
size
();
float
cycles
=
CYCLES
*
(
float
)(
nnodes
+
num_edges
(
VG
)
+
PHYSICAL
(
npnodes
));
float
optimal
=
OPTIMAL_SCORE
(
num_edges
(
VG
),
nnodes
);
#ifdef STATS
cout
<<
"STATS_OPTIMAL = "
<<
optimal
<<
endl
;
#endif
int
mintrans
=
(
int
)
cycles
;
int
trans
;
...
...
@@ -214,7 +241,7 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
vvertex_int_priority_queue
unassigned_nodes
;
#ifdef VERBOSE
cout
<<
"Initialized to cycles="
<<
cycles
<<
"
optimal="
<<
optimal
<<
"
mintrans="
cout
<<
"Initialized to cycles="
<<
cycles
<<
" mintrans="
<<
mintrans
<<
" naccepts="
<<
naccepts
<<
endl
;
#endif
...
...
@@ -258,8 +285,8 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
// For now, if we find more than one match, we pick the first. It's
// possible that picking some other type would give us a better
// score, but let's noty worry about that
if
(
vn
->
vclass
->
has_type
((
*
i
)
->
ptype
->
name
()))
{
vn
->
type
=
(
*
i
)
->
ptype
->
name
();
if
(
vn
->
vclass
->
has_type
((
*
i
)
->
get_
ptype
()
->
name
()))
{
vn
->
type
=
(
*
i
)
->
get_
ptype
()
->
name
();
break
;
}
}
...
...
@@ -275,7 +302,17 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
<<
vn
->
type
<<
"
\n
"
;
}
}
if
(
add_node
(
vv
,
pv
,
false
,
true
,
false
)
==
1
)
{
/*
* Normally, we want to bypass some checks in add_node for fixed nodes -
* but not always (usually for testing purposes).
*/
bool
skip_checks
=
true
;
if
(
check_fixed_nodes
)
{
skip_checks
=
false
;
}
if
(
add_node
(
vv
,
pv
,
false
,
skip_checks
,
false
)
==
1
)
{
cout
<<
"*** Fixed node: Could not map "
<<
vn
->
name
<<
" to "
<<
pn
->
name
<<
endl
;
fix_failed
++
;
...
...
@@ -417,7 +454,6 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
// Crap added by ricci
#ifdef MELT
bool
melting
;
double
meltstart
;
#endif
int
nincreases
,
ndecreases
;
double
avgincrease
;
...
...
@@ -601,9 +637,9 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
if
(
vn
->
vclass
!=
NULL
)
{
vn
->
type
=
vn
->
vclass
->
choose_type
();
#ifdef SCORE_DEBUG
cerr
<<
"vclass "
<<
vn
->
vclass
->
name
<<
": choose type for "
<<
cerr
<<
"vclass "
<<
vn
->
vclass
->
get_
name
()
<<
": choose type for "
<<
vn
->
name
<<
" = "
<<
vn
->
type
<<
" dominant = "
<<
vn
->
vclass
->
dominant
<<
endl
;
vn
->
vclass
->
get_
dominant
()
<<
endl
;
#endif
}
...
...
@@ -746,13 +782,7 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
* this transition
*/
bool
accepttrans
=
false
;
if
(
newscore
<
optimal
)
{
// If this score is smaller than the one we think is optimal, of course we
// take it!
accepttrans
=
true
;
RDEBUG
(
cout
<<
"accept: optimal ("
<<
newscore
<<
","
<<
optimal
<<
")"
<<
endl
;)
}
else
if
(
melting
)
{
if
(
melting
)
{
// When melting, we take everything!
accepttrans
=
true
;
RDEBUG
(
cout
<<
"accept: melting"
<<
endl
;)
...
...
@@ -870,10 +900,10 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
#endif // SCORE_DEBUG
tie
(
vit
,
veit
)
=
vertices
(
VG
);
for
(;
vit
!=
veit
;
++
vit
)
{
tb_vnode
*
vn
=
get
(
vvertex_pmap
,
*
vit
);
if
(
vn
->
assigned
)
{
best_solution
.
set_assignment
(
*
vit
,
vn
->
assignment
);
best_solution
.
set_vtype_assignment
(
*
vit
,
vn
->
type
);
tb_vnode
*
vn
ode
=
get
(
vvertex_pmap
,
*
vit
);
if
(
vn
ode
->
assigned
)
{
best_solution
.
set_assignment
(
*
vit
,
vn
ode
->
assignment
);
best_solution
.
set_vtype_assignment
(
*
vit
,
vn
ode
->
type
);
}
else
{
best_solution
.
clear_assignment
(
*
vit
);
}
...
...
@@ -882,14 +912,14 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
//abstypes[*vit] = get(vvertex_pmap,*vit)->type;
}
vedge_iterator
eit
,
e
eit
;
tie
(
eit
,
e
eit
)
=
edges
(
VG
);
for
(;
eit
!=
e
eit
;
++
e
it
)
{
tb_vlink
*
vlink
=
get
(
vedge_pmap
,
*
eit
);
vedge_iterator
e
dge_
it
,
e
dge_it_end
;
tie
(
e
dge_
it
,
e
dge_it_end
)
=
edges
(
VG
);
for
(;
e
dge_
it
!=
e
dge_it_end
;
++
edge_
it
)
{
tb_vlink
*
vlink
=
get
(
vedge_pmap
,
*
e
dge_
it
);
if
(
vlink
->
link_info
.
type_used
!=
tb_link_info
::
LINK_UNMAPPED
)
{
best_solution
.
set_link_assignment
(
*
eit
,
vlink
->
link_info
);
best_solution
.
set_link_assignment
(
*
e
dge_
it
,
vlink
->
link_info
);
}
else
{
best_solution
.
clear_link_assignment
(
*
eit
);
best_solution
.
clear_link_assignment
(
*
e
dge_
it
);
}
}
...
...
@@ -900,10 +930,6 @@ void anneal(bool scoring_selftest, double scale_neighborhood,
cerr
<<
"New best recorded"
<<
endl
;
#endif
}
if
(
newscore
<
optimal
)
{
cout
<<
"OPTIMAL ( "
<<
optimal
<<
")"
<<
endl
;
goto
DONE
;
}
// Accept change
}
else
{
// !acceptrans
// Reject change, go back to the state we were in before
...
...
assign/anneal.h
View file @
abf45b15
...
...
@@ -58,6 +58,25 @@ using namespace __gnu_cxx;
#define PHYSICAL(x) 0
#endif
/*
* Parameters used to control annealing
*/
extern
int
init_temp
;
extern
int
temp_prob
;
extern
float
temp_stop
;
extern
int
CYCLES
;
// Initial acceptance ratio for melting
extern
float
X0
;
extern
float
epsilon
;
extern
float
delta
;
// Number of runs to spend melting
extern
int
melt_trans
;
extern
int
min_neighborhood_size
;
extern
float
temp_rate
;
/*
* Globals - XXX made non-global!
*/
...
...
@@ -80,8 +99,9 @@ inline bool accept(double change, double temperature);
tb_pnode
*
find_pnode
(
tb_vnode
*
vn
);
/* The big guy! */
void
anneal
(
bool
scoring_selftest
,
double
scale_neighborhood
,
double
*
initial_temperature
,
double
use_connected_pnode_find
);
void
anneal
(
bool
scoring_selftest
,
bool
check_fixed_nodes
,
double
scale_neighborhood
,
double
*
initial_temperature
,
double
use_connected_pnode_find
);
typedef
hash_map
<
fstring
,
fstring
>
name_name_map
;
typedef
slist
<
fstring
>
name_slist
;
...
...
assign/annotate.cc
0 → 100644
View file @
abf45b15
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2008 University of Utah and the Flux Group.
* All rights reserved.
*/
/*
* Implements the annotate methods which are independent of the type of file being annotated.
*/
static
const
char
rcsid
[]
=
"$Id: annotate.cc,v 1.2 2009-05-20 18:06:07 tarunp Exp $"
;
#ifdef WITH_XML
#include
"annotate.h"
#include
<xercesc/dom/DOM.hpp>
#include
<xercesc/dom/DOMImplementation.hpp>
#include
<xercesc/dom/DOMWriter.hpp>
#include
<xercesc/framework/LocalFileFormatTarget.hpp>
XERCES_CPP_NAMESPACE_USE
using
namespace
std
;
void
annotate
::
write_annotated_file
(
const
char
*
filename
)
{
// Get the current implementation
DOMImplementation
*
impl
=
DOMImplementationRegistry
::
getDOMImplementation
(
NULL
);
// Construct the DOMWriter
DOMWriter
*
writer
=
((
DOMImplementationLS
*
)
impl
)
->
createDOMWriter
();
// Make the output look pretty
if
(
writer
->
canSetFeature
(
XMLUni
::
fgDOMWRTFormatPrettyPrint
,
true
))
writer
->
setFeature
(
XMLUni
::
fgDOMWRTFormatPrettyPrint
,
true
);
// Set the byte-order-mark feature
if
(
writer
->
canSetFeature
(
XMLUni
::
fgDOMWRTBOM
,
true
))
writer
->
setFeature
(
XMLUni
::
fgDOMWRTBOM
,
true
);
// Construct the LocalFileFormatTarget
XMLFormatTarget
*
outputFile
=
new
xercesc
::
LocalFileFormatTarget
(
filename
);
// Serialize a DOMNode to the local file "<some-file-name>.xml"
writer
->
writeNode
(
outputFile
,
*
dynamic_cast
<
DOMNode
*>
(
this
->
virtual_root
));
// Flush the buffer to ensure all contents are written
outputFile
->
flush
();
// Release the memory
writer
->
release
();
}
#endif
assign/annotate.h
0 → 100644
View file @
abf45b15
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2008 University of Utah and the Flux Group.
* All rights reserved.
*/
/*
* Base class for the annotater.
*/
/* This is ugly, but we only really need this file if we are building with XML support */
#ifdef WITH_XML
#ifndef __ANNOTATE_H
#define __ANNOTATE_H
#include
<utility>
#include
<string>
#include
<list>
#include
<map>
#include
<xercesc/dom/DOM.hpp>
class
annotate
{
protected:
//xercesc::DOMDocument* doc;
xercesc
::
DOMElement
*
virtual_root
;
std
::
map
<
std
::
string
,
xercesc
::
DOMElement
*>
*
physical_elements
;
public:
// Annotates nodes and direct links in the rspec
virtual
void
annotate_element
(
const
char
*
v_name
,
const
char
*
p_name
)
=
0
;
// Annotates intraswitch and interswitch links in the rspec
virtual
void
annotate_element
(
const
char
*
v_name
,
std
::
list
<
const
char
*>*
links
)
=
0
;
// 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
virtual
xercesc
::
DOMElement
*
create_component_hop
(
const
xercesc
::
DOMElement
*
plink
,
xercesc
::
DOMElement
*
vlink
,
int
endpoint_interface
,
const
xercesc
::
DOMElement
*
prev_component_hop
)
=
0
;
// Finds the next link in the path returned by assign
virtual
xercesc
::
DOMElement
*
find_next_link_in_path
(
xercesc
::
DOMElement
*
prev
,
std
::
list
<
const
char
*>*
links
)
=
0
;
// Writes the annotated xml to disk
void
write_annotated_file
(
const
char
*
filename
);
};
#endif // for __ANNOTATE_H
#endif // for WITH_XML
assign/annotate_rspec.cc
0 → 100644
View file @
abf45b15
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2003-2009 University of Utah and the Flux Group.
* All rights reserved.
*/
static
const
char
rcsid
[]
=
"$Id: annotate_rspec.cc,v 1.2 2009-05-20 18:06:07 tarunp Exp $"
;
#ifdef WITH_XML
#include
"annotate.h"
#include
"annotate_rspec.h"
#include
<xercesc/util/PlatformUtils.hpp>
#include
<xercesc/dom/DOM.hpp>
#include
"xstr.h"
#include
"xmlhelpers.h"
#include
<iostream>
#include
<utility>
#include
<list>
#include
<string>
#define XMLDEBUG(x) (cerr << x);
extern
DOMDocument
*
doc
;
extern
DOMElement
*
request_root
;
extern
map
<
string
,
DOMElement
*>*
advertisement_elements
;
XERCES_CPP_NAMESPACE_USE
using
namespace
std
;
annotate_rspec
::
annotate_rspec
()
{
// this->doc = doc;
this
->
virtual_root
=
request_root
;
this
->
physical_elements
=
advertisement_elements
;
}
// 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
)
{
DOMElement
*
vnode
=
getElementByAttributeValue
(
this
->
virtual_root
,
"node"
,
"virtual_id"
,
v_name
);
// If a vnode by that name was found, then go ahead. If not, that element should be a link
// We are not terribly concerned about having to scan the entire physical topology twice
// 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
);
}
else
{
DOMElement
*
vlink
=
getElementByAttributeValue
(
this
->
virtual_root
,
"link"
,
"virtual_id"
,
v_name
);
DOMElement
*
plink
=
(
this
->
physical_elements
->
find
(
p_name
))
->
second
;
annotate_interface
(
plink
,
vlink
,
0
);
annotate_interface
(
plink
,
vlink
,
1
);
create_component_hop
(
plink
,
vlink
,
BOTH
,
NULL
);
}
}
// This is called when an intraswitch or interswitch link has to be annotated
void
annotate_rspec
::
annotate_element
(
const
char
*
v_name
,
list
<
const
char
*>*
links
)
{
// These are the paths from the source to the first switch
// and from the last switch to the destination
const
char
*
psrc_name
=
links
->
front
();
const
char
*
pdst_name
=
links
->
back
();
DOMElement
*
p_src_switch_link
=
(
this
->
physical_elements
->
find
(
psrc_name
))
->
second
;
DOMElement
*
p_switch_dst_link
=
(
this
->
physical_elements
->
find
(
pdst_name
))
->
second
;
// Remove these links from the list
// If it is an intra-switch link, the list should now be empty.
links
->
pop_front
();
links
->
pop_back
();
DOMElement
*
vlink
=
getElementByAttributeValue
(
this
->
virtual_root
,
"link"
,
"virtual_id"
,
v_name
);
annotate_interface
(
p_src_switch_link
,
vlink
,
0
);
annotate_interface
(
p_switch_dst_link
,
vlink
,
1
);
DOMElement
*
prev_component_hop
=
create_component_hop
(
p_src_switch_link
,
vlink
,
SOURCE
,
NULL
);
for
(
DOMElement
*
prev_link_in_path
=
p_src_switch_link
;
!
links
->
empty
();
)
{
DOMElement
*
p_switch_switch_link
=
find_next_link_in_path
(
prev_link_in_path
,
links
);
prev_component_hop
=
create_component_hop
(
p_switch_switch_link
,
vlink
,
NEITHER
,
prev_component_hop
);
prev_link_in_path
=
p_switch_switch_link
;
}
create_component_hop
(
p_switch_dst_link
,
vlink
,
DESTINATION
,
prev_component_hop
);
}
// 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
DOMElement
*
annotate_rspec
::
create_component_hop
(
const
DOMElement
*
plink
,
DOMElement
*
vlink
,
int
endpoint_interface
,
const
DOMElement
*
prev_component_hop
)
{
// Create a single_hop_link element
DOMElement
*
component_hop
=
doc
->
createElement
(
XStr
(
"component_hop"
).
x
());
copy_component_spec
(
plink
,
component_hop
);
DOMElement
*
component_hop_interface
=
doc
->
createElement
(
XStr
(
"interface"
).
x
());
// We assume the first interface is the source and the second is the destination
DOMNodeList
*
pinterfaces
=
plink
->
getElementsByTagName
(
XStr
(
"interface"
).
x
());
DOMElement
*
plink_src_iface
=
dynamic_cast
<
DOMElement
*>
(
pinterfaces
->
item
(
0
));
DOMElement
*
plink_dst_iface
=
dynamic_cast
<
DOMElement
*>
(
pinterfaces
->
item
(
1
));
DOMNodeList
*
vinterfaces
=
vlink
->
getElementsByTagName
(
XStr
(
"interface"
).
x
());
DOMElement
*
vlink_src_iface
=
dynamic_cast
<
DOMElement
*>
(
vinterfaces
->
item
(
0
));
DOMElement
*
vlink_dst_iface
=
dynamic_cast
<
DOMElement
*>
(
vinterfaces
->
item
(
1
));
// If the previous component hop is not specified (NULL),
// then the link is either direct or the direction is guaranteed to be from the node to the switch
DOMElement
*
plink_src_iface_clone
=
dynamic_cast
<
DOMElement
*>
(
doc
->
importNode
(
dynamic_cast
<
DOMNode
*>
(
plink_src_iface
),
true
));
DOMElement
*
plink_dst_iface_clone
=
dynamic_cast
<
DOMElement
*>
(
doc
->
importNode
(
dynamic_cast
<
DOMNode
*>
(
plink_dst_iface
),
true
));
// If the previous component is specified,
// the link specification could be the opposite of what we need
if
(
prev_component_hop
!=
NULL
)
{
// Find the destination of the previous component hop
DOMElement
*
prev_hop_dst_iface
=
dynamic_cast
<
DOMElement
*>
((
prev_component_hop
->
getElementsByTagName
(
XStr
(
"interface"
).
x
()))
->
item
(
1
));
XStr
prev_hop_dst_uuid
(
prev_hop_dst_iface
->
getAttribute
(
XStr
(
"component_node_uuid"
).
x
()));
// We need to do this because in advertisements, all links are from nodes to switches
// and we need to reverse this order for the last hop of a multi-hop path
// This is slightly more expensive, but definitely more robust than checking based on whether a destination interface was specified
if
(
strcmp
(
prev_hop_dst_uuid
.
c
(),
XStr
(
plink_dst_iface
->
getAttribute
(
XStr
(
"component_node_uuid"
).
x
())).
c
())
==
0
)
{
plink_src_iface_clone
=
dynamic_cast
<
DOMElement
*>
(
doc
->
importNode
(
dynamic_cast
<
DOMNode
*>
(
plink_dst_iface
),
true
));
plink_dst_iface_clone
=
dynamic_cast
<
DOMElement
*>
(
doc
->
importNode
(
dynamic_cast
<
DOMNode
*>
(
plink_src_iface
),
true
));
}
}
// If the source interface is an end point
if
(
endpoint_interface
==
SOURCE
||
endpoint_interface
==
BOTH
)
set_interface_as_link_endpoint
(
plink_src_iface_clone
,
XStr
(
vlink_src_iface
->
getAttribute
(
XStr
(
"virtual_node_id"
).
x
())).
c
());
// If the destination interface is an end point
if
(
endpoint_interface
==
DESTINATION
||
endpoint_interface
==
BOTH
)
set_interface_as_link_endpoint
(
plink_dst_iface_clone
,
XStr
(
vlink_dst_iface
->
getAttribute
(
XStr
(
"virtual_node_id"
).
x
())).
c
());
// Add interface specifications to the link in the single hop element
component_hop
->
appendChild
(
plink_src_iface_clone
);
component_hop
->
appendChild
(
plink_dst_iface_clone
);
vlink
->
appendChild
(
component_hop
);
return
(
component_hop
);
}
// Annotates the interface element on a link and updates the node which is the end point of the link as well