Commit 0c5fa30e authored by Christopher Alfeld's avatar Christopher Alfeld

Initial files for hardwired version of assign.

These are not yet usable and are here for revision control and backup.
parent ad4d26af
class tb_type {
public:
char *name;
int max;
};
const int MAX_PNODES = 1024; // maximum # of physical nodes
typedef enum {TYPE_UNKNOWN, TYPE_PC, TYPE_DNARD, TYPE_DELAY, TYPE_DELAY_PC,
TYPE_SWITCH} nodeType;
enum {MAX_TYPES = 5};
/*
* parse ptop files. These are basic topologies
* that are used to represent the physical topology.
*
* format:
* node <name> <type> [<type2> ...]
* <type> = pc | switch | dnard
* link <src> <dst> <size> <number>
*/
#include <LEDA/graph_alg.h>
#include <LEDA/graphwin.h>
#include <LEDA/dictionary.h>
#include <LEDA/map.h>
#include <LEDA/graph_iterator.h>
#include <iostream.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "physical.h"
extern node pnodes[MAX_PNODES]; // int -> node map
extern tb_pgraph PG; // physical graph
void parse_ptop(tb_pgraph &G, istream& i)
{
dictionary<string, node> nmap;
node no1;
edge ed1;
string s1, s2;
char inbuf[255];
char n1[32], n2[32];
int size, num;
int n=0;
int j;
char *snext;
char *snode;
char *scur;
int isswitch;
while (!i.eof()) {
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 {
scur = strsep(&snext," ");
snode = scur;
string s(snode);
no1 = PG.new_node();
PG[no1].name=strdup(snode);
PG[no1].current_type = TYPE_UNKNOWN;
PG[no1].max_load = 0;
PG[no1].current_load = 0;
PG[no1].pnodes_used=0;
for (j = 0 ; j < MAX_TYPES; ++j) {
PG[no1].types[j].name = NULL;
PG[no1].types[j].max = 0;
}
while ((scur = strsep(&snext," ")) != NULL) {
if (strcmp(scur,"pc") == 0) {
PG[no1].types[TYPE_PC].name = "pc";
PG[no1].types[TYPE_PC].max = 1;
} else if (strcmp(scur,"dnard") == 0) {
// XXX
PG[no1].types[TYPE_DNARD].name = "dnard";
PG[no1].types[TYPE_DNARD].max = 0;
} else if (strcmp(scur,"delay") == 0) {
// XXX - add detection of max based on # of links
PG[no1].types[TYPE_DELAY].name = "pc";
PG[no1].types[TYPE_DELAY].max = 2;
} else if (strcmp(scur,"delay_pc") == 0) {
// this is an unsuported type. Have types of both
// delay and pc.
fprintf(stderr,"Unsupported type: delay_pc\n");
} else if (strcmp(scur,"switch") == 0) {
isswitch = 1;
PG[no1].types[TYPE_SWITCH].name = "switch";
PG[no1].types[TYPE_SWITCH].max = 1;
PG[no1].the_switch = no1;
}
}
if (! isswitch)
pnodes[n++]=no1;
nmap.insert(s, no1);
}
}
else if (!strncmp(inbuf, "link", 4)) {
if (sscanf(inbuf, "link %s %s %d %d", n1, n2, &size, &num)
!= 4) {
fprintf(stderr, "bad link line: %s\n", inbuf);
} else {
string s1(n1);
string s2(n2);
node node1 = nmap.access(s1);
node node2 = nmap.access(s2);
for (int i = 0; i < num; ++i) {
ed1=PG.new_edge(node1, node2);
PG[ed1].bandwidth=size;
PG[ed1].bw_used=0;
PG[ed1].users=0;
}
#define ISSWITCH(n) (PG[n].types[TYPE_SWITCH].max == 1)
if (ISSWITCH(node1) &&
! ISSWITCH(node2))
PG[node2].the_switch = node1;
else if (ISSWITCH(node2) &&
! ISSWITCH(node1))
PG[node1].the_switch = node2;
}
} else {
fprintf(stderr, "unknown directive: %s\n", inbuf);
}
}
}
/*
* Parse chris' ".top" file format into a LEDA graph
*/
#include <iostream.h>
#include <string.h>
#include <stdio.h>
#include <LEDA/graph_alg.h>
#include <LEDA/graphwin.h>
#include <LEDA/dictionary.h>
#include <LEDA/map.h>
#include <LEDA/graph_iterator.h>
#include "common.h"
#include "virtual.h"
void parse_top(tb_vgraph &G, istream& i)
{
dictionary<string, node> nmap;
node no1;
string s1, s2;
char inbuf[255];
char n1[32], n2[32], type[32];
while (!i.eof()) {
char *ret;
i.getline(inbuf, 254);
ret = strchr(inbuf, '\n');
if (ret) *ret = 0;
if (strlen(inbuf) == 0) { continue; }
if (!strncmp(inbuf, "node", 4)) {
if (sscanf(inbuf, "node %s %s", n1, type) < 1) {
fprintf(stderr, "bad node line: %s\n", inbuf);
} else {
string s1(n1);
no1 = G.new_node();
G[no1].name=strdup(n1);
G[no1].posistion = 0;
G[no1].no_connections=0;
nmap.insert(s1, no1);
if (!strcmp(type, "delay")) {
G[no1].type = TYPE_DELAY;
}
else if (!strcmp(type, "pc")) {
G[no1].type = TYPE_PC;
}
else if (!strcmp(type, "switch")) {
fprintf(stderr,"Can not have switch's in top file\n");
G[no1].type = TYPE_UNKNOWN;
}
else if (!strcmp(type, "dnard")) {
G[no1].type = TYPE_DNARD;
}
else {
fprintf(stderr,"Unknown type in top file: %s\n",type);
G[no1].type = TYPE_UNKNOWN;
}
}
}
else if (!strncmp(inbuf, "link", 4)) {
if (sscanf(inbuf, "link %s %s", n1, n2) != 2) {
fprintf(stderr, "bad link line: %s\n", inbuf);
} else {
string s1(n1);
string s2(n2);
edge e;
node node1 = nmap.access(s1);
node node2 = nmap.access(s2);
e = G.new_edge(node1, node2);
// XXX - add more bandwidth code
G[e].bandwidth = 10;
G[e].type = tb_vlink::LINK_UNKNOWN;
G[e].plink = NULL;
G[e].plink_two = NULL;
}
}
else {
fprintf(stderr, "unknown directive: %s\n", inbuf);
}
}
}
class tb_pnode {
public:
friend ostream &operator<<(ostream &o, const tb_pnode& node)
{
o << "TBNode: " << node.name << endl;
return o;
}
friend istream &operator>>(istream &i, const tb_pnode& node)
{
return i;
}
tb_pnode();
tb_type types[MAX_TYPES]; // array of types, with counts of max
nodeType current_type; // the current type of the node
int max_load; // maxmium load for current type
int current_load; // how many vnodes are assigned to this pnode
// int index; // index for switches
char *name;
node the_switch; // the switch the node is attached to
int pnodes_used; // for switch nodes
};
class tb_plink {
public:
friend ostream &operator<<(ostream &o, const tb_plink& edge)
{
o << "unimplemeted ostream << for tb_plinke " << endl;
return o;
}
friend istream & operator>>(istream &i, const tb_plink& edge)
{
return i;
}
int bandwidth; // maximum bandwidth of this link
int bw_used; // how much is used
int users; // number of users in direct links
};
class tb_route {
public:
private:
int length;
list<tb_plink> links;
};
typedef GRAPH<tb_pnode,tb_plink> tb_pgraph;
/*
* ASSUMPTIONS:
* 1. Any switch can get to any other switch either directly
* or via at most one other switch (star formation).
*/
// Not sure we need all these LEDA includes.
#include <LEDA/graph_alg.h>
#include <LEDA/graphwin.h>
#include <LEDA/dictionary.h>
#include <LEDA/map.h>
#include <LEDA/graph_iterator.h>
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include "common.h"
#include "score.h"
#include "virtual.h"
#include "physical.h"
#include "assert.h"
#define ASSERT assert
float score; // The score of the current mapping
int violated; // How many times the restrictions
// have been violated.
node pnodes[MAX_PNODES]; // int->node map
// pnodes[0] == NULL
extern tb_vgraph G; // virtual graph
extern tb_pgraph PG; // physical grpaph
int find_interswitch_path(node src,node dst,int bandwidth,edge *f,edge *s);
edge *direct_link(node a,node b);
/*
* init_score()
* This initialized the scoring system. It also clears all
* assignments.
*/
void init_score()
{
score=0;
violated=0;
node n;
edge e;
forall_nodes(n,G) {
tb_vnode &vn=G[n];
vn.posistion=0;
vn.no_connections=0;
score += SCORE_UNASSIGNED;
violations++;
}
forall_edges(e,G) {
tb_vlink &ve=G[e];
ve.type=tb_vlink::LINK_UNKNOWN;
}
forall_nodes(n,PG) {
tb_pnode &pn=PG[n];
pn.current_type=TYPE_UNKNOWN;
pn.current_load=0;
pn.pnodes_used=0;
}
forall_edges(e,PG) {
tb_plink &pe=PG[e];
pe.bw_used=0;
pe.users=0;
}
ASSERT(pnodes[0] == NULL);
}
/*
* void remove_node(node node)
* This removes a virtual node from the assignments, adjusting
* the score appropriately.
*/
void remove_node(node n)
{
/* Find pnode assigned to */
node pnode;
tb_vnode &vnoder = G[n];
pnode = pnodes[vnoder.posistion];
tb_pnode &pnoder = PG[pnode];
ASSERT(pnode != NULL);
edge e;
tb_vlink *vlink;
node vdst;
tb_vnode *vdstr;
node pdst;
tb_pnode *pdstr;
// remove the scores associated with each edge
forall_inout_edges(e,n) {
vlink=&G[e];
vdst=G.target(e);
if (vdst == n)
vdst = G.source(e);
vdstr=&G[vdst];
if (vlink->type == tb_vlink::LINK_DIRECT) {
// DIRECT LINK
PG[vlink->plink].users--;
if (PG[vlink->plink].users == 0) {
// link no longer used
score -= SCORE_DIRECT_LINK;
} else {
// getting close to no violations
score -= SCORE_DIRECT_LINK_PENALTY;
violated--;
}
} else if (vlink->type == tb_vlink::LINK_INTERSWITCH) {
// INTERSWITCH LINK
pdst=pnodes[vdstr->posistion];
pdstr=&PG[pdst];
edge first,second;
first = vlink->plink;
second = vlink->plink_two;
// remove bandwidth from edges
PG[first].bw_used -= vlink->bandwidth;
if (second)
PG[second].bw_used -= vlink->bandwidth;
// XXX add check for over bandwidth
// adjust score apropriately.
score -= SCORE_INTERSWITCH_LINK;
if (second)
score -= SCORE_INTERSWITCH_LINK;
} else {
// INTRASWITCH LINK
ASSERT(vlink->type == tb_vlink::LINK_INTRASWITCH);
score -= SCORE_INTRASWITCH_LINK;
}
}
// remove scores associated with the node
score -= SCORE_NO_CONNECTION * vnoder.no_connections;
violated -= vnoder.no_connections;
// adjust pnode scores
pnoder.current_load--;
if (pnoder.current_load == 0) {
// release pnode
score -= SCORE_PNODE;
node the_switch =pnoder.the_switch;
if ((PG[the_switch].pnodes_used--) == 0) {
// release switch
score -= SCORE_SWITCH;
}
// revert pnode type
pnoder.current_type=TYPE_UNKNOWN;
} else if (pnoder.current_load >= pnoder.max_load) {
score -= SCORE_PNODE_PENALTY;
violated--;
}
// add score for unassigned node
score += SCORE_UNASSIGNED;
violated++;
}
/*
* int add_node(node node,int ploc)
* Add a mapping of node to ploc and adjust score appropriately.
* Returns 1 in the case of an incompatible mapping. This should
* never happen as the same checks should be in place in a higher
* level. (Optimization?)
*/
int add_node(node n,int ploc)
{
tb_vnode &vnoder=G[n];
node pnode = pnodes[ploc];
tb_pnode &pnoder=PG[pnode];
// set up pnode
// figure out type
if (pnoder.current_type != TYPE_UNKNOWN) {
return 1;
}
// !!!: This code could be improved
// Hard code types to ints for efficiency?
// Remove check assuming at higher level?
// Remove higher level checks?
// XXX fix this.
#if 0
pnoder.max_load=0;
for (int i=0;i<MAX_TYPES;++i) {
if (pnoder.types[i] &&
strcmp(pnoder.types[i].name,n->type.name) == 0) {
pnoder.current_type=i;
pnoder.max_load=pnoder.types[i].max;
break;
}
}
#endif
if (pnoder.max_load == 0) {
// didn't find a type
return 1;
}
// set up links
vnoder.no_connections=0;
edge e;
node dst;
tb_vlink *er;
tb_plink *pl;
edge *pedge;
forall_inout_edges(e,n) {
dst=G.source(e);
er=&G[e];
if (dst == n) {
dst=G.target(e);
}
tb_vnode &dstr=G[dst];
if (dstr.posistion != 0) {
// dstr is assigned
node dpnode=pnodes[dstr.posistion];
tb_pnode &dpnoder=PG[pnode];
// XXX - choose method of getting there and set up links
// XXX - this is all wrong, need to distirnguish between
// plinks and vlinks. AAAA!!!
// XXX - 5/00 - Really need to write thise code.
if ((pedge=direct_link(dpnode,pnode)) != NULL) {
pl = &PG[*pedge];
// direct
er->type = tb_vlink::LINK_DIRECT;
er->plink = *pedge;
pl->users++;
if (pl->users == 1) {
score += SCORE_DIRECT_LINK;
} else {
score += SCORE_DIRECT_LINK_PENALTY;
violated++;
}
} else if (pnoder.the_switch == dpnoder.the_switch) {
// intraswitch
er->type = tb_vlink::LINK_INTRASWITCH;
score += SCORE_INTRASWITCH_LINK;
} else {
// try to find interswitch
edge first,second;
first=second=NULL;
if (find_interswitch_path(pnoder.the_switch,dpnoder.the_switch,
er->bandwidth,
&first,&second) == 0) {
// couldn't fidn path.
vnoder.no_connections++;
score += SCORE_NO_CONNECTION;
violated++;
} else {
er->type=tb_vlink::LINK_INTERSWITCH;
score += SCORE_INTERSWITCH_LINK;
if (second)
score += SCORE_INTERSWITCH_LINK;
// add bandwidth usage
PG[first].bw_used += er->bandwidth;
if (second)
PG[second].bw_used += er->bandwidth;
er->plink = first;
er->plink_two = second;
// XXX add checking for over bandwidth
}
}
}
}
// finish setting up pnode
pnoder.current_load++;
if (pnoder.current_load > pnoder.max_load) {
score += SCORE_PNODE_PENALTY;
violated++;
} else {
score += SCORE_PNODE;
if ((PG[pnoder.the_switch].pnodes_used++) == 1) {
score += SCORE_SWITCH;
}
}
// node no longer unassigned
score -= SCORE_UNASSIGNED;
violated--;
return 0;
}
// returns "best" direct link between a and b.
// best = less users
// break ties with minimum bw_used
edge *direct_link(node a,node b)
{
node dst;
edge e;
edge *best = NULL;
tb_plink *pl;
tb_plink *bestpl = NULL;
forall_inout_edges(e,a) {
dst=PG.target(e);
if (dst == a)
dst=PG.source(e);
if (dst == b) {
pl = &PG[e];
if (pl->users < bestpl->users ||
(pl->users == bestpl->users &&
pl->bw_used < bestpl->bw_used)) {
best = &e;
bestpl = pl;
}
}
}
return best;
}
// this needs to find a path between switches src and dst (in PG).
// needs to return the best of all possible
// best =
// shorter is better
// lowest % of bw used after link added is better.
int find_interswitch_path(node src,node dst,int bandwidth,edge *f,edge *s)
{
edge *best_first,*best_second;
float best_bw;
float bw;
best_bw=100.0;
best_first = best_second = NULL;
// try to find a path to the destination
node ldst,ldstb;
edge first,second;
forall_inout_edges(first,src) {
ldst = PG.target(first);
if (ldst == src)
ldst = PG.source(first);
if (ldst == dst) {
// we've found a path, it's just firstedge
if (first)
bw = (PG[first].bw_used+bandwidth)/PG[first].bandwidth;
if (! best_first || bw < best_bw) {
best_first = &first;
best_bw = bw;
best_second = NULL;
}
}
forall_inout_edges(second,ldst) {
ldstb = PG.target(second);
if (ldstb == ldst)
ldstb = PG.source(second);
if (ldstb == dst) {
if (! best_second) continue;
bw = (PG[first].bw_used+bandwidth)/PG[first].bandwidth;
if (second)
// NOTE: One thing to try differently.
bw *= (PG[second].bw_used+bandwidth)/PG[second].bandwidth;
if (bw < best_bw) {
best_first = &first;
best_second = &second;
best_bw = bw;
}
}
}
}
// if we get here we didn't find a path
if (best_first) {
*f = *best_first;
if (best_second)
*s = *best_second;
return 1;
} else {
return 0;
}
}
#ifndef _SCORE_H
#define _SCORE_H
// Cost of a direct link
const float SCORE_DIRECT_LINK = 0.01;
// Cost of overusing a direct link
const float SCORE_DIRECT_LINK_PENALTY = 0.5;
// Cost of an intraswitch link
const float SCORE_INTRASWITCH_LINK=0.02;
// Cost of an interswitch link
const float SCORE_INTERSWITCH_LINK=0.05;
// Cost of being unable to fulfill a virtual link
const float SCORE_NO_CONNECTION = 0.5;
// Cost of using a pnode
const float SCORE_PNODE = 0.05;
// Cost of overusing a pnode
const float SCORE_PNODE_PENALTY = 0.5;
// Cost of using a switch.
const float SCORE_SWITCH = 0.5;
// Cost of an unassigned node
const float SCORE_UNASSIGNED = 1;
extern float score;
extern int violations;
void init_score();
void remove_node(node n);
void add_node(node n);
#endif
class tb_vnode {
public:
int posistion; // index into pnode array
int no_connections; // how many unfulfilled connections from this node
nodeType type; // type of the node
char *name; // string name of the node
};
enum {LINK_DIRECT,LINK_INTRASWITCH,LINK_INTERSWITCH} tb_link_type;
class tb_plink;
class tb_vlink {
public:
typedef enum {LINK_UNKNOWN, LINK_DIRECT,
LINK_INTRASWITCH, LINK_INTERSWITCH} linkType;
int bandwidth; // how much bandwidth this uses
linkType type; // link type
edge plink; // plink this belongs to
edge plink_two; // second plink for INTRA and INTER links
};
typedef GRAPH<tb_vnode,tb_vlink> tb_vgraph;
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