//
// Copyright (c) 1997-2001 by the University of Southern California
// All rights reserved.
//
// Permission to use, copy, modify, and distribute this software and its
// documentation in source and binary forms for non-commercial purposes
// and without fee is hereby granted, provided that the above copyright
// notice appear in all copies and that both the copyright notice and
// this permission notice appear in supporting documentation. and that
// any documentation, advertising materials, and other materials related
// to such distribution and use acknowledge that the software was
// developed by the University of Southern California, Information
// Sciences Institute. The name of the University may not be used to
// endorse or promote products derived from this software without
// specific prior written permission.
//
// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
// the suitability of this software for any purpose. THIS SOFTWARE IS
// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Other copyrights might apply to parts of this software and are so
// noted when applicable.
//
// $Header: /cvsroot/nsnam/nam-1/enetmodel.cc,v 1.45 2003/10/11 22:56:50 xuanc Exp $
//
// Network model with Editor layout
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "random.h"
#include "view.h"
#include "netview.h"
#include "animation.h"
#include "queue.h"
#include "edge.h"
#include "node.h"
#include "agent.h"
#include "sincos.h"
#include "state.h"
#include "packet.h"
#include "enetmodel.h"
#include "trafficsource.h"
#include "queuehandle.h"
static int agent_number = 0;
class EditorNetworkModelClass : public TclClass {
public:
EditorNetworkModelClass() : TclClass("NetworkModel/Editor") {}
TclObject* create(int argc, const char*const* argv) {
if (argc < 5)
return 0;
return (new EditorNetModel(argv[4]));
}
} editornetworkmodel_class;
EditorNetModel::EditorNetModel(const char *editor) :
NetModel(editor) {
node_id_count = 0;
traffic_sources_ = NULL;
lossmodels_ = NULL;
queue_handles_ = NULL;
maximum_simulation_time_ = 30.0; // seconds
playback_speed_ = 2000.0; // default animation speed (in microseconds)
bind("Wpxmin_", &pxmin_);
bind("Wpymin_", &pymin_);
bind("Wpxmax_", &pxmax_);
bind("Wpymax_", &pymax_);
bind("maximum_simulation_time_", &maximum_simulation_time_);
}
EditorNetModel::~EditorNetModel()
{
}
void EditorNetModel::BoundingBox(BBox& bb)
{
// by default, 800X1000 internal drawing area
bb.xmin = pxmin_;
bb.ymin = pymin_;
bb.xmax = pxmax_;
bb.ymax = pymax_;
for (Animation* a = drawables_; a != 0; a = a->next()) {
a->merge(bb);
}
pxmin_ = bb.xmin;
pymin_ = bb.ymin;
pxmax_ = bb.xmax;
pymax_ = bb.ymax;
}
//----------------------------------------------------------------------
// Node *
// EditorNetModel::addNode(Node * node)
//----------------------------------------------------------------------
Node *
EditorNetModel::addNode(Node * node) {
if (!lookupNode(node->num())) {
node->next_ = nodes_;
nodes_ = node;
node->Animation::insert(&drawables_);
return node;
}
return NULL;
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addNode(int node_id)
//----------------------------------------------------------------------
Node *
EditorNetModel::addNode(int node_id) {
Node * node = NULL;
static char name[TRACE_LINE_MAXLEN];
double size = 10.0; // This is the default node size taken from
// parser.cc under the 'n' animation event
sprintf(name, "%d", node_id);
node = new CircleNode(name, size);
node->init_color("black");
if (node_id_count <= node_id) {
node_id_count = node_id + 1;
}
if (!addNode(node)) {
delete node;
node = NULL;
}
return node;
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addNode(float cx, float cy)
// - Create a node using the specified name
// and the default size and insert it into this
// NetModel's list of drawables.
//----------------------------------------------------------------------
int
EditorNetModel::addNode(float cx, float cy) {
Node * node;
// Find the next node id number
if (node_id_count == 0 ) {
for (node = nodes_; node != 0; node = node->next_) {
if (node->num() > node_id_count) {
node_id_count = node->num();
}
}
node_id_count++;
}
node = addNode(node_id_count);
if (node) {
node->place(cx,cy);
}
return (TCL_OK);
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
Edge *
EditorNetModel::addEdge(Edge * edge) {
enterEdge(edge); // adds edge to a hash table
edge->Animation::insert(&drawables_); // adds to list of drawable objects
placeEdge(edge, edge->getSourceNode());
return edge;
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addLink(Node * src, Node * dst)
// - All links are duplex links by default
//----------------------------------------------------------------------
int
EditorNetModel::addLink(Node * src, Node * dst) {
double bw = 1.0; // Mb/s
double delay = 20; // ms
double length = 0.0;
double angle = 1.0;
Edge * edge;
if (!src->find_edge(dst->number()) &&
!dst->find_edge(src->number())) {
// Create the forward edge
edge = new Edge(src, dst, 25, bw, delay, length, angle);
edge->init_color("black");
enterEdge(edge);
edge->Animation::insert(&drawables_);
src->add_link(edge);
placeEdge(edge, src);
// Add queue handle for editing the forward edge's queue properties
addQueueHandle(edge);
// Create the reverse edge
edge = new Edge(dst, src, 25, bw, delay, length, angle);
edge->init_color("black");
enterEdge(edge);
edge->Animation::insert(&drawables_);
dst->add_link(edge);
placeEdge(edge, dst);
// Add queue handle for editing the reverse edge's queue properties
addQueueHandle(edge);
}
return (TCL_OK);
}
//----------------------------------------------------------------------
// int EditorNetModel::addLink(int source_id, int destination_id)
//----------------------------------------------------------------------
int
EditorNetModel::addLink(int source_id, int destination_id) {
Node * source_node, * destination_node;
source_node = lookupNode(source_id);
destination_node = lookupNode(destination_id);
if (source_node && destination_node) {
return addLink(source_node, destination_node);
}
return TCL_ERROR;
}
//----------------------------------------------------------------------
// agent_type
// EditorNetModel::classifyAgent(const char * agent)
//----------------------------------------------------------------------
agent_type
EditorNetModel::classifyAgent(const char * agent) {
if (strcmp(agent, "UDP") == 0) return UDP_SOURCE_AGENT;
if (strcmp(agent, "Null") == 0) return UDP_SINK_AGENT;
if ((strcmp(agent, "TCP") == 0) || (strncmp(agent, "TCP/", 4) == 0))
return TCP_SOURCE_AGENT;
if (strcmp(agent, "TCPSink") >= 0) return TCP_SINK_AGENT;
return UNKNOWN_AGENT;
}
//----------------------------------------------------------------------
// bool
// EditorNetModel::checkAgentCompatibility(agent_type source, agent_type dest)
//----------------------------------------------------------------------
bool
EditorNetModel::checkAgentCompatibility(agent_type source, agent_type dest) {
return (source == UDP_SOURCE_AGENT && dest == UDP_SINK_AGENT)
|| (source == UDP_SINK_AGENT && dest == UDP_SOURCE_AGENT)
|| (source == TCP_SOURCE_AGENT && dest == TCP_SINK_AGENT)
|| (source == TCP_SINK_AGENT && dest == TCP_SOURCE_AGENT)
|| (source == FULLTCP_AGENT && dest == FULLTCP_AGENT);
}
//----------------------------------------------------------------------
// bool
// EditorNetModel::checkAgentCompatibility(const char * source, const char * dest)
//----------------------------------------------------------------------
bool
EditorNetModel::checkAgentCompatibility(const char * source, const char * dest) {
return checkAgentCompatibility(classifyAgent(source), classifyAgent(dest));
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addAgent(Agent * agent, Node * node)
//----------------------------------------------------------------------
int
EditorNetModel::addAgent(Agent * agent, Node * node) {
placeAgent(agent, node);
// Add to animations list so that it will be redrawn on all updates
agent->Animation::insert(&animations_);
agent->node_ = node;
node->add_agent(agent);
return (TCL_OK);
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addAgent(Node *src, char * agent_type, float cx, float cy)
//----------------------------------------------------------------------
int
EditorNetModel::addAgent(Node * src, const char * agent_type, float cx, float cy) {
Agent *a;
Node *n = lookupNode(src->num());
if (n == 0) {
return 0;
} else {
a = new BoxAgent(agent_type, n->size());
placeAgent(a, src);
// Add to animations list so that it will be redrawn on all updates
a->Animation::insert(&animations_);
a->node_ = n;
//a->number_ = agent_number++;
agent_number++;
n->add_agent(a);
}
return (TCL_OK);
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addAgentLink(Agent *src_agent, Agent *dst_agent)
// - Need to add more constraints on which agents can connect to
// each other
//
//----------------------------------------------------------------------
int EditorNetModel::addAgentLink(Agent *src_agent, Agent *dst_agent) {
if (!src_agent->AgentPartner_ && !dst_agent->AgentPartner_
&& checkAgentCompatibility(src_agent->name(), dst_agent->name())) {
// Only connect agents that don't have a partner yet
// and are compatible with each other
agent_type src_type = classifyAgent(src_agent->name());
if ( src_type == UDP_SOURCE_AGENT
|| src_type == TCP_SOURCE_AGENT
|| src_type == FULLTCP_AGENT) {
src_agent->AgentRole_ = SOURCE;
dst_agent->AgentRole_ = DESTINATION;
} else {
src_agent->AgentRole_ = DESTINATION;
src_agent->AgentRole_ = SOURCE;
}
src_agent->AgentPartner_ = dst_agent;
dst_agent->AgentPartner_ = src_agent;
return TCL_OK;
}
return TCL_ERROR;
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addAgentLink(int source_id, int destination_id) {
//----------------------------------------------------------------------
int
EditorNetModel::addAgentLink(int source_id, int destination_id) {
Agent * source, * destination;
source = lookupAgent(source_id);
destination = lookupAgent(destination_id);
if (source && destination) {
return addAgentLink(source, destination);
}
return TCL_ERROR;
}
//----------------------------------------------------------------------
// trafgen_type
// EditorNetModel::classifyTrafficSource(const char * source)
//----------------------------------------------------------------------
trafgen_type
EditorNetModel::classifyTrafficSource(const char * source) {
if ( strcmp(source, "FTP") == 0
|| strcmp(source, "Telnet") == 0) return TCP_APP;
if ( strcmp(source, "CBR") == 0
|| strcmp(source, "Pareto") == 0
|| strcmp(source, "Exponential") == 0) return UDP_APP;
return UNKNOWN_APP;
}
//----------------------------------------------------------------------
// trafgen_type
// EditorNetModel::checkAgentTrafficSourceCompatibility(agent_type agent, trafgen_type source)
//----------------------------------------------------------------------
bool
EditorNetModel::checkAgentTrafficSourceCompatibility(agent_type agent, trafgen_type source) {
return (source == UDP_APP && agent == UDP_SOURCE_AGENT)
|| (source == TCP_APP && agent == TCP_SOURCE_AGENT)
|| (source == TCP_APP && agent == FULLTCP_AGENT)
|| (source == FULLTCP_APP && agent == FULLTCP_AGENT);
}
//----------------------------------------------------------------------
// trafgen_type
// EditorNetModel::checkAgentTrafficSourceCompatibility(const char * agent, const char * source)
//----------------------------------------------------------------------
bool
EditorNetModel::checkAgentTrafficSourceCompatibility(const char * agent, const char * source) {
return checkAgentTrafficSourceCompatibility(classifyAgent(agent),
classifyTrafficSource(source));
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addTrafficSource(TrafficSource * traffic_source,
// Agent * agent)
//----------------------------------------------------------------------
int
EditorNetModel::addTrafficSource(TrafficSource * traffic_source,
Agent * agent) {
if (traffic_source && agent
&& checkAgentTrafficSourceCompatibility(agent->name(), traffic_source->name())) {
traffic_source->attachTo(agent);
// Add to animations list so that it will be redrawn on all updates
traffic_source->Animation::insert(&animations_);
// Add to master list of all trafficsources_ which is used to
// look up a traffic source for editing purposes
traffic_source->editornetmodel_next_ = traffic_sources_;
traffic_sources_ = traffic_source;
return TCL_OK;
}
return TCL_ERROR;
}
//----------------------------------------------------------------------
// int
// EditorNetModel::addTrafficSource(Agent * agent, char * type,
// float cx, float cy)
//----------------------------------------------------------------------
int
EditorNetModel::addTrafficSource(Agent * agent, const char * type,
float cx, float cy) {
TrafficSource * traffic_source;
if (agent) {
traffic_source = new TrafficSource(type, agent->size());
return addTrafficSource(traffic_source, agent);
}
return (TCL_ERROR);
}
//----------------------------------------------------------------------
// TrafficSource *
// EditorNetModel::lookupTrafficSource(int id)
//----------------------------------------------------------------------
TrafficSource *
EditorNetModel::lookupTrafficSource(int id) {
TrafficSource * ts;
for (ts = traffic_sources_; ts; ts = ts->editornetmodel_next_) {
if (ts->number() == id) {
break;
}
}
return ts;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
int
EditorNetModel::addLossModel(LossModel * loss_model, Edge * edge) {
if (loss_model && edge) {
edge->addLossModel(loss_model);
loss_model->place();
// Add to animations list so that it will be redrawn on all updates
loss_model->Animation::insert(&animations_);
// Add to master list of all lossmodels_ which is used to
// look up a lossmodel for editing purposes
loss_model->next_lossmodel_ = lossmodels_;
lossmodels_ = loss_model;
}
return TCL_OK;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
int
EditorNetModel::addLossModel(Edge * edge, const char * type,
double cx, double cy) {
LossModel * loss_model;
if (edge && !edge->getLossModel()) {
loss_model = new LossModel(type, edge->getSourceNode()->size());
edge->addLossModel(loss_model);
// Add to animations list so that it will be redrawn on all updates
loss_model->Animation::insert(&animations_);
// Add to master list of all lossmodels_ which is used to
// look up a lossmodel for editing purposes
loss_model->next_lossmodel_ = lossmodels_;
lossmodels_ = loss_model;
}
return (TCL_OK);
}
//----------------------------------------------------------------------
// TrafficSource *
// EditorNetModel::lookupLossModel(int id)
//----------------------------------------------------------------------
LossModel *
EditorNetModel::lookupLossModel(int id) {
LossModel * loss_model;
for (loss_model = lossmodels_;
loss_model;
loss_model = loss_model->next_lossmodel_) {
if (loss_model->number() == id) {
break;
}
}
return loss_model;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
QueueHandle *
EditorNetModel::addQueueHandle(Edge * edge) {
QueueHandle * queue_handle;
// Add queue handle for editing the edge's queue properties
queue_handle = new QueueHandle(edge);
edge->addQueueHandle(queue_handle);
queue_handle->Animation::insert(&drawables_);
queue_handle->next_queue_handle_ = queue_handles_;
queue_handles_ = queue_handle;
return queue_handle;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
QueueHandle *
EditorNetModel::addQueueHandle(Edge * edge, const char * type) {
QueueHandle * queue_handle;
queue_handle = addQueueHandle(edge);
queue_handle->setType(type);
return queue_handle;
}
//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
void EditorNetModel::setNodeProperty(int id, const char * value, const char * variable) {
Node * node = lookupNode(id);
if (node) {
if (!strcmp(variable, "size_")) {
node->size(strtod(value,NULL));
} else if (!strcmp(variable, "color")) {
node->init_color(value);
} else if (!strcmp(variable, "dlabel_")) {
node->dlabel(value);
} else if (!strcmp(variable, "X_")) {
node->place(strtod(value, NULL),node->y());
} else if (!strcmp(variable, "Y_")) {
node->place(node->x(), strtod(value, NULL));
} else if (!strcmp(variable, "Z_")) {
//
} else {
fprintf(stderr, "EditorNetModel::setNodeProperty - unknown property %s\n", variable);
}
} else {
fprintf(stderr, "Node %d does not exist.\n", id);
}
}
//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
void EditorNetModel::setAgentProperty(int id, const char * value, const char * variable) {
Agent * agent = lookupAgent(id);
if (agent) {
if (!strcmp(variable, "windowInit_")) {
// initial window size
agent->windowInit(atoi(value));
} else if (!strcmp(variable, "window_")) {
// window size
agent->window(atoi(value));
} else if (!strcmp(variable, "maxcwnd_")) {
// maximum cwnd_
agent->maxcwnd(atoi(value));
} else if (!strcmp(variable, "flowcolor_")) {
// Flow ID + Color
if ((strcmp(value, "(null)") == 0) || (strcmp(value, "") == 0)) {
agent->flowcolor("black");
} else {
agent->flowcolor(value);
}
} else if (!strcmp(variable, "packetSize_")) {
agent->packetSize(atoi(value));
} else {
// fprintf(stderr, "EditorNetModel::setAgentProperty - unknown property %s\n", variable);
}
} else {
fprintf(stderr, "EditorNetModel::setAgentProperty - Nonexisting agent %d.\n", id);
}
}
//----------------------------------------------------------------------
// void
// EditorNetModel::setLinkProperty(int source_id, int destination_id,
// char * value, char * variable)
//----------------------------------------------------------------------
void
EditorNetModel::setLinkProperty(int source_id, int destination_id,
const char * value, const char * variable) {
Edge * edge = lookupEdge(source_id, destination_id);
if (edge) {
if (!strcmp(variable, "bandwidth_")) {
edge->setBW(strtod(value,NULL));
} else if (!strcmp(variable, "color_")) {
edge->init_color(value);
} else if (!strcmp(variable, "delay_")) {
edge->setDelay(strtod(value,NULL));
} else if (!strcmp(variable, "dlabel_")) {
if (strcmp(value, "")) {
edge->dlabel(value);
}
} else if (!strcmp(variable, "length_")) {
edge->setLength(strtod(value,NULL));
}
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
EditorNetModel::setQueueHandleProperty(int source_id, int destination_id,
const char * value, const char * variable) {
Edge * edge;
QueueHandle * queue;
edge = lookupEdge(source_id, destination_id);
if (edge) {
queue = edge->getQueueHandle();
if (queue) {
if (strcmp(variable, "type_") == 0) {
queue->setType(value);
} else if (strcmp(variable, "limit_") == 0) {
queue->setLimit(atoi(value));
} else if (strcmp(variable, "secsPerByte__") == 0) {
queue->setSecondsPerByte(strtod(value,NULL));
} else if (strcmp(variable, "maxqueue_") == 0) {
queue->setMaxQueue(atoi(value));
} else if (strcmp(variable, "buckets_") == 0) {
queue->setBuckets(atoi(value));
} else if (strcmp(variable, "blimit_") == 0) {
queue->setSharedBufferSize(atoi(value));
} else if (strcmp(variable, "quantum_") == 0) {
queue->setQuantum(atoi(value));
} else if (strcmp(variable, "mask_") == 0) {
if (atoi(value) == 0) {
queue->setMask(false);
} else {
queue->setMask(true);
}
} else if (strcmp(variable, "bytes_") == 0) {
if (atoi(value) == 0) {
queue->setBytes(false);
} else {
queue->setBytes(true);
}
} else if (strcmp(variable, "queue_in_bytes_") == 0) {
if (atoi(value) == 0) {
queue->setQueueInBytes(false);
} else {
queue->setQueueInBytes(true);
}
} else if (strcmp(variable, "thresh_") == 0) {
queue->setThreshold(strtod(value,NULL));
} else if (strcmp(variable, "max_thresh__") == 0) {
queue->setMaximumThreshold(strtod(value,NULL));
} else if (strcmp(variable, "mean_pktsize_") == 0) {
queue->setMeanPacketSize(atoi(value));
} else if (strcmp(variable, "q_weight_") == 0) {
queue->setQueueWeight(strtod(value,NULL));
} else if (strcmp(variable, "wait_") == 0) {
if (atoi(value) == 0) {
queue->setWaitInterval(false);
} else {
queue->setWaitInterval(true);
}
} else if (strcmp(variable, "linterm_") == 0) {
queue->setLinterm(strtod(value,NULL));
} else if (strcmp(variable, "setbit_") == 0) {
if (atoi(value) == 0) {
queue->setBitMarking(false);
} else {
queue->setBitMarking(true);
}
} else if (strcmp(variable, "drop_tail_") == 0) {
if (atoi(value) == 0) {
queue->setREDDropTail(false);
} else {
queue->setREDDropTail(true);
}
}
} else {
fprintf(stderr, "EditorNetModel::setQueueHandleProperty() - no queuehandle on edge.\n");
}
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
EditorNetModel::setTrafficSourceProperty(int id, const char * value,
const char * variable) {
TrafficSource * trafficsource;
trafficsource = lookupTrafficSource(id);
if (trafficsource) {
if (strcmp(variable, "start_") == 0) {
//trafficsource->startAt(atof(value));
trafficsource->timelist.add(strtod(value, NULL));
} else if (strcmp(variable, "stop_") == 0) {
//trafficsource->stopAt(atof(value));
trafficsource->timelist.add(strtod(value, NULL));
} else if (strcmp(variable, "interval_") == 0) {
trafficsource->setInterval(atof(value));
} else if (strcmp(variable, "maxpkts_") == 0) {
trafficsource->setMaxpkts(atoi(value));
} else if (strcmp(variable, "addtime") == 0) {
trafficsource->timelist.add(atof(value));
} else if (strcmp(variable, "removetime") == 0) {
trafficsource->timelist.remove(atof(value));
} else if (strcmp(variable, "timelist") == 0) {
trafficsource->timelist.setList(value);
// --- Exponential Properties
} else if (strcmp(variable, "burst_time_") == 0) {
trafficsource->setBurstTime(atoi(value));
} else if (strcmp(variable, "idle_time_") == 0) {
trafficsource->setIdleTime(atoi(value));
} else if (strcmp(variable, "rate_") == 0) {
trafficsource->setRate(atoi(value));
// --- Pareto
} else if (strcmp(variable, "shape_") == 0) {
trafficsource->setShape(strtod(value, NULL));
} else if (strcmp(variable, "title") == 0) {
} else if (strcmp(variable, "agent_name") == 0) {
} else {
fprintf(stderr, " Unknown traffic source property %s\n", variable);
}
} else {
fprintf(stderr, " Unable to find traffic source with id %d\n", id);
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
EditorNetModel::setLossModelProperty(int id, const char * value,
const char * variable) {
LossModel * lossmodel;
lossmodel = lookupLossModel(id);
if (lossmodel) {
if (strcmp(variable, "period_") == 0) {
lossmodel->setPeriod(strtod(value, NULL));
} else if (strcmp(variable, "offset_") == 0) {
lossmodel->setOffset(strtod(value, NULL));
} else if (strcmp(variable, "burstlen_") == 0) {
lossmodel->setBurstLength(strtod(value, NULL));
} else if (strcmp(variable, "rate_") == 0) {
lossmodel->setRate(strtod(value, NULL));
} else if (strcmp(variable, "loss_unit_") == 0) {
lossmodel->setLossUnit(value);
}
} else {
fprintf(stderr, " Unable to find loss model with id %d\n", id);
}
}
//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int EditorNetModel::command(int argc, const char *const *argv) {
FILE * file;
Node * node;
double time;
if (argc == 2) {
if (strcmp(argv[1], "layout") == 0) {
layout();
return (TCL_OK);
}
} else if (argc == 4) {
// Write out ns script information
if (strcmp(argv[1], "saveasns") == 0) {
// argv syntax is as follows:
// <net> saveasns filename filename_root
file = fopen(argv[2], "w");
if (file) {
// fprintf(stderr, "Writing ns script to %s...",argv[2]);
writeNsScript(file, argv[2], argv[3]);
fclose(file);
// fprintf(stderr, "done.\n");
} else {
fprintf(stderr, "nam: Unable to open file: %s\n", argv[2]);
}
return (TCL_OK);
} else if (strcmp(argv[1], "removeNodeMovement") == 0) {
node = lookupNode(atoi(argv[2]));
time = strtod(argv[3], NULL);
node->removeMovementDestination(time);
return TCL_OK;
}
}
return (NetModel::command(argc, argv));
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void EditorNetModel::layout() {
Node *n;
for (n = nodes_; n != 0; n = n->next_)
for (Edge* e = n->links(); e != 0; e = e->next_)
placeEdge(e, n);
}
//----------------------------------------------------------------------
// int
// EditorNetModel::saveAsNs(FILE * file)
//----------------------------------------------------------------------
int
EditorNetModel::writeNsScript(FILE * file, const char * filename, const char * filename_root) {
Node * node;
Edge * edge;
LossModel * loss_model;
Agent * agent;
int number_of_wireless_nodes = 0;
int number_of_wired_nodes = 0;
double maximum_x, maximum_y;
double node_x, node_y;
maximum_x = 500;
maximum_y = 500;
// Add a disclaimer
fprintf(file, "#------------------------------------------------------- \n");
fprintf(file, "# This ns script has been created by the nam editor.\n");
fprintf(file, "# If you edit it manually, the nam editor might not\n");
fprintf(file, "# be able to open it properly in the future.\n");
fprintf(file, "#\n");
fprintf(file, "# EDITING BY HAND IS AT YOUR OWN RISK!\n");
fprintf(file, "#------------------------------------------------------- \n");
fprintf(file, "# Create a new simulator object.\n");
fprintf(file, "set ns [new Simulator]\n");
fprintf(file, "# Create a nam trace datafile.\n");
fprintf(file, "set namfile [open %s.nam w]\n", filename_root);
fprintf(file, "$ns namtrace-all $namfile\n");
// write out node creation infomation
fprintf(file, "\n# Create wired nodes.\n");
for (node = nodes_; node; node = node->next_) {
if (node->links()) {
// Only write out wired links here
node->writeNsScript(file);
fprintf(file, "\n");
number_of_wired_nodes++;
} else {
// If a node has no links it must be a wireless node
number_of_wireless_nodes++;
}
// Find maximum node mobility and placement range
node_x = node->getMaximumX();
node_y = node->getMaximumY();
if (node_x > maximum_x) {
// Add some extra space to be sure node is within
// wireless boundary
maximum_x = node_x + 2.0*node->size();
}
if (node_y > maximum_y) {
// Add some extra space to be sure node is within
// wireless boundary
maximum_y = node_y + 2.0*node->size();
}
}
if (number_of_wireless_nodes > 0) {
fprintf(file, "\n# ----- Setup wireless environment. ----\n");
fprintf(file, "set wireless_tracefile [open %s.trace w]\n", filename_root);
fprintf(file, "set topography [new Topography]\n");
fprintf(file, "$ns trace-all $wireless_tracefile\n");
fprintf(file, "$ns namtrace-all-wireless $namfile %f %f\n", maximum_x, maximum_y);
fprintf(file, "$topography load_flatgrid %f %f\n", maximum_x, maximum_y);
fprintf(file, "#\n");
fprintf(file, "# Create God\n");
fprintf(file, "#\n");
fprintf(file, "set god_ [create-god %d]\n", number_of_wireless_nodes);
fprintf(file, "#global node setting\n");
fprintf(file, "$ns node-config -adhocRouting DSR \\\n");
fprintf(file, " -llType LL \\\n");
fprintf(file, " -macType Mac/802_11 \\\n");
fprintf(file, " -ifqType Queue/DropTail/PriQueue \\\n");
fprintf(file, " -ifqLen 50 \\\n");
fprintf(file, " -antType Antenna/OmniAntenna \\\n");
fprintf(file, " -propType Propagation/TwoRayGround \\\n");
fprintf(file, " -phyType Phy/WirelessPhy \\\n");
fprintf(file, " -channel [new Channel/WirelessChannel] \\\n");
fprintf(file, " -topoInstance $topography \\\n");
fprintf(file, " -agentTrace ON \\\n");
fprintf(file, " -routerTrace OFF \\\n");
fprintf(file, " -macTrace ON\n");
fprintf(file, "\n# Create wireless nodes.\n");
for (node = nodes_; node; node = node->next_) {
if (!node->links()) {
node->writeNsScript(file);
node->writeNsMovement(file);
}
}
}
// write out link information
fprintf(file, "\n# Create links between nodes.\n");
for (node = nodes_; node ; node = node->next_) {
for (edge = node->links(); edge; edge = edge->next_) {
edge->writeNsScript(file);
}
}
// Write out lossmodel information
fprintf(file, "# Add Link Loss Models\n");
for (loss_model = lossmodels_;
loss_model;
loss_model = loss_model->next_lossmodel_) {
loss_model->writeNsDefinitionScript(file);
}
// write out agents and it's traffic sources
fprintf(file, "\n# Create agents.\n");
for (node = nodes_; node; node = node->next_) {
for (agent = node->agents(); agent; agent = agent->next_) {
agent->writeNsDefinitionScript(file);
}
}
// Write out agent connections
// An agent can connect to only one other agent
fprintf(file, "\n# Connect agents.\n");
for (node = nodes_; node; node = node->next_) {
for (agent = node->agents(); agent; agent = agent->next_) {
agent->writeNsConnectionScript(file);
}
}
// Find time at which to stop the simulation
// for (ts = traffic_sources_; ts; ts = ts->editornetmodel_next_) {
// if (finish_time < ts->stopAt()) {
// finish_time = ts->stopAt();
// }
// }
fprintf(file, "# Run the simulation\n");
fprintf(file, "proc finish {} {\n global ns namfile\n $ns flush-trace\n");
fprintf(file, " close $namfile\n exec nam -r %fus %s.nam & \n exit 0\n }\n", playback_speed_, filename_root);
//fprintf(file, "$ns at %f \"finish\"\n", finish_time);
fprintf(file, "$ns at %f \"finish\"\n", maximum_simulation_time_);
fprintf(file, "$ns run\n");
return 0;
}
//----------------------------------------------------------------------
// void
// EditorNetModel::removeNode(Node *n)
// - remove node n from the nodes_ list and delete it
//----------------------------------------------------------------------
void EditorNetModel::removeNode(Node *n) {
Node * previous, * run;
Edge * edge;
Agent * agent;
previous = nodes_;
for (run = nodes_; run; run = run->next_) {
if (n->num() == run->num()) {
// when deleting the last node
if (run->num() == nodes_->num()) {
nodes_ = nodes_->next_;
break;
} else {
previous->next_ = run->next_;
break;
}
}
previous = run;
}
run->next_ = NULL;
// Remove it from list of drawables
run->detach();
// delete edges of the nodes_
for (edge = run->links(); edge != 0; edge = edge->next_) {
removeLink(edge);
}
// delete agents on the nodes_
for (agent = run->agents(); agent != 0; agent = agent->next_) {
removeAgent(agent);
}
delete run;
}
//----------------------------------------------------------------------
// void
// EditorNetModel::removeLink(Edge *e)
//
//----------------------------------------------------------------------
void
EditorNetModel::removeLink(Edge *e) {
EdgeHashNode * h, * g;
Edge * e1, * e2;
LossModel * lossmodel;
int src = e->src();
int dst = e->dst();
h = lookupEdgeHashNode(src, dst);
g = lookupEdgeHashNode(dst, src);
if (h == 0 || g == 0) {
// h,g = 0 or h,g !=0
return;
}
e1 = h->edge;
e2 = g->edge;
lossmodel = e1->getLossModel();
if (lossmodel) {
removeLossModel(lossmodel);
}
lossmodel = e2->getLossModel();
if (lossmodel) {
removeLossModel(lossmodel);
}
// defined in netmodel.cc
removeEdge(e1);
removeEdge(e2);
e1->detach();
e2->detach();
Node* srcnode = e1->start();
Node* dstnode = e2->start();
// it is a duplex by default
srcnode->delete_link(e1);
dstnode->delete_link(e2);
delete e1;
delete e2;
}
//----------------------------------------------------------------------
// void
// EditorNetModel::removeAgent(Agent *a)
// - removes and deletes an Agent and all of its Traffic Sources
//----------------------------------------------------------------------
void
EditorNetModel::removeAgent(Agent *a) {
Node * n;
TrafficSource * ts, * next_ts;
n = a->node_;
if (a->AgentPartner_ != NULL) {
a->AgentPartner_->AgentPartner_ = NULL;
a->AgentPartner_->AgentRole_ = 0;
}
n->delete_agent(a);
a->detach();
for (ts = a->traffic_sources_; ts; ts = next_ts) {
// Save next traffic source in list since this
// traffic source will be deleted in removeTrafficSource
next_ts = ts->next_;
removeTrafficSource(ts);
}
delete a;
}
//----------------------------------------------------------------------
// void
// EditorNetModel::removeTrafficSource(TrafficSource * ts) {
//----------------------------------------------------------------------
void
EditorNetModel::removeTrafficSource(TrafficSource * ts) {
TrafficSource * run, * previous;
// Run down the list of traffic sources
previous = NULL;
for (run = traffic_sources_; run; run = run->editornetmodel_next_) {
if (run == ts) {
break;
}
previous = run;
}
if (previous) {
previous->editornetmodel_next_ = ts->editornetmodel_next_;
} else {
if (run == traffic_sources_) {
// ts is at the front of the list
traffic_sources_ = ts->editornetmodel_next_;
}
}
ts->editornetmodel_next_ = NULL;
ts->removeFromAgent();
delete ts;
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
EditorNetModel::removeLossModel(LossModel * lossmodel) {
LossModel * run, * previous;
// Run down the list of lossmodels
previous = NULL;
for (run = lossmodels_; run; run = run->next_lossmodel_) {
if (run == lossmodel) {
break;
}
previous = run;
}
if (previous) {
previous->next_lossmodel_ = lossmodel->next_lossmodel_;
} else {
if (run == lossmodels_) {
// ts is at the front of the list
lossmodels_ = lossmodel->next_lossmodel_;
}
}
lossmodel->next_lossmodel_ = NULL;
lossmodel->clearEdge();
delete lossmodel;
}
syntax highlighted by Code2HTML, v. 0.9.1