edge.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:19k
- /*
- * Copyright (c) 1991,1993 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the Computer Systems
- * Engineering Group at Lawrence Berkeley Laboratory.
- * 4. Neither the name of the University nor of the Laboratory may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#) $Header: /cvsroot/nsnam/nam-1/edge.cc,v 1.54 2003/10/11 22:56:49 xuanc Exp $ (LBL)
- */
- #include <tclcl.h>
- #include "config.h"
- #include "sincos.h"
- #include "edge.h"
- #include "queuehandle.h"
- #include "node.h"
- #include "packet.h"
- #include "view.h"
- #include "netview.h"
- #include "psview.h"
- #include "transform.h"
- #include "paint.h"
- #include "monitor.h"
- #include "agent.h"
- #include "lossmodel.h"
- //----------------------------------------------------------------------
- // Wrapper for tcl creation of Edges (links)
- //----------------------------------------------------------------------
- static class EdgeClass : public TclClass {
- public:
- EdgeClass() : TclClass("Edge") {}
- TclObject * create(int argc, const char*const* argv) {
- // set <Edge> [new Node node_id type size]
- Edge * edge;
- double bandwidth, delay, length, angle, label_size;
- bandwidth = strtod(argv[4], NULL);
- delay = strtod(argv[5], NULL);
- length = strtod(argv[6], NULL);
- angle = strtod(argv[7], NULL);
- label_size = strtod(argv[8], NULL);
- edge = new Edge(label_size, bandwidth, delay, length, angle);
- return edge;
- }
- } class_edge;
- //----------------------------------------------------------------------
- // Edge::Edge(double ps, double bw, double delay,
- // double length, double angle)
- // - Creates an edge that is not attached to any nodes.
- // Used by nam editor when loading in an existing enam file.
- // - With this constructor, the nodes need to be added
- // to this edge using Edge::attachNodes()
- //----------------------------------------------------------------------
- Edge::Edge(double ps, double bw, double delay,
- double length, double angle) :
- Animation(0,0) {
- psize_ = ps;
- angle_ = angle;
- bandwidth_ = bw;
- delay_ = delay;
- length_ = length;
- state_ = UP;
- paint_ = Paint::instance()->thick();
-
- setupDefaults();
- }
- //----------------------------------------------------------------------
- // Edge::Edge(Node* src, Node* dst, double ps, double bw,
- // double delay, double length, double angle)
- // - creates an edge which is a one way network link
- // - the edge is automaticall attached to nodes src and dst
- //----------------------------------------------------------------------
- Edge::Edge(Node * src, Node * dst, double ps, double bw,
- double _delay, double length, double angle) :
- Animation(0,0),
- psize_(ps),
- angle_(angle),
- bandwidth_(bw),
- delay_(_delay),
- length_(length) {
- setupDefaults();
- src_ = src->num();
- dst_ = dst->num();
- start_ = src;
- neighbor_ = dst;
- paint_ = Paint::instance()->thick();
- if (length_ == 0) {
- length_ = delay_;
- }
- }
- //----------------------------------------------------------------------
- // Edge::Edge(Node* src, Node* dst, double ps, double bw,
- // double delay, double length, double angle, int ws)
- // - creates an edge for wireless
- //----------------------------------------------------------------------
- Edge::Edge(Node* src, Node* dst, double ps,
- double bw, double _delay, double length, double angle, int ws) :
- Animation(0,0),
- psize_(ps),
- angle_(angle),
- bandwidth_(bw),
- delay_(_delay),
- length_(length),
- wireless_(ws)
- {
- setupDefaults();
- src_ = src->num();
- dst_ = dst->num();
- start_ = src;
- neighbor_ = dst;
- paint_ = Paint::instance()->thick();
- if (length_ == 0) {
- length_ = delay_;
- }
- }
- //----------------------------------------------------------------------
- // void
- // Edge::setupDefaults()
- //----------------------------------------------------------------------
- void
- Edge::setupDefaults() {
- x0_ = 0.0;
- y0_ = 0.0;
- state_ = UP;
- packets_ = NULL;
- no_of_packets_ = 0;
- last_packet_ = NULL;
- marked_ = 0;
- visible_ = 1;
- dlabel_ = NULL;
- dcolor_ = NULL;
- direction_ = 0;
- used_ = 0;
-
- // Set initial (x0,y0), (x1,y1) so that they reflect the current
- // angle. This enables netmodel to share the same placeEdge() and
- // placeAgent() with AutoNetModel.
- SINCOSPI(angle_, &x1_, &y1_);
- lossmodel_ = NULL;
- queue_handle_ = NULL;
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- Edge::~Edge() {
- if (queue_handle_) {
- delete queue_handle_;
- }
- }
- //----------------------------------------------------------------------
- // void
- // Edge::attachNodes(Node * source, Node * destination)
- //----------------------------------------------------------------------
- void
- Edge::attachNodes(Node * source, Node * destination) {
- src_ = source->num();
- dst_ = destination->num();
- start_ = source;
- neighbor_ = destination;
- if (length_ == 0) {
- length_ = delay_;
- }
- start_->add_link(this);
- }
- //----------------------------------------------------------------------
- // void
- // Edge::addLossModel(LossModel * lossmodel)
- //----------------------------------------------------------------------
- void
- Edge::addLossModel(LossModel * lossmodel) {
- if (!lossmodel_) {
- lossmodel_ = lossmodel;
- lossmodel_->attachTo(this);
- lossmodel_->place();
- }
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- LossModel *
- Edge::getLossModel() {
- return lossmodel_;
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- void
- Edge::clearLossModel() {
- // Delete previous loss model if it exists
- if (lossmodel_) {
- lossmodel_ = NULL;
- }
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- void
- Edge::addQueueHandle(QueueHandle * q_handle) {
- queue_handle_ = q_handle;
- queue_handle_->place();
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- float Edge::distance(float x, float y) const
- {
- // TODO: Look it up when back home...
- matrix_.imap(x, y);
- return y;
- }
- //----------------------------------------------------------------------
- // inline double
- // Edge::delay() const
- // - delay_ is stored in milliseconds
- // - this function returns the delay in seconds
- //
- // - look at tcl/netModel.tcl layout_link and layout_lan
- // for the conversion to milliseconds
- //
- // - delay_ is kept in milliseconds so that Edge::info()
- // is displayed in millseconds and so that delay can be
- // entered in milliseconds by the nam editor
- //
- //----------------------------------------------------------------------
- double
- Edge::delay() const {
- return (delay_/1000.0);
- }
- void Edge::init_color(const char *clr)
- {
- color(clr);
- dcolor(clr);
- oldPaint_ = paint_;
- }
- void Edge::set_down(char *color)
- {
- // If current color is down, don't change it again.
- // Assuming only one down color. User can change this behavior
- // by adding tcl code for link-up and link-down events.
- if (state_ == UP) {
- int pno = Paint::instance()->lookup(color, 3);
- oldPaint_ = paint_;
- paint_ = pno;
- state_ = DOWN;
- }
- }
- void Edge::set_up()
- {
- if (state_ == DOWN) {
- state_ = UP;
- toggle_color();
- }
- }
- void Edge::place(double x0, double y0, double x1, double y1)
- {
- x0_ = x0;
- y0_ = y0;
- x1_ = x1;
- y1_ = y1;
- double dx = x1 - x0;
- double dy = y1 - y0;
- /*XXX*/
- // delay should not be equal to edge's position
- // delay_ = sqrt(dx * dx + dy * dy);
- matrix_.clear();
- matrix_.rotate((180 / M_PI) * atan2(dy, dx));
- matrix_.translate(x0, y0);
- if (x1>x0) {
- bb_.xmin = x0; bb_.xmax = x1;
- } else {
- bb_.xmin = x1; bb_.xmax = x0;
- }
- if (y1>y0) {
- bb_.ymin = y0; bb_.ymax = y1;
- } else {
- bb_.ymin = y1; bb_.ymax = y0;
- }
- eb_.xmin = -0.1 * start_->size();
- eb_.xmax = sqrt(dx*dx+dy*dy) + 0.1*neighbor_->size();
- eb_.ymin = -0.1 * start_->size();
- eb_.ymax = 0.1 * start_->size();
- if (queue_handle_) {
- queue_handle_->place();
- }
- if (lossmodel_) {
- lossmodel_->place();
- }
- }
- void Edge::AddPacket(Packet *p)
- {
- p->next(packets_);
- if (packets_!=NULL)
- packets_->prev(p);
- p->prev(NULL);
- packets_=p;
- if (last_packet_==NULL)
- last_packet_=p;
- no_of_packets_++;
- #define PARANOID
- #ifdef PARANOID
- int ctr=0;
- for(Packet *tp=packets_;tp!=NULL;tp=tp->next()) {
- ctr++;
- if (ctr>no_of_packets_)
- abort();
- }
- if (last_packet_->next()!=NULL)
- abort();
- #ifdef DEBUG
- printf("AddPacket: %d->%d OKn", src_, dst_);
- #endif
- #endif
- #undef PARANOID
- }
- void Edge::arrive_packet(Packet *p, double atime)
- {
- /*Trigger any arrival event at the node*/
- neighbor_->arrive_packet(p, this, atime);
- }
- void Edge::DeletePacket(Packet *p)
- {
- /*Trigger any deletion event at the node*/
- if (neighbor_) neighbor_->delete_packet(p);
- else return ;
- no_of_packets_--;
- if (last_packet_==p) {
- /*Normal case - it's the last packet*/
- last_packet_ = p->prev();
- if (packets_!=p)
- p->prev()->next(NULL);
- else
- packets_=NULL;
- } else {
- /*Abnormal case - need to search the list*/
- Packet *tp;
- tp=packets_;
- while((tp!=p)&&(tp!=NULL)) {
- tp=tp->next();
- }
- if (tp==p) {
- if (tp==packets_)
- /*it was the first packet*/
- packets_=tp->next();
- else
- tp->prev()->next(tp->next());
- if (tp==last_packet_) {
- /*this shouldn't ever happen*/
- fprintf(stderr, "**it happenedn");
- last_packet_=tp->prev();
- } else
- tp->next()->prev(tp->prev());
- }
- }
- #define PARANOID
- #ifdef PARANOID
- int ctr=0;
- for(Packet *tp=packets_;tp!=NULL;tp=tp->next()) {
- ctr++;
- if (ctr>no_of_packets_) abort();
- }
- if ((last_packet_!=NULL)&&(last_packet_->next()!=NULL)) abort();
- #ifdef DEBUG
- printf("DeletePacket: %d->%d OKn", src_, dst_);
- #endif
- #endif
- #undef PARANOID
- }
- void Edge::dlabel(const char* name)
- {
- if (name[0] == 0) {
- if (dlabel_) {
- delete []dlabel_;
- dlabel_ = 0;
- }
- return;
- }
- if (dlabel_)
- delete []dlabel_;
- dlabel_ = new char[strlen(name) + 1];
- strcpy(dlabel_, name);
- }
- void Edge::dcolor(const char* name)
- {
- if (name[0] == 0) {
- if (dcolor_) {
- delete []dcolor_;
- dcolor_ = 0;
- }
- return;
- }
- if (dcolor_)
- delete []dcolor_;
- dcolor_ = new char[strlen(name) + 1];
- strcpy(dcolor_, name);
- }
- void Edge::direction(const char* name)
- {
- if (name[0] == 0) {
- if (direction_)
- direction_ = 0;
- return;
- }
- if (!strcmp(name, "SOUTH")) direction_ = 1;
- else if (!strcmp(name, "NORTH")) direction_ = 2;
- else if (!strcmp(name, "EAST")) direction_ = 3;
- else if (!strcmp(name, "WEST")) direction_ = 4;
- else direction_ = 2;
- }
- void Edge::draw(View* view, double now) {
- if (visible()) {
- view->line(x0_, y0_, x1_, y1_, paint_);
- }
- if (monitor_!=NULL)
- monitor_->draw(view, (x0_+x1_)/2, (y0_+y1_)/2);
- if (dlabel_ == 0)
- return;
- // Draw dynamic label
- switch (direction_) {
- case 0:
- view->string((x0_+x1_)/2.0, (y0_+y1_)/2.0+psize_*1.5,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- case 1:
- view->string((x0_+x1_)/2.0, (y0_+y1_)/2.0-psize_*1.5,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- case 2:
- view->string((x0_+x1_)/2.0, (y0_+y1_)/2.0+psize_*1.5,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- case 3:
- view->string((x0_+x1_)/2.0-psize_*1.5, (y0_+y1_)/2.0,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- case 4:
- view->string((x0_+x1_)/2.0+psize_*1.5, (y0_+y1_)/2.0,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- default:
- view->string((x0_+x1_)/2.0, (y0_+y1_)/2.0+psize_*1.5,
- psize_*2.3, dlabel_, direction_, dcolor_);
- break;
- }
- }
- void Edge::reset(double)
- {
- // paint_ = Paint::instance()->thick();
- no_of_packets_=0;
- packets_=NULL;
- last_packet_=NULL;
- }
- int Edge::inside(double, float px, float py) const
- {
- // matrix_.imap(px, py);
- // return eb_.inside(px, py);
- return inside(px, py);
- }
- int Edge::inside(float px, float py) const
- {
- matrix_.imap(px, py);
- return eb_.inside(px, py);
- }
- const char* Edge::info() const
- {
- static char text[128];
- sprintf(text, "Link: %d<->%dn Bandwidth: %g Mbits/secn Delay: %g msn",
- src_, dst_, bandwidth_, delay_);
- return (text);
- }
- const char* Edge::property() {
- rgb *color;
- color=Paint::instance()->paint_to_rgb(paint_);
-
- static char text[256];
- char *p;
-
- // object type and id
- p = text;
- if (!wireless_) {
- sprintf(text, "{"Link %d-%d" title title "Link %d-%d"} ",
- src_, dst_, src_, dst_);
- } else {
- sprintf(text, "{"Wireless Link %d-%d" title title "Wireless Link %d-%d"} ",
- src_, dst_, src_, dst_);
- }
- p = &text[strlen(text)];
- sprintf(p, "{Color color_ color %s} ", color->colorname); // color & value
- // label
- p = &text[strlen(text)];
- if (dlabel_) {
- sprintf(p, "{Label dlabel_ text %s} ", dlabel_);
- } else {
- sprintf(p, "{Label dlabel_ text } ");
- }
-
- //p = &text[strlen(text)];
- //sprintf(p, "{LABEL-DIRECTION %d} ", direction_); // label-direction $ value
-
- // Link Bandwidth
- p = &text[strlen(text)];
- sprintf(p, "{"Bandwidth (Mbits per second)" bandwidth_ text %-f} ", bandwidth_);
- // Link Delay
- p = &text[strlen(text)];
- sprintf(p, "{"Delay (ms)" delay_ text %-f} ", delay_);
- return(text);
- }
- const char* Edge::getname() const
- {
- static char text[128];
- sprintf(text, "l %d %d",
- src_, dst_);
- return (text);
- }
- void Edge::monitor(Monitor *m, double /*now*/, char *result, int /*len*/)
- {
- monitor_=m;
- sprintf(result, "link %d-%d:n bw: %g Mbits/secn delay: %g ms",
- src_, dst_, bandwidth_, delay_);
- return;
- }
- int Edge::save(FILE *file)
- {
- rgb *color;
- color=Paint::instance()->paint_to_rgb(paint_);
- char state[10];
- double angle,length;
- float dx,dy;
- //Edges in the tracefile are bidirectional, so don't need to save
- //both unidirectional edges
- if (src_>dst_) return 0;
- if (state_==UP)
- strcpy(state, " -S UP");
- else if (state_==DOWN)
- strcpy(state, " -S DOWN");
- else
- state[0]=' ';
- if (angle_<0)
- angle=180*(angle_+2*M_PI)/M_PI;
- else
- angle=180*(angle_/M_PI);
- dx=x0_-x1_;
- dy=y0_-y1_;
- length=sqrt(dx*dx+dy*dy);
- // printf("%d->%d, angle=%f (%fdeg)n", src_, dst_, angle_, angle);
- fprintf(file, "l -t * -s %d -d %d -r %f -D %f -c %s -o %.1fdeg -l %f%sn",
- src_, dst_, bandwidth_, delay_, color->colorname,angle, length, state);
- return 0;
- }
- int Edge::saveAsEnam(FILE *file)
- {
- rgb *color;
- color=Paint::instance()->paint_to_rgb(paint_);
- char state[10];
- double angle,length;
- float dx,dy;
- // XXX Should never set edge size outside scale_estimate()!!!!
- // psize_ = 25.0;
- // Edges in the tracefile are bidirectional, so don't need to save
- // both unidirectional edges
- if (src_>dst_) return 0;
-
- if (state_==UP)
- strcpy(state, " -S UP");
- else if (state_==DOWN)
- strcpy(state, " -S DOWN");
- else
- state[0]=' ';
- if (angle_<0)
- angle=180*(angle_+2*M_PI)/M_PI;
- else
- angle=180*(angle_/M_PI);
- dx=x0_-x1_;
- dy=y0_-y1_;
- length=sqrt(dx*dx+dy*dy);
- // printf("%d->%d, angle=%f (%fdeg)n", src_, dst_, angle_, angle);
- fprintf(file, "##l -t * -s %d -d %d -r %f -D %f -c %s -o %.1fdeg -l %f%s -b %sn",
- src_, dst_, bandwidth_, delay_, color->colorname,angle, length, state, dlabel_);
- return 0;
- }
- //----------------------------------------------------------------------
- // int
- // Edge::writeNsScript(FILE *file)
- // - Edges in the tracefile are bidirectional, so don't need to save
- // both unidirectional edges
- //----------------------------------------------------------------------
- int
- Edge::writeNsScript(FILE *file) {
- rgb *color;
- double angle,length;
- float dx,dy;
- color = Paint::instance()->paint_to_rgb(paint_);
- if (angle_ < 0) {
- angle = 180 * (angle_ + 2 * M_PI) / M_PI;
- } else {
- angle = 180 * (angle_ / M_PI);
- }
- dx = x0_ - x1_;
- dy = y0_ - y1_;
- length = sqrt(dx * dx + dy * dy);
- // Create the link
- if (queue_handle_) {
- //fprintf(file, "$ns simplex-link $node(%d) $node(%d) %f %f DropTailn",
- fprintf(file, "$ns simplex-link $node(%d) $node(%d) %fMb %fms %sn",
- src_, dst_, bandwidth_, delay_, queue_handle_->name());
- } else {
- fprintf(file, "$ns simplex-link $node(%d) $node(%d) %fMb %fms DropTailn",
- src_, dst_, bandwidth_, delay_);
- }
- // Add a packet queue
- fprintf(file, "$ns simplex-link-op $node(%d) $node(%d) queuePos 0.5n",
- src_, dst_);
- // Set different options for the link
- // - Color
- fprintf(file, "$ns simplex-link-op $node(%d) $node(%d) color %sn",
- src_, dst_, color->colorname);
- // - Orientation
- fprintf(file, "$ns simplex-link-op $node(%d) $node(%d) orient %.1fdegn",
- src_, dst_, angle);
-
- if (dlabel_){
- // - label
- fprintf(file, "$ns simplex-link-op $node(%d) $node(%d) label %sn",
- src_, dst_, dlabel_);
- }
- if (direction_!=0) {
- // - label orientation
- fprintf(file, "$ns simplex-link-op $node(%d) $node(%d) label-at %dn",
- src_, dst_, direction_);
- }
- if (queue_handle_) {
- queue_handle_->writeNsScript(file);
- }
- fprintf(file, "n");
- return 0;
- }