Skip to content
GitLab
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
48385f00
Commit
48385f00
authored
Feb 10, 2003
by
Robert Ricci
Browse files
Back off to versions before merging in paper branch, so that we have
time to debug a delayed LAN problem.
parent
779f4ca6
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
assign/GNUmakefile.in
View file @
48385f00
#
# Insert Copyright Here.
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ..
SUBDIR = assign
#
# Support for optional assign binary to avoid LEDA restrictions
#
ASSIGNBINARY = @ASSIGN@
include $(OBJDIR)/Makeconf
all: assign
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS=parse_top.o parse_ptop.o assign.o pclass.o vclass.o config.o score.o \
parser.o
LIBS+= -lm
LDFLAGS+= -pipe -O3
CXXFLAGS = -pipe -I/usr/local/include -ftemplate-depth-30
LEDA=@LEDA@
# Pick either this
CXXFLAGS += -O3
# or this
OBJS=score.o parse_top.o parse_ptop.o config.o pclass.o vclass.o
LIBS+=-L${LEDA} -lD3 -lW -lP -lG -lL -L/usr/X11R6/lib -lX11 -lm -L.
LDFLAGS+= -O3
CXXFLAGS = -I${LEDA}/incl
# Pick one of the following:
CXXFLAGS += -Wall -O3
#CXXFLAGS += -O0 -g -Wall -DVERBOSE
# and then zero or more of these
#CXXFLAGS += -DSCORE_DEBUG
#CXXFLAGS += -DSCORE_DEBUG_MORE
#CXXFLAGS += -DPCLASS_DEBUG
#CXXFLAGS += -DDUMP_GRAPH
#CXXFLAGS += -DSCORE_DEBUG_LOTS
# And then, regardless, you can also have this
#CXXFLAGS += -DSTATS
#CXXFLAGS += -O0 -g -Wall -DVERBOSE -DSCORE_DEBUG -DPCLASS_DEBUG
#CXXFLAGS += -O0 -g -Wall -DVERBOSE -DSCORE_DEBUG -DPCLASS_DEBUG -DPCLASS_DEBUG_MORE
#CXXFLAGS += -O0 -g -Wall -DVERBOSE -DSCORE_DEBUG -DSCORE_DEBUG_MORE -DPCLASS_DEBUG -DPCLASS_DEBUG_MORE
# assign now supports a dizzing array of defines, which are as-yet undocumented
# Here are the ones used for a typical build:
# Pick cooling schedule
CXXFLAGS += -DMELT -DEPSILON_TERMINATE -DCHILL -DNEIGHBOR_LENGTH \
-DLOCAL_DERIVATIVE -DALLOW_NEGATIVE_DELTA
# Bug/scoring fixes
CXXFLAGS += -DINTERSWITCH_LENGTH -DPNODE_SWITCH_LOAD -DFIX_SHARED_INTERFACES
# Various tweaks to the simulated annealing behavior
CXXFLAGS += -DFIND_PNODE_SEARCH -DNO_REVERT
# This should be enabled, for better mapping, but has to be disabled
# for now because it breaks vclasses
#CXXFLAGS += -DPER_VNODE_TT -DSMART_UNMAP
#CXXFLAGS += -DSTATS
# 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... :)
DEPLIBS=$(OBJS)
assign: ${DEPLIBS} ${OBJS}
${CXX} -o assign ${LIBS} $(OBJS) ${LDFLAGS}
ifdef ASSIGNBINARY
assign: ${ASSIGNBINARY}
rm -f assign
cp $< assign
else
assign: ${DEPLIBS} ${OBJS} assign.o
${CXX} assign.o -o assign ${LIBS} $(OBJS) ${LDFLAGS}
endif
install: $(INSTALL_LIBEXECDIR)/assign
...
...
assign/assign.cc
View file @
48385f00
This diff is collapsed.
Click to expand it.
assign/common.h
View file @
48385f00
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* All rights reserved.
*/
#ifndef __COMON_H
#define __COMON_H
#include
"config.h"
const
int
MAX_PNODES
=
1024
;
/* maximum # of physical nodes */
const
int
MAX_PNODES
=
2048
;
/* maximum # of physical nodes */
/*
To use these on the command line, each entry gets a
...
...
@@ -11,78 +17,29 @@ const int MAX_PNODES = 1024; /* maximum # of physical nodes */
Here we declare them all and give them defaults.
*/
//static int init_temp = 100;
static
int
init_temp
=
10
;
static
int
init_temp
=
100
;
static
int
USE_OPTIMAL
=
1
;
static
int
temp_prob
=
130
;
#ifdef LOW_TEMP_STOP
//static int temp_stop = 1;
static
float
temp_stop
=
.005
;
#else
static
float
temp_stop
=
2
;
//static int temp_stop = 20;
#endif
static
int
temp_stop
=
20
;
static
int
CYCLES
=
20
;
// The following are basically arbitrary constants
// Initial acceptance ratio for melting
static
float
X0
=
.95
;
//static float epsilon = 0.1;
#ifdef LOCAL_DERIVATIVE
static
float
epsilon
=
0.0001
;
#else
static
float
epsilon
=
0.01
;
#endif
static
float
delta
=
2
;
//static float delta = 1;
//static float min_temp_end = 0.01;
//static float min_temp_end = 10000000.0;
// Number of runs to spend melting
static
int
melt_trans
=
500
;
static
int
min_neighborhood_size
=
500
;
static
float
temp_rate
=
0
.
9
;
static
float
opt_nodes_per_sw
=
5
.
0
;
#ifdef PENALIZE_BANDWIDTH
static
float
SCORE_DIRECT_LINK
=
0.0
;
/* Cost of a direct link */
static
float
SCORE_INTRASWITCH_LINK
=
0.0
;
/* Cost of an intraswitch link*/
static
float
SCORE_INTERSWITCH_LINK
=
0.0
;
/* Cost of an interswitch link*/
#else
static
float
SCORE_DIRECT_LINK
=
0
.
01
;
/* Cost of a direct link */
static
float
SCORE_INTRASWITCH_LINK
=
0.02
;
/* Cost of an intraswitch link*/
static
float
SCORE_INTERSWITCH_LINK
=
0.2
;
/* Cost of an interswitch link*/
#endif
static
float
SCORE_DIRECT_LINK_PENALTY
=
0
.
5
;
/* Cost of overused direct link*/
static
float
SCORE_INTRASWITCH_LINK
=
0
.
02
;
/* Cost of an intraswitch link*/
static
float
SCORE_INTERSWITCH_LINK
=
0
.
05
;
/* Cost of an interswitch link*/
static
float
SCORE_NO_CONNECTION
=
0
.
5
;
/* Cost of not filling a virt. link*/
static
float
SCORE_PNODE
=
0.
2
;
/* Cost of using a pnode*/
static
float
SCORE_PNODE
=
0
.
05
;
/* Cost of using a pnode*/
static
float
SCORE_PNODE_PENALTY
=
0
.
5
;
/* Cost of overusing a pnode*/
static
float
SCORE_SWITCH
=
0
.
5
;
/* Cost of using a switch.*/
static
float
SCORE_UNASSIGNED
=
1.0
;
/* Cost of an unassigned node*/
static
float
SCORE_DESIRE
=
1.0
;
/* Multiplier for desire costs*/
static
float
SCORE_FEATURE
=
1.0
;
/* Multiplier for feature weights*/
#ifdef NO_PCLASS_PENALTY
static
float
SCORE_PCLASS
=
0.0
;
/* Cost of each pclass */
#else
static
float
SCORE_UNASSIGNED
=
1
;
/* Cost of an unassigned node*/
static
float
SCORE_OVER_BANDWIDTH
=
0
.
5
;
/* Cost of going over bandwidth*/
static
float
SCORE_DESIRE
=
1
;
/* Multiplier for desire costs*/
static
float
SCORE_FEATURE
=
1
;
/* Multiplier for feature weights*/
static
float
SCORE_PCLASS
=
0
.
5
;
/* Cost of each pclass */
#endif
static
float
SCORE_VCLASS
=
1.0
;
/* vclass score multiplier */
static
float
SCORE_VCLASS
=
1
;
/* vclass score multiplier */
static
float
SCORE_EMULATED_LINK
=
0
.
01
;
/* cost of an emualted link */
static
float
SCORE_OUTSIDE_DELAY
=
0.5
;
/* penalty for going out of delay
requirements */
static
float
SCORE_DELAY
=
10.0
;
/* multiplier to distance for delay scoring */
#ifdef PENALIZE_UNUSED_INTERFACES
static
float
SCORE_UNUSED_INTERFACE
=
0.04
;
#endif
// The following are used to weight possible link resolutions. Higher
// numbers mean a more likely resolution. Trivial resolutions are always
// used if possible.
static
float
LINK_RESOLVE_DIRECT
=
4.0
;
static
float
LINK_RESOLVE_INTRASWITCH
=
2.0
;
static
float
LINK_RESOLVE_INTERSWITCH
=
1.0
;
static
struct
config_param
options
[]
=
{
{
"IT"
,
CONFIG_INT
,
&
init_temp
,
0
},
...
...
@@ -96,6 +53,7 @@ static struct config_param options[] = {
{
"1S"
,
CONFIG_FLOAT
,
&
SCORE_INTERSWITCH_LINK
,
0
},
{
"2S"
,
CONFIG_FLOAT
,
&
SCORE_INTRASWITCH_LINK
,
0
},
{
"NC"
,
CONFIG_FLOAT
,
&
SCORE_NO_CONNECTION
,
0
},
{
"OB"
,
CONFIG_FLOAT
,
&
SCORE_OVER_BANDWIDTH
,
0
},
{
"DL"
,
CONFIG_FLOAT
,
&
SCORE_DIRECT_LINK
,
0
},
{
"DP"
,
CONFIG_FLOAT
,
&
SCORE_DIRECT_LINK_PENALTY
,
0
},
{
"PN"
,
CONFIG_FLOAT
,
&
SCORE_PNODE
,
0
},
...
...
@@ -105,41 +63,12 @@ static struct config_param options[] = {
{
"SW"
,
CONFIG_FLOAT
,
&
SCORE_SWITCH
,
0
},
{
"EL"
,
CONFIG_FLOAT
,
&
SCORE_EMULATED_LINK
,
0
},
{
"ON"
,
CONFIG_FLOAT
,
&
opt_nodes_per_sw
,
0
},
{
"TR"
,
CONFIG_FLOAT
,
&
temp_rate
,
0
},
{
"LD"
,
CONFIG_FLOAT
,
&
LINK_RESOLVE_DIRECT
,
0
},
{
"LI"
,
CONFIG_FLOAT
,
&
LINK_RESOLVE_INTRASWITCH
,
0
},
{
"LT"
,
CONFIG_FLOAT
,
&
LINK_RESOLVE_INTERSWITCH
,
0
},
{
"OD"
,
CONFIG_FLOAT
,
&
SCORE_OUTSIDE_DELAY
,
0
},
{
"DM"
,
CONFIG_FLOAT
,
&
SCORE_DELAY
,
0
}
{
"TR"
,
CONFIG_FLOAT
,
&
temp_rate
,
0
}
};
static
int
noptions
=
sizeof
(
options
)
/
sizeof
(
options
[
0
]);
void
parse_options
(
char
**
argv
,
struct
config_param
options
[],
int
nopt
);
struct
eqstr
{
bool
operator
()(
const
char
*
A
,
const
char
*
B
)
const
{
return
(
!
strcmp
(
A
,
B
));
}
};
enum
edge_data_t
{
edge_data
};
enum
vertex_data_t
{
vertex_data
};
#endif
namespace
boost
{
BOOST_INSTALL_PROPERTY
(
edge
,
data
);
BOOST_INSTALL_PROPERTY
(
vertex
,
data
);
}
typedef
hash_map
<
crope
,
crope
>
name_name_map
;
typedef
slist
<
crope
>
name_slist
;
template
<
class
T
>
struct
hashptr
{
size_t
operator
()(
T
const
&
A
)
const
{
return
(
size_t
)
A
;
}
};
#endif
assign/config.h
View file @
48385f00
/*
* Copyright (c) 1999-2001 The University of Utah and the Flux Group.
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* All rights reserved.
*/
...
...
@@ -24,7 +25,7 @@ struct config_param {
/* types */
#define CONFIG_INT 0
#define CONFIG_FLOAT 1
void
parse_options
(
char
**
argv
,
struct
config_param
options
[],
int
nopt
);
int
config_parse
(
char
**
args
,
struct
config_param
cparams
[],
int
nparams
);
void
dump_options
(
const
char
*
str
,
struct
config_param
cparams
[],
int
nparams
);
...
...
assign/parse_ptop.cc
View file @
48385f00
#include
"port.h"
#include
<hash_map>
#include
<slist>
#include
<rope>
#include
<hash_set>
#include
<boost/config.hpp>
#include
<boost/utility.hpp>
#include
<boost/property_map.hpp>
#include
<boost/graph/graph_traits.hpp>
#include
<boost/graph/adjacency_list.hpp>
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group.
* All rights reserved.
*/
/*
* parse ptop files. These are basic topologies
* that are used to represent the physical topology.
*
* format:
* node <name> <type> [<type2> ...]
* <type> = <t>[:<max>]
* <t> = pc | switch | dnard
* <max> = how many virtual entities of that type per physical entity.
* link <name> <src>[:<mac>] <dst>[:<mac>] <size> <number>
*/
#include
<LEDA/graph_alg.h>
#include
<LEDA/graphwin.h>
#include
<LEDA/ugraph.h>
#include
<LEDA/dictionary.h>
#include
<LEDA/map.h>
#include
<LEDA/graph_iterator.h>
#include
<LEDA/sortseq.h>
#include
<iostream.h>
using
namespace
boost
;
using
namespace
boost
;
#include
<string.h>
#include
<stdio.h>
#include
"common.h"
#include
"delay.h"
#include
"physical.h"
#include
"parser.h"
extern
name_pvertex_map
pname2
vertex
;
extern
n
ame_slist
ptypes
;
#define ptop_error(s) errors++;cerr << "PTOP:" << line << ": " << s << endl
extern
dictionary
<
string
,
node
>
pname2
node
;
extern
n
ode
pnodes
[
MAX_PNODES
];
// int -> node map
node_array
<
int
>
switch_index
;
extern
list
<
string
>
ptypes
;
int
parse_ptop
(
tb_pgraph
&
PG
,
tb_sgraph
&
SG
,
istream
&
i
)
{
int
num_nodes
=
0
;
int
line
=
0
,
errors
=
0
;
char
inbuf
[
1024
];
string_vector
parsed_line
;
int
switchi
=
0
;
node
no1
;
edge
ed1
;
string
s1
,
s2
;
char
inbuf
[
255
];
char
n1
[
32
],
n2
[
32
];
int
size
,
num
;
int
n
=
1
;
char
*
snext
;
char
*
snode
;
char
*
scur
;
char
lname
[
32
];
int
isswitch
;
switch_index
.
init
(
PG
,
MAX_PNODES
,
0
);
pnodes
[
0
]
=
NULL
;
while
(
!
i
.
eof
())
{
line
++
;
i
.
getline
(
inbuf
,
1024
);
parsed_line
=
split_line
(
inbuf
,
' '
);
if
(
parsed_line
.
size
()
==
0
)
{
continue
;}
crope
command
=
parsed_line
[
0
];
if
(
command
.
compare
(
"node"
)
==
0
)
{
if
(
parsed_line
.
size
()
<
3
)
{
ptop_error
(
"Bad node line, too few arguments."
);
char
*
ret
;
i
.
getline
(
inbuf
,
254
);
ret
=
strchr
(
inbuf
,
'\n'
);
if
(
ret
)
*
ret
=
0
;
if
(
strlen
(
inbuf
)
==
0
)
{
continue
;
}
if
(
!
strncmp
(
inbuf
,
"node"
,
4
))
{
isswitch
=
0
;
snext
=
inbuf
;
scur
=
strsep
(
&
snext
,
" "
);
if
(
strcmp
(
"node"
,
scur
)
!=
0
)
{
fprintf
(
stderr
,
"bad node line: %s
\n
"
,
inbuf
);
}
else
{
num_nodes
++
;
crope
name
=
parsed_line
[
1
];
bool
isswitch
=
false
;
pvertex
pv
=
add_vertex
(
PG
);
tb_pnode
*
p
=
new
tb_pnode
();
put
(
pvertex_pmap
,
pv
,
p
);
p
->
name
=
name
;
p
->
typed
=
false
;
p
->
max_load
=
0
;
p
->
current_load
=
0
;
p
->
pnodes_used
=
0
;
//#ifdef PENALIZE_UNUSED_INTERFACES
p
->
total_interfaces
=
0
;
//#endif
unsigned
int
i
;
for
(
i
=
2
;
(
i
<
parsed_line
.
size
())
&&
(
parsed_line
[
i
].
compare
(
"-"
)
!=
0
);
++
i
)
{
crope
type
,
load
;
if
(
split_two
(
parsed_line
[
i
],
':'
,
type
,
load
,
"1"
)
!=
0
)
{
ptop_error
(
"Bad node line, no load for type: "
<<
type
<<
"."
);
}
scur
=
strsep
(
&
snext
,
" "
);
snode
=
scur
;
string
s
(
snode
);
#ifdef GRAPH_DEBUG
cout
<<
"Found phys. node '"
<<
snode
<<
"'
\n
"
;
#endif
no1
=
PG
.
new_node
();
PG
[
no1
].
name
=
string
(
snode
);
PG
[
no1
].
typed
=
false
;
PG
[
no1
].
max_load
=
0
;
PG
[
no1
].
current_load
=
0
;
PG
[
no1
].
pnodes_used
=
0
;
while
((
scur
=
strsep
(
&
snext
,
" "
))
!=
NULL
&&
(
strcmp
(
scur
,
"-"
)))
{
char
*
t
,
*
load
=
scur
;
int
iload
;
if
(
sscanf
(
load
.
c_str
(),
"%d"
,
&
iload
)
!=
1
)
{
ptop_error
(
"Bad node line, bad load: "
<<
load
<<
"."
);
iload
=
1
;
t
=
strsep
(
&
load
,
":"
);
string
stype
(
t
);
if
(
load
)
{
if
(
sscanf
(
load
,
"%d"
,
&
iload
)
!=
1
)
{
fprintf
(
stderr
,
"Bad load specifier: %s
\n
"
,
load
);
iload
=
1
;
}
}
else
{
iload
=
1
;
}
ptypes
.
push
_front
(
type
);
if
(
type
.
compare
(
"switch"
)
==
0
)
{
isswitch
=
true
;
p
->
types
[
"switch"
]
=
1
;
svertex
sv
=
add_vertex
(
SG
)
;
tb_switch
*
s
=
new
tb_switch
();
put
(
svertex_pmap
,
sv
,
s
)
;
s
->
mate
=
pv
;
p
->
sgraph_switch
=
sv
;
ptypes
.
push
(
s
type
);
if
(
strcmp
(
t
,
"switch"
)
==
0
)
{
isswitch
=
1
;
PG
[
no1
].
types
.
insert
(
stype
,
1
)
;
PG
[
no1
].
the_switch
=
no1
;
node
sw
=
SG
.
new_node
();
SG
[
sw
].
mate
=
no1
;
PG
[
no1
].
sgraph_switch
=
sw
;
switch_index
[
no1
]
=
switchi
++
;
}
else
{
p
->
types
[
type
]
=
iload
;
PG
[
no1
].
types
.
insert
(
stype
,
iload
)
;
}
}
for
(
i
=
i
+
1
;
i
<
parsed_line
.
size
();
++
i
)
{
crope
feature
,
cost
;
if
(
split_two
(
parsed_line
[
i
],
':'
,
feature
,
cost
,
"0"
)
!=
0
)
{
ptop_error
(
"Bad node line, no cost for feature: "
<<
feature
<<
"."
)
;
}
double
gcost
;
if
(
sscanf
(
cost
.
c_str
()
,
"%lg"
,
&
g
cost
)
!=
1
)
{
ptop_error
(
"Bad node line, bad cost: "
<<
gcost
<<
"."
);
g
cost
=
0
;
/* Either end of line or - . Read in features */
while
((
scur
=
strsep
(
&
snext
,
" "
))
!=
NULL
)
{
char
*
feature
=
scur
;
double
icost
;
char
*
t
;
t
=
strsep
(
&
feature
,
":"
);
string
sfeat
(
t
)
;
if
(
(
!
feature
)
||
sscanf
(
feature
,
"%lg"
,
&
i
cost
)
!=
1
)
{
fprintf
(
stderr
,
"Bad cost specifier for %s
\n
"
,
t
);
i
cost
=
0
.01
;
}
p
->
features
[
feature
]
=
g
cost
;
PG
[
no1
].
features
.
insert
(
sfeat
,
i
cost
)
;
}
pname2vertex
[
name
]
=
pv
;
/* Done */
if
(
!
isswitch
)
pnodes
[
n
++
]
=
no1
;
pname2node
.
insert
(
s
,
no1
);
}
}
else
if
(
command
.
compare
(
"link"
)
==
0
)
{
if
(
parsed_line
.
size
()
<
7
)
{
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
]
<<
"."
);
penalty
=
1.0
;
}
else
if
(
!
strncmp
(
inbuf
,
"link"
,
4
))
{
if
(
sscanf
(
inbuf
,
"link %s %s %s %d %d"
,
lname
,
n1
,
n2
,
&
size
,
&
num
)
!=
5
)
{
fprintf
(
stderr
,
"bad link line: %s
\n
"
,
inbuf
);
}
else
{
string
linkname
(
lname
);
char
*
snode
,
*
smac
;
char
*
dnode
,
*
dmac
;
smac
=
n1
;
dmac
=
n2
;
snode
=
strsep
(
&
smac
,
":"
);
dnode
=
strsep
(
&
dmac
,
":"
);
if
(
pname2node
.
lookup
(
snode
)
==
nil
)
{
fprintf
(
stderr
,
"PTOP error: Unknown source node %s
\n
"
,
snode
);
exit
(
1
);
}
}
#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
;
if
(
pname2node
.
lookup
(
dnode
)
==
nil
)
{
fprintf
(
stderr
,
"PTOP error: Unknown destination node %s
\n
"
,
dnode
);
exit
(
1
);
}
}
#endif
#ifdef FIX_PLINK_ENDPOINTS
bool
fixends
=
false
;
if
(
parsed_line
.
size
()
==
9
)
{
if
(
parsed_line
[
8
].
compare
(
"fixends"
)
==
0
)
{
fixends
=
true
;
}
}
#else
if
(
parsed_line
.
size
()
>
8
)
{
ptop_error
(
"Bad link line, too many arguments."
);
}
#endif
crope
name
=
parsed_line
[
1
];
crope
src
,
srcmac
;
split_two
(
parsed_line
[
2
],
':'
,
src
,
srcmac
,
"(null)"
);
crope
dst
,
dstmac
;
split_two
(
parsed_line
[
3
],
':'
,
dst
,
dstmac
,
"(null)"
);
crope
bw
=
parsed_line
[
4
];
crope
delay
=
parsed_line
[
5
];
crope
loss
=
parsed_line
[
6
];
int
ibw
,
idelay
;
double
gloss
;
if
((
sscanf
(
bw
.
c_str
(),
"%d"
,
&
ibw
)
!=
1
)
||
(
sscanf
(
delay
.
c_str
(),
"%d"
,
&
idelay
)
!=
1
)
||
(
sscanf
(
loss
.
c_str
(),
"%lg"
,
&
gloss
)
!=
1
))
{
ptop_error
(
"Bad link line, bad delay characteristics."
);
}
#define ISSWITCH(n) (n->types.find("switch") != n->types.end())
pvertex
srcv
=
pname2vertex
[
src
];
pvertex
dstv
=
pname2vertex
[
dst
];
tb_pnode
*
srcnode
=
get
(
pvertex_pmap
,
srcv
);
tb_pnode
*
dstnode
=
get
(
pvertex_pmap
,
dstv
);
for
(
int
cur
=
0
;
cur
<
num
;
++
cur
)
{
pedge
pe
=
(
add_edge
(
srcv
,
dstv
,
PG
)).
first
;
tb_plink
*
pl
=
new
tb_plink
();
put
(
pedge_pmap
,
pe
,
pl
);
pl
->
delay_info
.
bandwidth
=
ibw
;
pl
->
delay_info
.
delay
=
idelay
;
pl
->
delay_info
.
loss
=
gloss
;
pl
->
bw_used
=
0
;
pl
->
name
=
name
;
pl
->
emulated
=
0
;
pl
->
nonemulated
=
0
;
#ifdef FIX_PLINK_ENDPOINTS
pl
->
fixends
=
fixends
;
#endif
#ifdef PENALIZE_BANDWIDTH
pl
->
penalty
=
penalty
;
#endif
pl
->
type
=
tb_plink
::
PLINK_NORMAL
;
pl
->
srcmac
=
srcmac
;
pl
->
dstmac
=
dstmac
;
if
(
ISSWITCH
(
srcnode
)
&&
ISSWITCH
(
dstnode
))
{
if
(
cur
!=
0
)
{
cout
<<
"Warning: Extra links between switches will be ignored. ("
<<
name
<<
")"
<<
endl
;
}
else
{
svertex
src_switch
=
get
(
pvertex_pmap
,
srcv
)
->
sgraph_switch
;
svertex
dst_switch
=
get
(
pvertex_pmap
,
dstv
)
->
sgraph_switch
;
sedge
swedge
=
add_edge
(
src_switch
,
dst_switch
,
SG
).
first
;
tb_slink
*
sl
=
new
tb_slink
();
put
(
sedge_pmap
,
swedge
,
sl
);
sl
->
mate
=
pe
;
pl
->
type
=
tb_plink
::
PLINK_INTERSWITCH
;
node
node1
=
pname2node
.
access
(
snode
);
node
node2
=
pname2node
.
access
(
dnode
);
#define ISSWITCH(n) (PG[n].types.lookup("switch") != nil)
for
(
int
i
=
0
;
i
<
num
;
++
i
)
{
ed1
=
PG
.
new_edge
(
node1
,
node2
);
PG
[
ed1
].
bandwidth
=
size
;
PG
[
ed1
].
bw_used
=
0
;
PG
[
ed1
].
name
=
linkname
;
PG
[
ed1
].
emulated
=
0
;
PG
[
ed1
].
nonemulated
=
0
;
if
(
smac
)
PG
[
ed1
].
srcmac
=
string
(
smac
);
else
PG
[
ed1
].
srcmac
=
string
(
"(null)"
);
if
(
dmac
)
PG
[
ed1
].
dstmac
=
string
(
dmac
);
else
PG
[
ed1
].
dstmac
=
string
(
"(null)"
);
if
(
ISSWITCH
(
node1
)
&&
ISSWITCH
(
node2
))
{
if
(
i
!=
0
)
{
cout
<<
"Warning: Extra links between switches will be ignored."
<<
endl
;
}
edge
swedge
=
SG
.
new_edge
(
PG
[
node1
].
sgraph_switch
,