// // 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 #include #include #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: // 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; }