enetmodel.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:36k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 1997-2001 by the University of Southern California
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License,
  6.  * version 2, as published by the Free Software Foundation.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License along
  14.  * with this program; if not, write to the Free Software Foundation, Inc.,
  15.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  16.  *
  17.  *
  18.  * The copyright of this module includes the following
  19.  * linking-with-specific-other-licenses addition:
  20.  *
  21.  * In addition, as a special exception, the copyright holders of
  22.  * this module give you permission to combine (via static or
  23.  * dynamic linking) this module with free software programs or
  24.  * libraries that are released under the GNU LGPL and with code
  25.  * included in the standard release of ns-2 under the Apache 2.0
  26.  * license or under otherwise-compatible licenses with advertising
  27.  * requirements (or modified versions of such code, with unchanged
  28.  * license).  You may copy and distribute such a system following the
  29.  * terms of the GNU GPL for this module and the licenses of the
  30.  * other code concerned, provided that you include the source code of
  31.  * that other code when and as the GNU GPL requires distribution of
  32.  * source code.
  33.  *
  34.  * Note that people who make modified versions of this module
  35.  * are not obligated to grant this special exception for their
  36.  * modified versions; it is their choice whether to do so.  The GNU
  37.  * General Public License gives permission to release a modified
  38.  * version without this exception; this exception also makes it
  39.  * possible to release a modified version which carries forward this
  40.  * exception.
  41.  *
  42.  * $Header: /cvsroot/nsnam/nam-1/enetmodel.cc,v 1.46 2007/02/12 07:08:43 tom_henderson Exp $
  43.  */
  44. // Network model with Editor layout
  45. #include <stdlib.h>
  46. #include <math.h>
  47. #include <float.h>
  48. #include "random.h"
  49. #include "view.h"
  50. #include "netview.h"
  51. #include "animation.h"
  52. #include "queue.h"
  53. #include "edge.h"
  54. #include "node.h"
  55. #include "agent.h"
  56. #include "sincos.h"
  57. #include "state.h"
  58. #include "packet.h"
  59. #include "enetmodel.h"
  60. #include "trafficsource.h"
  61. #include "queuehandle.h"
  62. static int agent_number = 0;
  63. class EditorNetworkModelClass : public TclClass {
  64. public:
  65. EditorNetworkModelClass() : TclClass("NetworkModel/Editor") {}
  66. TclObject* create(int argc, const char*const* argv) {
  67. if (argc < 5) 
  68. return 0;
  69. return (new EditorNetModel(argv[4]));
  70. }
  71. } editornetworkmodel_class;
  72. EditorNetModel::EditorNetModel(const char *editor) :
  73. NetModel(editor) {
  74. node_id_count = 0;
  75. traffic_sources_ = NULL;
  76. lossmodels_ = NULL;
  77. queue_handles_ = NULL;
  78. maximum_simulation_time_ = 30.0; // seconds
  79. playback_speed_ = 2000.0;  // default animation speed (in microseconds)
  80. bind("Wpxmin_", &pxmin_);
  81. bind("Wpymin_", &pymin_);
  82. bind("Wpxmax_", &pxmax_);
  83. bind("Wpymax_", &pymax_);
  84. bind("maximum_simulation_time_", &maximum_simulation_time_);
  85. }
  86. EditorNetModel::~EditorNetModel()
  87. {
  88. }
  89. void EditorNetModel::BoundingBox(BBox& bb)
  90. // by default, 800X1000 internal drawing area
  91. bb.xmin = pxmin_;
  92. bb.ymin = pymin_;
  93. bb.xmax = pxmax_;
  94. bb.ymax = pymax_;
  95. for (Animation* a = drawables_; a != 0; a = a->next()) {
  96. a->merge(bb);
  97. }
  98. pxmin_ = bb.xmin;
  99. pymin_ = bb.ymin;
  100. pxmax_ = bb.xmax;
  101. pymax_ = bb.ymax;
  102. }
  103. //----------------------------------------------------------------------
  104. // Node * 
  105. // EditorNetModel::addNode(Node * node)
  106. //----------------------------------------------------------------------
  107. Node * 
  108. EditorNetModel::addNode(Node * node) {
  109. if (!lookupNode(node->num())) {
  110. node->next_ = nodes_;
  111. nodes_ = node;
  112. node->Animation::insert(&drawables_);
  113. return node;
  114. }
  115. return NULL;
  116. }
  117. //----------------------------------------------------------------------
  118. // int
  119. // EditorNetModel::addNode(int node_id)
  120. //----------------------------------------------------------------------
  121. Node *
  122. EditorNetModel::addNode(int node_id) {
  123. Node * node = NULL;
  124. static char name[TRACE_LINE_MAXLEN];
  125. double size = 10.0; // This is the default node size taken from
  126. // parser.cc under the 'n' animation event
  127. sprintf(name, "%d", node_id);
  128. node = new CircleNode(name, size);  
  129. node->init_color("black");
  130. if (node_id_count <= node_id) {
  131. node_id_count = node_id + 1;
  132. }
  133. if (!addNode(node)) {
  134. delete node;
  135. node = NULL; 
  136. }
  137. return node;
  138. }
  139.  
  140. //----------------------------------------------------------------------
  141. // int 
  142. // EditorNetModel::addNode(float cx, float cy)
  143. // - Create a node using the specified name
  144. // and the default size and insert it into this
  145. // NetModel's list of drawables.
  146. //----------------------------------------------------------------------
  147. int 
  148. EditorNetModel::addNode(float cx, float cy) {
  149. Node * node;
  150. // Find the next node id number
  151. if (node_id_count == 0 ) {
  152. for (node = nodes_; node != 0; node = node->next_) {
  153. if (node->num() > node_id_count) {
  154. node_id_count = node->num(); 
  155. }
  156. }
  157. node_id_count++;
  158. }
  159.  
  160. node = addNode(node_id_count);
  161. if (node) {
  162. node->place(cx,cy);
  163. }
  164. return (TCL_OK);
  165. }
  166. //----------------------------------------------------------------------
  167. //----------------------------------------------------------------------
  168. Edge *
  169. EditorNetModel::addEdge(Edge * edge) {
  170. enterEdge(edge); // adds edge to a hash table
  171. edge->Animation::insert(&drawables_); // adds to list of drawable objects
  172. placeEdge(edge, edge->getSourceNode());
  173. return edge;
  174. }
  175. //----------------------------------------------------------------------
  176. // int
  177. // EditorNetModel::addLink(Node * src, Node * dst)
  178. //  - All links are duplex links by default
  179. //----------------------------------------------------------------------
  180. int
  181. EditorNetModel::addLink(Node * src, Node * dst) {
  182. double bw = 1.0;  // Mb/s
  183. double delay = 20;  // ms
  184. double length = 0.0;
  185. double angle = 1.0;
  186. Edge * edge;
  187. if (!src->find_edge(dst->number()) && 
  188.     !dst->find_edge(src->number())) {
  189. // Create the forward edge
  190. edge = new Edge(src, dst, 25, bw, delay, length, angle);
  191. edge->init_color("black");
  192. enterEdge(edge);
  193. edge->Animation::insert(&drawables_);
  194. src->add_link(edge);
  195. placeEdge(edge, src);
  196. // Add queue handle for editing the forward edge's queue properties
  197. addQueueHandle(edge);
  198.  
  199. // Create the reverse edge
  200. edge = new Edge(dst, src, 25, bw, delay, length, angle);
  201. edge->init_color("black");
  202. enterEdge(edge);
  203. edge->Animation::insert(&drawables_);
  204. dst->add_link(edge);
  205. placeEdge(edge, dst);
  206. // Add queue handle for editing the reverse edge's queue properties
  207. addQueueHandle(edge);
  208. }
  209. return (TCL_OK);
  210. }
  211. //----------------------------------------------------------------------
  212. // int EditorNetModel::addLink(int source_id, int destination_id)
  213. //----------------------------------------------------------------------
  214. int 
  215. EditorNetModel::addLink(int source_id, int destination_id) {
  216. Node * source_node, * destination_node;
  217. source_node = lookupNode(source_id);
  218. destination_node = lookupNode(destination_id);
  219. if (source_node && destination_node) {
  220. return addLink(source_node, destination_node);
  221. }
  222. return TCL_ERROR;
  223. }
  224. //----------------------------------------------------------------------
  225. // agent_type
  226. // EditorNetModel::classifyAgent(const char * agent)
  227. //----------------------------------------------------------------------
  228. agent_type
  229. EditorNetModel::classifyAgent(const char * agent) {
  230. if (strcmp(agent, "UDP") == 0) return UDP_SOURCE_AGENT;
  231. if (strcmp(agent, "Null") == 0) return UDP_SINK_AGENT;
  232. if ((strcmp(agent, "TCP") == 0) || (strncmp(agent, "TCP/", 4) == 0))
  233. return TCP_SOURCE_AGENT;
  234. if (strcmp(agent, "TCPSink") >= 0) return TCP_SINK_AGENT;
  235. return UNKNOWN_AGENT;
  236. }
  237. //----------------------------------------------------------------------
  238. // bool
  239. // EditorNetModel::checkAgentCompatibility(agent_type source, agent_type dest)
  240. //----------------------------------------------------------------------
  241. bool
  242. EditorNetModel::checkAgentCompatibility(agent_type source, agent_type dest) {
  243. return (source == UDP_SOURCE_AGENT && dest == UDP_SINK_AGENT)
  244. || (source == UDP_SINK_AGENT && dest == UDP_SOURCE_AGENT)
  245. || (source == TCP_SOURCE_AGENT && dest == TCP_SINK_AGENT)
  246. || (source == TCP_SINK_AGENT && dest == TCP_SOURCE_AGENT)
  247. || (source == FULLTCP_AGENT && dest == FULLTCP_AGENT);
  248. }
  249. //----------------------------------------------------------------------
  250. // bool
  251. // EditorNetModel::checkAgentCompatibility(const char * source, const char * dest)
  252. //----------------------------------------------------------------------
  253. bool
  254. EditorNetModel::checkAgentCompatibility(const char * source, const char * dest) {
  255. return checkAgentCompatibility(classifyAgent(source), classifyAgent(dest));
  256. }
  257. //----------------------------------------------------------------------
  258. // int
  259. // EditorNetModel::addAgent(Agent * agent, Node * node)
  260. //----------------------------------------------------------------------
  261. int
  262. EditorNetModel::addAgent(Agent * agent, Node * node) {
  263. placeAgent(agent, node);
  264. // Add to animations list so that it will be redrawn on all updates
  265. agent->Animation::insert(&animations_);
  266. agent->node_ = node;
  267. node->add_agent(agent);
  268. return (TCL_OK);
  269. }
  270. //----------------------------------------------------------------------
  271. // int
  272. // EditorNetModel::addAgent(Node *src, char * agent_type, float cx, float cy)
  273. //----------------------------------------------------------------------
  274. int
  275. EditorNetModel::addAgent(Node * src, const char * agent_type, float cx, float cy) {
  276. Agent *a;
  277. Node *n = lookupNode(src->num());
  278. if (n == 0) {
  279. return 0;
  280. } else {
  281. a = new BoxAgent(agent_type, n->size());
  282. placeAgent(a, src);
  283. // Add to animations list so that it will be redrawn on all updates
  284. a->Animation::insert(&animations_);
  285. a->node_ = n;
  286. //a->number_ = agent_number++;
  287. agent_number++;
  288. n->add_agent(a);
  289. }
  290. return (TCL_OK);
  291. }
  292. //----------------------------------------------------------------------
  293. // int
  294. // EditorNetModel::addAgentLink(Agent *src_agent, Agent *dst_agent)
  295. //  - Need to add more constraints on which agents can connect to 
  296. //  each other
  297. // 
  298. //----------------------------------------------------------------------
  299. int EditorNetModel::addAgentLink(Agent *src_agent, Agent *dst_agent) {
  300. if (!src_agent->AgentPartner_ && !dst_agent->AgentPartner_
  301. && checkAgentCompatibility(src_agent->name(), dst_agent->name())) {
  302. // Only connect agents that don't have a partner yet
  303. // and are compatible with each other
  304.  
  305. agent_type src_type = classifyAgent(src_agent->name());
  306. if (   src_type == UDP_SOURCE_AGENT
  307.     || src_type == TCP_SOURCE_AGENT
  308.     || src_type == FULLTCP_AGENT) {
  309. src_agent->AgentRole_ = SOURCE;
  310. dst_agent->AgentRole_ = DESTINATION;
  311. } else {
  312. src_agent->AgentRole_ = DESTINATION;
  313. src_agent->AgentRole_ = SOURCE;
  314. }
  315. src_agent->AgentPartner_ = dst_agent;
  316. dst_agent->AgentPartner_ = src_agent;
  317. return TCL_OK;
  318. }
  319. return TCL_ERROR;
  320. }
  321. //----------------------------------------------------------------------
  322. // int
  323. // EditorNetModel::addAgentLink(int source_id, int destination_id) {
  324. //----------------------------------------------------------------------
  325. int
  326. EditorNetModel::addAgentLink(int source_id, int destination_id) {
  327. Agent * source, * destination;
  328. source = lookupAgent(source_id);
  329. destination = lookupAgent(destination_id);
  330. if (source && destination) {
  331.  return addAgentLink(source, destination);
  332. }
  333. return TCL_ERROR;
  334. }
  335. //----------------------------------------------------------------------
  336. // trafgen_type
  337. // EditorNetModel::classifyTrafficSource(const char * source)
  338. //----------------------------------------------------------------------
  339. trafgen_type
  340. EditorNetModel::classifyTrafficSource(const char * source) {
  341. if ( strcmp(source, "FTP") == 0
  342.   || strcmp(source, "Telnet") == 0) return TCP_APP;
  343. if ( strcmp(source, "CBR") == 0
  344.   || strcmp(source, "Pareto") == 0
  345.   || strcmp(source, "Exponential") == 0) return UDP_APP;
  346. return UNKNOWN_APP;
  347. }
  348. //----------------------------------------------------------------------
  349. // trafgen_type
  350. // EditorNetModel::checkAgentTrafficSourceCompatibility(agent_type agent, trafgen_type source)
  351. //----------------------------------------------------------------------
  352. bool
  353. EditorNetModel::checkAgentTrafficSourceCompatibility(agent_type agent, trafgen_type source) {
  354. return (source == UDP_APP && agent == UDP_SOURCE_AGENT)
  355.     || (source == TCP_APP && agent == TCP_SOURCE_AGENT)
  356.     || (source == TCP_APP && agent == FULLTCP_AGENT)
  357.     || (source == FULLTCP_APP && agent == FULLTCP_AGENT);
  358. }
  359. //----------------------------------------------------------------------
  360. // trafgen_type
  361. // EditorNetModel::checkAgentTrafficSourceCompatibility(const char * agent, const char * source)
  362. //----------------------------------------------------------------------
  363. bool
  364. EditorNetModel::checkAgentTrafficSourceCompatibility(const char * agent, const char * source) {
  365. return checkAgentTrafficSourceCompatibility(classifyAgent(agent),
  366. classifyTrafficSource(source));
  367. }
  368. //----------------------------------------------------------------------
  369. // int
  370. // EditorNetModel::addTrafficSource(TrafficSource * traffic_source,
  371. // Agent * agent)
  372. //----------------------------------------------------------------------
  373. int
  374. EditorNetModel::addTrafficSource(TrafficSource * traffic_source,
  375.                                  Agent * agent) {
  376. if (traffic_source && agent
  377.     && checkAgentTrafficSourceCompatibility(agent->name(), traffic_source->name())) {
  378. traffic_source->attachTo(agent);
  379. // Add to animations list so that it will be redrawn on all updates
  380. traffic_source->Animation::insert(&animations_);
  381. // Add to master list of all trafficsources_ which is used to 
  382. // look up a traffic source for editing purposes
  383. traffic_source->editornetmodel_next_ = traffic_sources_;
  384. traffic_sources_ = traffic_source;
  385. return TCL_OK;
  386. }
  387. return TCL_ERROR;
  388. }
  389. //----------------------------------------------------------------------
  390. // int
  391. // EditorNetModel::addTrafficSource(Agent * agent, char * type,
  392. // float cx, float cy)
  393. //----------------------------------------------------------------------
  394. int
  395. EditorNetModel::addTrafficSource(Agent * agent, const char * type,
  396.                                  float cx, float cy) {
  397. TrafficSource * traffic_source;
  398. if (agent) {
  399. traffic_source = new TrafficSource(type, agent->size());
  400. return addTrafficSource(traffic_source, agent);
  401. }
  402. return (TCL_ERROR);
  403. }
  404. //----------------------------------------------------------------------
  405. // TrafficSource *
  406. // EditorNetModel::lookupTrafficSource(int id)
  407. //----------------------------------------------------------------------
  408. TrafficSource *
  409. EditorNetModel::lookupTrafficSource(int id) {
  410. TrafficSource * ts;
  411. for (ts = traffic_sources_; ts; ts = ts->editornetmodel_next_) {
  412. if (ts->number() == id) {
  413. break;
  414. }
  415. }
  416. return ts;
  417. }
  418. //----------------------------------------------------------------------
  419. //----------------------------------------------------------------------
  420. int
  421. EditorNetModel::addLossModel(LossModel * loss_model, Edge * edge) {
  422. if (loss_model && edge) {
  423. edge->addLossModel(loss_model);
  424. loss_model->place();
  425. // Add to animations list so that it will be redrawn on all updates
  426. loss_model->Animation::insert(&animations_);
  427. // Add to master list of all lossmodels_ which is used to 
  428. // look up a lossmodel for editing purposes
  429. loss_model->next_lossmodel_ = lossmodels_;
  430. lossmodels_ = loss_model;
  431. }
  432. return TCL_OK;
  433. }
  434. //----------------------------------------------------------------------
  435. //----------------------------------------------------------------------
  436. int
  437. EditorNetModel::addLossModel(Edge * edge, const char * type,
  438.                              double cx, double cy) {
  439. LossModel * loss_model;
  440. if (edge && !edge->getLossModel()) {
  441. loss_model = new LossModel(type, edge->getSourceNode()->size());
  442. edge->addLossModel(loss_model);
  443. // Add to animations list so that it will be redrawn on all updates
  444. loss_model->Animation::insert(&animations_);
  445. // Add to master list of all lossmodels_ which is used to 
  446. // look up a lossmodel for editing purposes
  447. loss_model->next_lossmodel_ = lossmodels_;
  448. lossmodels_ = loss_model;
  449. }
  450. return (TCL_OK);
  451. }
  452. //----------------------------------------------------------------------
  453. // TrafficSource *
  454. // EditorNetModel::lookupLossModel(int id)
  455. //----------------------------------------------------------------------
  456. LossModel *
  457. EditorNetModel::lookupLossModel(int id) {
  458. LossModel * loss_model;
  459. for (loss_model = lossmodels_; 
  460.              loss_model;
  461.              loss_model = loss_model->next_lossmodel_) {
  462. if (loss_model->number() == id) {
  463. break;
  464. }
  465. }
  466. return loss_model;
  467. }
  468. //----------------------------------------------------------------------
  469. //----------------------------------------------------------------------
  470. QueueHandle * 
  471. EditorNetModel::addQueueHandle(Edge * edge) {
  472. QueueHandle * queue_handle;
  473. // Add queue handle for editing the edge's queue properties
  474. queue_handle = new QueueHandle(edge);
  475. edge->addQueueHandle(queue_handle);
  476. queue_handle->Animation::insert(&drawables_);
  477. queue_handle->next_queue_handle_ = queue_handles_;
  478. queue_handles_ = queue_handle;
  479. return queue_handle;
  480. }
  481. //----------------------------------------------------------------------
  482. //----------------------------------------------------------------------
  483. QueueHandle *
  484. EditorNetModel::addQueueHandle(Edge * edge, const char * type) {
  485. QueueHandle * queue_handle;
  486. queue_handle = addQueueHandle(edge);
  487. queue_handle->setType(type);
  488. return queue_handle;
  489. }
  490. //----------------------------------------------------------------------
  491. //
  492. //----------------------------------------------------------------------
  493. void EditorNetModel::setNodeProperty(int id, const char * value, const char * variable) {
  494. Node * node = lookupNode(id);
  495. if (node) {
  496. if (!strcmp(variable, "size_")) {
  497. node->size(strtod(value,NULL));
  498. } else if (!strcmp(variable, "color")) {
  499. node->init_color(value);
  500. } else if (!strcmp(variable, "dlabel_")) {
  501. node->dlabel(value);
  502. } else if (!strcmp(variable, "X_")) {
  503. node->place(strtod(value, NULL),node->y());
  504. } else if (!strcmp(variable, "Y_")) {
  505. node->place(node->x(), strtod(value, NULL));
  506. } else if (!strcmp(variable, "Z_")) {
  507. // 
  508. } else {
  509. fprintf(stderr, "EditorNetModel::setNodeProperty - unknown property %sn", variable);
  510. }
  511. } else {
  512. fprintf(stderr, "Node %d does not exist.n", id);
  513.      }
  514. }
  515. //----------------------------------------------------------------------
  516. //
  517. //----------------------------------------------------------------------
  518. void EditorNetModel::setAgentProperty(int id, const char * value, const char * variable) {
  519. Agent * agent = lookupAgent(id);
  520. if (agent) {
  521. if (!strcmp(variable, "windowInit_")) {
  522. // initial window size
  523. agent->windowInit(atoi(value));
  524. } else if (!strcmp(variable, "window_")) {
  525. // window size
  526. agent->window(atoi(value));
  527. } else if (!strcmp(variable, "maxcwnd_")) {
  528. // maximum cwnd_
  529. agent->maxcwnd(atoi(value));
  530. } else if (!strcmp(variable, "flowcolor_")) {
  531. // Flow ID + Color
  532. if ((strcmp(value, "(null)") == 0) || (strcmp(value, "") == 0)) {
  533. agent->flowcolor("black");
  534. } else {
  535. agent->flowcolor(value);
  536. } else if (!strcmp(variable, "packetSize_")) {
  537. agent->packetSize(atoi(value));
  538. } else {
  539. // fprintf(stderr, "EditorNetModel::setAgentProperty - unknown property %sn", variable);
  540. }
  541. } else {
  542. fprintf(stderr, "EditorNetModel::setAgentProperty - Nonexisting agent %d.n", id);
  543. }
  544. }
  545. //----------------------------------------------------------------------
  546. // void
  547. // EditorNetModel::setLinkProperty(int source_id, int destination_id, 
  548. //                                 char * value, char * variable)
  549. //----------------------------------------------------------------------
  550. void
  551. EditorNetModel::setLinkProperty(int source_id, int destination_id, 
  552.                                 const char * value, const char * variable) {
  553. Edge * edge = lookupEdge(source_id, destination_id);
  554. if (edge) {
  555. if (!strcmp(variable, "bandwidth_")) {
  556. edge->setBW(strtod(value,NULL));
  557. } else if (!strcmp(variable, "color_")) {
  558. edge->init_color(value);
  559. } else if (!strcmp(variable, "delay_")) {
  560. edge->setDelay(strtod(value,NULL));
  561. } else if (!strcmp(variable, "dlabel_")) {
  562. if (strcmp(value, "")) {
  563. edge->dlabel(value);
  564. }
  565. } else if (!strcmp(variable, "length_")) {
  566. edge->setLength(strtod(value,NULL));
  567. }
  568. }
  569. }
  570. //----------------------------------------------------------------------
  571. //----------------------------------------------------------------------
  572. void
  573. EditorNetModel::setQueueHandleProperty(int source_id, int destination_id,
  574.                                        const char * value, const char * variable) {
  575. Edge * edge;
  576. QueueHandle * queue;
  577. edge = lookupEdge(source_id, destination_id);
  578. if (edge) {
  579. queue = edge->getQueueHandle();
  580.   if (queue) {
  581. if (strcmp(variable, "type_") == 0) {
  582. queue->setType(value);
  583. } else if (strcmp(variable, "limit_") == 0) {
  584. queue->setLimit(atoi(value)); 
  585. } else if (strcmp(variable, "secsPerByte__") == 0) {
  586. queue->setSecondsPerByte(strtod(value,NULL));
  587. } else if (strcmp(variable, "maxqueue_") == 0) {
  588. queue->setMaxQueue(atoi(value));
  589. } else if (strcmp(variable, "buckets_") == 0) {
  590. queue->setBuckets(atoi(value));
  591. } else if (strcmp(variable, "blimit_") == 0) {
  592. queue->setSharedBufferSize(atoi(value));
  593. } else if (strcmp(variable, "quantum_") == 0) {
  594. queue->setQuantum(atoi(value));
  595. } else if (strcmp(variable, "mask_") == 0) {
  596. if (atoi(value) == 0) {
  597. queue->setMask(false);
  598. } else {
  599. queue->setMask(true);
  600. }
  601. } else if (strcmp(variable, "bytes_") == 0) {
  602. if (atoi(value) == 0) {
  603. queue->setBytes(false);
  604. } else {
  605. queue->setBytes(true);
  606. }
  607. } else if (strcmp(variable, "queue_in_bytes_") == 0) {
  608. if (atoi(value) == 0) {
  609. queue->setQueueInBytes(false);
  610. } else {
  611. queue->setQueueInBytes(true);
  612. }
  613. } else if (strcmp(variable, "thresh_") == 0) {
  614. queue->setThreshold(strtod(value,NULL));
  615. } else if (strcmp(variable, "max_thresh__") == 0) {
  616. queue->setMaximumThreshold(strtod(value,NULL));
  617. } else if (strcmp(variable, "mean_pktsize_") == 0) {
  618. queue->setMeanPacketSize(atoi(value));
  619. } else if (strcmp(variable, "q_weight_") == 0) {
  620. queue->setQueueWeight(strtod(value,NULL));
  621. } else if (strcmp(variable, "wait_") == 0) {
  622. if (atoi(value) == 0) {
  623. queue->setWaitInterval(false);
  624. } else {
  625. queue->setWaitInterval(true);
  626. }
  627. } else if (strcmp(variable, "linterm_") == 0) {
  628. queue->setLinterm(strtod(value,NULL));
  629. } else if (strcmp(variable, "setbit_") == 0) {
  630. if (atoi(value) == 0) {
  631. queue->setBitMarking(false);
  632. } else {
  633. queue->setBitMarking(true);
  634. }
  635. } else if (strcmp(variable, "drop_tail_") == 0) {
  636. if (atoi(value) == 0) {
  637. queue->setREDDropTail(false);
  638. } else {
  639. queue->setREDDropTail(true);
  640. }
  641. }
  642. } else {
  643. fprintf(stderr, "EditorNetModel::setQueueHandleProperty() - no queuehandle on edge.n");
  644. }
  645. }
  646. }
  647. //----------------------------------------------------------------------
  648. //----------------------------------------------------------------------
  649. void
  650. EditorNetModel::setTrafficSourceProperty(int id, const char * value,
  651.                                          const char * variable) {
  652. TrafficSource * trafficsource;
  653. trafficsource = lookupTrafficSource(id);
  654. if (trafficsource) {
  655. if (strcmp(variable, "start_") == 0) {
  656. //trafficsource->startAt(atof(value));
  657. trafficsource->timelist.add(strtod(value, NULL));
  658. } else if (strcmp(variable, "stop_") == 0) {
  659. //trafficsource->stopAt(atof(value));
  660. trafficsource->timelist.add(strtod(value, NULL));
  661. } else if (strcmp(variable, "interval_") == 0) {
  662. trafficsource->setInterval(atof(value));
  663. } else if (strcmp(variable, "maxpkts_") == 0) {
  664. trafficsource->setMaxpkts(atoi(value));
  665. } else if (strcmp(variable, "addtime") == 0) {
  666. trafficsource->timelist.add(atof(value));
  667. } else if (strcmp(variable, "removetime") == 0) {
  668. trafficsource->timelist.remove(atof(value));
  669. } else if (strcmp(variable, "timelist") == 0) {
  670. trafficsource->timelist.setList(value);
  671. // --- Exponential Properties
  672. } else if (strcmp(variable, "burst_time_") == 0) {
  673. trafficsource->setBurstTime(atoi(value));
  674. } else if (strcmp(variable, "idle_time_") == 0) {
  675. trafficsource->setIdleTime(atoi(value));
  676. } else if (strcmp(variable, "rate_") == 0) {
  677. trafficsource->setRate(atoi(value));
  678. // --- Pareto
  679. } else if (strcmp(variable, "shape_") == 0) {
  680. trafficsource->setShape(strtod(value, NULL));
  681. } else if (strcmp(variable, "title") == 0) {
  682. } else if (strcmp(variable, "agent_name") == 0) {
  683. } else {
  684. fprintf(stderr, " Unknown traffic source property %sn", variable);
  685. }
  686. } else {
  687. fprintf(stderr, " Unable to find traffic source with id %dn", id);
  688. }
  689. }
  690. //----------------------------------------------------------------------
  691. //----------------------------------------------------------------------
  692. void
  693. EditorNetModel::setLossModelProperty(int id, const char * value,
  694.                                      const char * variable) {
  695. LossModel * lossmodel;
  696.  
  697. lossmodel = lookupLossModel(id);
  698. if (lossmodel) {
  699. if (strcmp(variable, "period_") == 0) {
  700. lossmodel->setPeriod(strtod(value, NULL));
  701.  
  702. } else if (strcmp(variable, "offset_") == 0) {
  703. lossmodel->setOffset(strtod(value, NULL));
  704. } else if (strcmp(variable, "burstlen_") == 0) {
  705. lossmodel->setBurstLength(strtod(value, NULL));
  706. } else if (strcmp(variable, "rate_") == 0) {
  707. lossmodel->setRate(strtod(value, NULL));
  708. } else if (strcmp(variable, "loss_unit_") == 0) {
  709. lossmodel->setLossUnit(value);
  710. }
  711. } else {
  712. fprintf(stderr, " Unable to find loss model with id %dn", id);
  713. }
  714. }
  715. //----------------------------------------------------------------------
  716. //
  717. //----------------------------------------------------------------------
  718. int EditorNetModel::command(int argc, const char *const *argv) {
  719. FILE * file;
  720. Node * node;
  721. double time;
  722. if (argc == 2) {
  723. if (strcmp(argv[1], "layout") == 0) {
  724. layout();
  725. return (TCL_OK);
  726. }
  727. } else if (argc == 4) {
  728. // Write out ns script information
  729. if (strcmp(argv[1], "saveasns") == 0) {
  730. // argv syntax is as follows:
  731. // <net> saveasns filename filename_root
  732. file = fopen(argv[2], "w");
  733. if (file) {
  734. // fprintf(stderr, "Writing ns script to %s...",argv[2]);
  735. writeNsScript(file, argv[2], argv[3]);
  736. fclose(file);
  737. // fprintf(stderr, "done.n");
  738. } else {
  739. fprintf(stderr, "nam: Unable to open file: %sn", argv[2]);
  740. }
  741. return (TCL_OK);
  742. } else if (strcmp(argv[1], "removeNodeMovement") == 0) {
  743. node = lookupNode(atoi(argv[2]));
  744.                time = strtod(argv[3], NULL);
  745. node->removeMovementDestination(time);
  746. return TCL_OK;
  747. }
  748. return (NetModel::command(argc, argv));
  749. }
  750. //----------------------------------------------------------------------
  751. //----------------------------------------------------------------------
  752. void EditorNetModel::layout() {
  753. Node *n;
  754. for (n = nodes_; n != 0; n = n->next_)
  755. for (Edge* e = n->links(); e != 0; e = e->next_)
  756. placeEdge(e, n);
  757. }
  758. //----------------------------------------------------------------------
  759. // int 
  760. // EditorNetModel::saveAsNs(FILE * file)
  761. //----------------------------------------------------------------------
  762. int 
  763. EditorNetModel::writeNsScript(FILE * file, const char * filename, const char * filename_root) {
  764. Node * node;
  765. Edge * edge;
  766. LossModel * loss_model;
  767. Agent * agent;
  768. int number_of_wireless_nodes = 0;
  769. int number_of_wired_nodes = 0;
  770. double maximum_x, maximum_y;
  771. double node_x, node_y;
  772. maximum_x = 500;
  773. maximum_y = 500;
  774. // Add a disclaimer
  775. fprintf(file, "#------------------------------------------------------- n");
  776. fprintf(file, "# This ns script has been created by the nam editor.n");
  777. fprintf(file, "# If you edit it manually, the nam editor might notn");
  778. fprintf(file, "# be able to open it properly in the future.n");
  779. fprintf(file, "#n");
  780. fprintf(file, "# EDITING BY HAND IS AT YOUR OWN RISK!n");
  781. fprintf(file, "#------------------------------------------------------- n");
  782. fprintf(file, "# Create a new simulator object.n");
  783. fprintf(file, "set ns [new Simulator]n");
  784. fprintf(file, "# Create a nam trace datafile.n");
  785. fprintf(file, "set namfile [open %s.nam w]n", filename_root);
  786. fprintf(file, "$ns namtrace-all $namfilen");
  787. // write out node creation infomation
  788. fprintf(file, "n# Create wired nodes.n");
  789. for (node = nodes_; node; node = node->next_) {
  790. if (node->links()) {
  791. // Only write out wired links here
  792. node->writeNsScript(file);
  793. fprintf(file, "n");
  794. number_of_wired_nodes++;
  795. } else {
  796. // If a node has no links it must be a wireless node
  797. number_of_wireless_nodes++;
  798. }
  799. // Find maximum node mobility and placement range
  800. node_x = node->getMaximumX();
  801. node_y = node->getMaximumY();
  802. if (node_x > maximum_x) {
  803. // Add some extra space to be sure node is within
  804. // wireless boundary
  805. maximum_x = node_x + 2.0*node->size();
  806. }
  807. if (node_y > maximum_y) {
  808. // Add some extra space to be sure node is within
  809. // wireless boundary
  810. maximum_y = node_y + 2.0*node->size();
  811. }
  812. }
  813. if (number_of_wireless_nodes > 0) {
  814. fprintf(file, "n# ----- Setup wireless environment. ----n");
  815. fprintf(file, "set wireless_tracefile [open %s.trace w]n", filename_root);
  816. fprintf(file, "set topography [new Topography]n");
  817. fprintf(file, "$ns trace-all $wireless_tracefilen");
  818. fprintf(file, "$ns namtrace-all-wireless $namfile %f %fn", maximum_x, maximum_y);
  819. fprintf(file, "$topography load_flatgrid %f %fn", maximum_x, maximum_y);
  820. fprintf(file, "#n");
  821. fprintf(file, "# Create Godn");
  822. fprintf(file, "#n");
  823. fprintf(file, "set god_ [create-god %d]n", number_of_wireless_nodes);
  824. fprintf(file, "#global node settingn");
  825. fprintf(file, "$ns node-config -adhocRouting DSR \n");
  826. fprintf(file, "                 -llType LL \n");
  827. fprintf(file, "                 -macType Mac/802_11 \n");
  828. fprintf(file, "                 -ifqType Queue/DropTail/PriQueue \n");
  829. fprintf(file, "                 -ifqLen 50 \n");
  830. fprintf(file, "                 -antType Antenna/OmniAntenna \n");
  831. fprintf(file, "                 -propType Propagation/TwoRayGround \n");
  832. fprintf(file, "                 -phyType Phy/WirelessPhy \n");
  833. fprintf(file, "                 -channel [new Channel/WirelessChannel] \n");
  834. fprintf(file, "                 -topoInstance $topography \n");
  835. fprintf(file, "                 -agentTrace ON \n");
  836. fprintf(file, "                 -routerTrace OFF \n");
  837. fprintf(file, "                 -macTrace ONn");
  838. fprintf(file, "n# Create wireless nodes.n");
  839. for (node = nodes_; node; node = node->next_) {
  840. if (!node->links()) {
  841. node->writeNsScript(file);
  842. node->writeNsMovement(file);
  843. }
  844. }
  845. }
  846. // write out link information
  847. fprintf(file, "n# Create links between nodes.n");
  848. for (node = nodes_; node ; node = node->next_) {
  849. for (edge = node->links(); edge; edge = edge->next_) {
  850. edge->writeNsScript(file);
  851. }
  852. }
  853. // Write out lossmodel information
  854. fprintf(file, "# Add Link Loss Modelsn");
  855. for (loss_model = lossmodels_;
  856. loss_model;
  857. loss_model = loss_model->next_lossmodel_) {
  858. loss_model->writeNsDefinitionScript(file);
  859. }
  860. // write out agents and it's traffic sources
  861. fprintf(file, "n# Create agents.n");
  862. for (node = nodes_; node; node = node->next_) {
  863. for (agent = node->agents(); agent; agent = agent->next_) {
  864. agent->writeNsDefinitionScript(file);
  865. }
  866. }
  867. // Write out agent connections
  868. // An agent can connect to only one other agent
  869. fprintf(file, "n# Connect agents.n");
  870. for (node = nodes_; node; node = node->next_) {
  871. for (agent = node->agents(); agent; agent = agent->next_) {
  872. agent->writeNsConnectionScript(file);
  873. }
  874. }
  875. // Find time at which to stop the simulation
  876. // for (ts = traffic_sources_; ts; ts = ts->editornetmodel_next_) {
  877. // if (finish_time < ts->stopAt()) {
  878. // finish_time = ts->stopAt();
  879. // }
  880. // }
  881. fprintf(file, "# Run the simulationn");
  882. fprintf(file, "proc finish {} {n global ns namfilen $ns flush-tracen");
  883. fprintf(file, " close $namfilen exec nam -r %fus %s.nam & n exit 0n }n", playback_speed_, filename_root);
  884. //fprintf(file, "$ns at %f "finish"n", finish_time);
  885. fprintf(file, "$ns at %f "finish"n", maximum_simulation_time_);
  886. fprintf(file, "$ns runn");
  887. return 0;
  888. }
  889. //----------------------------------------------------------------------
  890. // void
  891. // EditorNetModel::removeNode(Node *n)
  892. //  - remove node n from the nodes_ list and delete it
  893. //----------------------------------------------------------------------
  894. void EditorNetModel::removeNode(Node *n) {
  895. Node * previous, * run;
  896. Edge * edge;
  897. Agent * agent;
  898. previous = nodes_;  
  899. for (run = nodes_; run; run = run->next_) {
  900. if (n->num() == run->num()) {
  901. // when deleting the last node
  902. if (run->num() == nodes_->num()) {
  903. nodes_ = nodes_->next_;
  904. break;
  905. } else {
  906. previous->next_ = run->next_; 
  907. break;
  908. }
  909. }
  910. previous = run;
  911. }
  912. run->next_ = NULL;
  913. // Remove it from list of drawables
  914. run->detach();
  915. // delete edges of the nodes_
  916. for (edge = run->links(); edge != 0; edge = edge->next_) {
  917. removeLink(edge);
  918. }
  919. // delete agents on the nodes_
  920. for (agent = run->agents(); agent != 0; agent = agent->next_) {
  921. removeAgent(agent);
  922. }
  923. delete run;
  924. }
  925. //----------------------------------------------------------------------
  926. // void
  927. // EditorNetModel::removeLink(Edge *e)
  928. // 
  929. //----------------------------------------------------------------------
  930. void
  931. EditorNetModel::removeLink(Edge *e) {
  932. EdgeHashNode * h, * g;
  933. Edge * e1, * e2;
  934.      LossModel * lossmodel;
  935. int src = e->src();
  936. int dst = e->dst();
  937. h = lookupEdgeHashNode(src, dst);
  938. g = lookupEdgeHashNode(dst, src);
  939. if (h == 0 || g == 0) {
  940. // h,g = 0 or h,g !=0
  941. return;
  942. e1 = h->edge;
  943. e2 = g->edge;
  944.      lossmodel = e1->getLossModel();
  945.      if (lossmodel) {
  946.        removeLossModel(lossmodel);
  947.      }
  948.  
  949.      lossmodel = e2->getLossModel();
  950.      if (lossmodel) {
  951.        removeLossModel(lossmodel);
  952.      }
  953.      
  954. // defined in netmodel.cc
  955. removeEdge(e1);
  956. removeEdge(e2);
  957.  
  958. e1->detach();
  959. e2->detach();
  960.  
  961. Node* srcnode = e1->start();
  962. Node* dstnode = e2->start();
  963. // it is a duplex by default
  964. srcnode->delete_link(e1);
  965. dstnode->delete_link(e2); 
  966. delete e1;
  967. delete e2;
  968. }
  969. //----------------------------------------------------------------------
  970. // void 
  971. // EditorNetModel::removeAgent(Agent *a)
  972. //  - removes and deletes an Agent and all of its Traffic Sources
  973. //----------------------------------------------------------------------
  974. void 
  975. EditorNetModel::removeAgent(Agent *a) {
  976. Node * n;
  977. TrafficSource * ts, * next_ts;
  978. n = a->node_;
  979. if (a->AgentPartner_ != NULL) {
  980. a->AgentPartner_->AgentPartner_ = NULL;
  981. a->AgentPartner_->AgentRole_ = 0;
  982. }
  983. n->delete_agent(a);
  984. a->detach();
  985. for (ts = a->traffic_sources_; ts; ts = next_ts) {
  986. // Save next traffic source in list since this
  987. // traffic source will be deleted in removeTrafficSource
  988. next_ts = ts->next_;
  989. removeTrafficSource(ts);
  990. }
  991. delete a;
  992. }
  993. //----------------------------------------------------------------------
  994. // void 
  995. // EditorNetModel::removeTrafficSource(TrafficSource * ts) {
  996. //----------------------------------------------------------------------
  997. void 
  998. EditorNetModel::removeTrafficSource(TrafficSource * ts) {
  999. TrafficSource * run, * previous;
  1000. // Run down the list of traffic sources
  1001. previous = NULL;
  1002. for (run = traffic_sources_; run; run = run->editornetmodel_next_) {
  1003. if (run == ts) {
  1004. break;
  1005. }
  1006. previous = run;
  1007. }
  1008. if (previous) {
  1009. previous->editornetmodel_next_ = ts->editornetmodel_next_;
  1010. } else {
  1011. if (run == traffic_sources_) {
  1012. // ts is at the front of the list
  1013. traffic_sources_ = ts->editornetmodel_next_;
  1014. }
  1015. }
  1016. ts->editornetmodel_next_ = NULL;
  1017. ts->removeFromAgent();
  1018. delete ts; 
  1019. }
  1020. //----------------------------------------------------------------------
  1021. //----------------------------------------------------------------------
  1022. void 
  1023. EditorNetModel::removeLossModel(LossModel * lossmodel) {
  1024. LossModel * run, * previous;
  1025. // Run down the list of lossmodels
  1026. previous = NULL;
  1027. for (run = lossmodels_; run; run = run->next_lossmodel_) {
  1028. if (run == lossmodel) {
  1029. break;
  1030. }
  1031. previous = run;
  1032. }
  1033. if (previous) {
  1034. previous->next_lossmodel_ = lossmodel->next_lossmodel_;
  1035. } else {
  1036. if (run == lossmodels_) {
  1037. // ts is at the front of the list
  1038. lossmodels_ = lossmodel->next_lossmodel_;
  1039. }
  1040. }
  1041. lossmodel->next_lossmodel_ = NULL;
  1042. lossmodel->clearEdge();
  1043. delete lossmodel;