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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001 University of Southern California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *      This product includes software developed by the Information Sciences
  16.  *      Institute of the University of Southern California.
  17.  * 4. Neither the name of the University nor of the Institute may be used
  18.  *    to endorse or promote products derived from this software without
  19.  *    specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  */
  34. #include <stdlib.h>
  35. #include <math.h>
  36. #ifdef WIN32
  37. #include <windows.h>
  38. #endif
  39. #include "netview.h"
  40. #include "node.h"
  41. #include "edge.h"
  42. #include "paint.h"
  43. #include "sincos.h"
  44. #include "queuehandle.h"
  45. #define PROPERTY_STRING_LENGTH 256
  46. static int g_queuehandle_number = 1;
  47. //----------------------------------------------------------------------
  48. //  Wrapper for creating QueueHandles in OTcl
  49. //----------------------------------------------------------------------
  50. static class QueueHandleClass : public TclClass {
  51. public:
  52.   QueueHandleClass() : TclClass("QueueHandle") {}
  53.   TclObject* create(int argc, const char * const * argv) {
  54.     const char * type;
  55.     int id;
  56.     double size;
  57.     type = argv[4];
  58.     id = strtol(argv[5], NULL, 10);
  59.     size = strtod(argv[6], NULL);
  60.     
  61.     return (new QueueHandle(type, id, size));
  62.   }
  63. } class_queuehandle;
  64. //----------------------------------------------------------------------
  65. //----------------------------------------------------------------------
  66. QueueHandle::QueueHandle(const char* type, int id, double _size) :
  67.   Animation(0, 0) {
  68.   setDefaults();
  69.   number_ = id;
  70.   if (g_queuehandle_number++ <= id) {
  71.     g_queuehandle_number = id + 1;
  72.   }
  73.   width_ = 50.0;
  74.   height_ = size_/2.0;
  75.   size_ = _size;
  76.   size(_size);
  77. }
  78. //----------------------------------------------------------------------
  79. //----------------------------------------------------------------------
  80. QueueHandle::QueueHandle(Edge * edge) :
  81.   Animation(0, 0) {
  82.   Node * node;
  83.   setDefaults();
  84.   edge_ = edge;
  85.   
  86.   number_ = g_queuehandle_number;
  87.   g_queuehandle_number++;
  88.   node = edge_->getSourceNode();
  89.   if (node) {
  90.    size(node->size());
  91.   } else {
  92.    size(10.0);
  93.   }
  94.   limit_ = 20;
  95.   
  96.   // FQ
  97.   secsPerByte_ = 0.0;
  98.   // Stocastic Fair Queue
  99.   maxqueue_ = 40;
  100.   buckets_ = 16;
  101.   // DRR
  102.   blimit_ = 2500;
  103.   quantum_ = 250;
  104.   mask_ = false;
  105.   // RED
  106.   bytes_ = false;
  107.   queue_in_bytes_ = false;
  108.   thresh_ = 5.0;
  109.   maxthresh_ = 15.0;
  110.   mean_pktsize_ = 500;
  111.   q_weight_ = 0.002;
  112.   wait_ = false;
  113.   linterm_ = 30.0;
  114.   setbit_ = false;
  115.   drop_tail_ = false;
  116. }
  117. //----------------------------------------------------------------------
  118. //----------------------------------------------------------------------
  119. void
  120. QueueHandle::setDefaults() {
  121.   next_queue_handle_ = NULL;
  122.   edge_ = NULL;
  123.   x_ = 0.0;
  124.   y_ = 0.0;
  125.   angle_ = NO_ANGLE;
  126.   color_ = "black";
  127.   paint_ = Paint::instance()->thin();
  128.   width_ = 10.0;
  129.   height_ = 10.0;
  130.   type_ = NULL;
  131.   ns_type_ = NULL;
  132.   setType("DropTail");
  133. }
  134. //----------------------------------------------------------------------
  135. // double 
  136. // QueueHandle::distance(double x, double y) const {
  137. //----------------------------------------------------------------------
  138. double
  139. QueueHandle::distance(double x, double y) const {
  140.   return sqrt((x_-x)*(x_-x) + (y_-y)*(y_-y));
  141. }
  142. //----------------------------------------------------------------------
  143. //----------------------------------------------------------------------
  144. void
  145. QueueHandle::color(const char * name) {
  146.   if (color_) {
  147.     delete []color_;
  148.   }
  149.   color_ = new char[strlen(name) + 1];
  150.   strcpy(color_, name);
  151. }
  152. //----------------------------------------------------------------------
  153. //----------------------------------------------------------------------
  154. void QueueHandle::size(double s) {
  155.   size_ = s;
  156.   width_ = 10.0 + 25.0;
  157.   height_ = s/2.0;
  158.   update_bb();
  159. }
  160. //----------------------------------------------------------------------
  161. //----------------------------------------------------------------------
  162. void QueueHandle::update_bb() {
  163.   bb_.xmin = x_;
  164.   bb_.ymin = y_;
  165.   bb_.xmax = x_ + width_;
  166.   bb_.ymax = y_ + height_;
  167. }
  168. //----------------------------------------------------------------------
  169. //----------------------------------------------------------------------
  170. void QueueHandle::setType(const char* type) {
  171.         const char * expanded_type;
  172.         // Expand Ns Type Names 
  173. if (!strcmp(type, "FQ")) {
  174.           expanded_type = "FairQueue";
  175. } else if (!strcmp(type, "SFQ")) {
  176.           expanded_type = "StocasticFairQueue";
  177. } else if (!strcmp(type, "DRR")) {
  178.           expanded_type = "DeficitRoundRobin";
  179.         } else {
  180.           expanded_type = type;
  181.         }
  182.   
  183.         // Deleted existing type strings
  184. if (type_) {
  185. delete[] type_;
  186. }
  187. if (ns_type_) {
  188. delete[] ns_type_;
  189. ns_type_ = NULL;
  190. }
  191.         // Set type and ns type to new strings
  192. type_ = new char[strlen(expanded_type) + 1];
  193. strcpy(type_, expanded_type);
  194. if (!strcmp(expanded_type, "DropTail")) {
  195. ns_type_ = new char[strlen("DropTail") + 1];
  196. strcpy(ns_type_, "DropTail");
  197. } else if (!strcmp(expanded_type, "FairQueue")) {
  198. ns_type_ = new char[strlen("FQ") + 1];
  199. strcpy(ns_type_, "FQ");
  200. } else if (!strcmp(expanded_type, "StocasticFairQueue")) {
  201. ns_type_ = new char[strlen("SFQ") + 1];
  202. strcpy(ns_type_, "SFQ");
  203. } else if (!strcmp(expanded_type, "DeficitRoundRobin")) {
  204. ns_type_ = new char[strlen("DRR") + 1];
  205. strcpy(ns_type_, "DRR");
  206. } else if (!strcmp(expanded_type, "RED")) {
  207. ns_type_ = new char[strlen("RED") + 1];
  208. strcpy(ns_type_, "RED");
  209. }
  210. }
  211. //----------------------------------------------------------------------
  212. //----------------------------------------------------------------------
  213. void QueueHandle::reset(double) {
  214.   paint_ = Paint::instance()->thick();
  215. }
  216. //----------------------------------------------------------------------
  217. // void
  218. // QueueHandle::attach(Agent * agent)
  219. //----------------------------------------------------------------------
  220. void
  221. QueueHandle::attachTo(Edge * edge) {
  222.   edge_ = edge; 
  223.   place();
  224. }
  225. //----------------------------------------------------------------------
  226. //----------------------------------------------------------------------
  227. void QueueHandle::clearEdge() {
  228.   edge_ = NULL;
  229. }
  230. //----------------------------------------------------------------------
  231. // void
  232. // QueueHandle::place()  
  233. //----------------------------------------------------------------------
  234. void
  235. QueueHandle::place() {
  236. double sine, cosine, angle;
  237. if (edge_) {
  238. angle = edge_->angle();
  239. sine = sin(angle);
  240. cosine = cos(angle);
  241. if ((angle > 0.0 && angle < M_PI/2.0) ||
  242.     (angle < M_PI/-2.0 && angle > -1.0*M_PI)) {
  243. x_ = edge_->x() + cosine * height_;
  244. y_ = edge_->y() + sine * height_ - height_;
  245. } else {
  246. x_ = edge_->x() + cosine * height_;
  247. y_ = edge_->y() + sine * height_;
  248. }
  249. }
  250.      update_bb();
  251. }
  252. //----------------------------------------------------------------------
  253. //----------------------------------------------------------------------
  254. const char* QueueHandle::info() const {
  255.   static char text[128];
  256.   sprintf(text, "Queue Type: %s %d->%d", type_, edge_->src(), edge_->dst());
  257.   return (text);
  258. }
  259. //----------------------------------------------------------------------
  260. // int 
  261. // QueueHandle::inside(double, float px, float py) const 
  262. //   - Check to see if point (px, py) is within the Loss Model box
  263. //----------------------------------------------------------------------
  264. int 
  265. QueueHandle::inside(double, float px, float py) const {
  266.   return (px >= x_ && 
  267.           px <= (x_ + width_) &&
  268.           py >= y_ && 
  269.           py <= (y_ + height_));
  270. }
  271. //----------------------------------------------------------------------
  272. // void
  273. // QueueHandle::draw(View * view, double ) const
  274. //   - Draw the Loss Model on its edge
  275. //----------------------------------------------------------------------
  276. void
  277. QueueHandle::draw(View * view, double time) {
  278. double label_width, label_height, label_x, label_y;
  279. char * label = "Q";
  280. if (edge_) {
  281. // Draw label centered inside of border
  282. // We have to keep calculting the label width and height because
  283. // we have no way of knowing if the user has zoomed in or out 
  284. // on the current network view.
  285. label_height = 0.9 * height_;
  286. label_width = view->getStringWidth(label, label_height);
  287. // Add 10% of padding to width for the box
  288. setWidth(1.1 * label_width);
  289. // Center label in box
  290. label_x = x_ + (width_ - label_width);
  291. label_y = y_ + (height_ - label_height);
  292. view->string(label, label_x , label_y, label_height, NULL);
  293. update_bb();
  294. // Draw Rectangle Border
  295. view->rect(x_, y_, x_ + width_, y_ + height_ , paint_);
  296. }
  297. }
  298. //----------------------------------------------------------------------
  299. // int
  300. // QueueHandle::writeNsScript(FILE * file)
  301. //  - outputs ns script format for creating loss models
  302. //----------------------------------------------------------------------
  303. int
  304. QueueHandle::writeNsScript(FILE * file) {
  305. if (edge_) {
  306. fprintf(file, "# Set Queue Properties for link %d->%dn", edge_->src(), edge_->dst());
  307. if (!strcmp(type_, "DropTail")) {
  308. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set limit_ %dn", edge_->src(), edge_->dst(), limit_);
  309. } else if (!strcmp(type_, "FairQueue")) {
  310. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set secsPerByte_ %fn", edge_->src(), edge_->dst(), secsPerByte_);
  311. } else if (!strcmp(type_, "StocasticFairQueue")) {
  312. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set maxqueue_ %dn", edge_->src(), edge_->dst(), maxqueue_);
  313. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set buckets_ %dn", edge_->src(), edge_->dst(), buckets_);
  314. } else if (!strcmp(type_, "DeficitRoundRobin")) {
  315. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set buckets_ %dn", edge_->src(), edge_->dst(), buckets_);
  316. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set blimit_ %dn", edge_->src(), edge_->dst(), blimit_);
  317. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set quantum_ %dn", edge_->src(), edge_->dst(), quantum_);
  318.                         if (mask_) {
  319.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set mask_ 1n", edge_->src(), edge_->dst());
  320.                         }
  321. } else if (!strcmp(type_, "RED")) {
  322.                         if (bytes_) {
  323.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set bytes_ 1n", edge_->src(), edge_->dst());
  324.                         }
  325.                         if (queue_in_bytes_) {
  326.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set queue_in_bytes_ 1n", edge_->src(), edge_->dst());
  327.                         }
  328. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set thresh_ %fn", edge_->src(), edge_->dst(), thresh_);
  329. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set maxthresh_ %fn", edge_->src(), edge_->dst(), maxthresh_);
  330. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set mean_pktsize_ %dn", edge_->src(), edge_->dst(), mean_pktsize_);
  331. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set q_weight_ %fn", edge_->src(), edge_->dst(), q_weight_);
  332.                         if (wait_) {
  333.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set queue_in_bytes_ 1n", edge_->src(), edge_->dst());
  334.                         }
  335. fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set linterm_ %fn", edge_->src(), edge_->dst(), linterm_);
  336.                         if (setbit_) {
  337.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set setbit_ 1n", edge_->src(), edge_->dst());
  338.                         }
  339.                         if (queue_in_bytes_) {
  340.         fprintf(file, "[[$ns link $node(%d) $node(%d)] queue] set drop_tail_ 1n", edge_->src(), edge_->dst());
  341.                         }
  342. }
  343. }
  344.   return 0;
  345. }
  346. //----------------------------------------------------------------------
  347. // QueueHandle::property()
  348. //   - return the list of queue configuration parameters
  349. //     (properties) to be shown in the property edit window
  350. //----------------------------------------------------------------------
  351. const char*
  352. QueueHandle::property() {
  353.   return getProperties(type_);
  354. }
  355.   
  356. //----------------------------------------------------------------------
  357. // QueueHandle::property()
  358. //   - return the list of queue configuration parameters
  359. //     (properties) to be shown in the property edit window
  360. //   - This is used if the queue type is changed to a different type
  361. //     so we can give the properties related to that specific type of 
  362. //     queue to which we have switched 
  363. //----------------------------------------------------------------------
  364. const char *
  365. QueueHandle::getProperties(char * type) {
  366.   static char text[PROPERTY_STRING_LENGTH];
  367.   char * property_list;
  368.   int total_written = 0;
  369.   // object type, id and header info
  370.   property_list = text;
  371.   total_written = sprintf(text,
  372.           "{"Queue: %s %d->%d" title title "QueueHandle %d-%d"} ",
  373.           type_, edge_->src(), edge_->dst(), edge_->src(), edge_->dst());
  374.   property_list = &text[strlen(text)];
  375.   sprintf(property_list, "{"Queue Type" type_ drop_down_list {{%s} {DropTail FairQueue StocasticFairQueue DeficitRoundRobin RED}}} ", type);
  376.   if (strcmp(type, "DropTail") == 0) {
  377.     property_list = &text[strlen(text)];
  378.     sprintf(property_list, "{"Maximum Queue Size" limit_ text %d} ",
  379.                            limit_);
  380.   } else if (strcmp(type, "FairQueue") == 0) {
  381.     property_list = &text[strlen(text)];
  382.     sprintf(property_list, "{"Seconds Per Byte" secsPerByte_ text %f} ",
  383.                            secsPerByte_); 
  384.   } else if (strcmp(type, "StocasticFairQueue") == 0) {
  385.     property_list = &text[strlen(text)];
  386.     sprintf(property_list, "{"Maximum Queue Size" maxqueue_ text %d} ",
  387.                            maxqueue_);
  388.     property_list = &text[strlen(text)];
  389.     sprintf(property_list, "{"Number of Buckets" buckets_ text %d} ",
  390.                            buckets_);
  391.   } else if (strcmp(type, "DeficitRoundRobin") == 0) {
  392.     property_list = &text[strlen(text)];
  393.     sprintf(property_list, "{"Number of Buckets" buckets_ text %d} ",
  394.                            buckets_);
  395.     property_list = &text[strlen(text)];
  396.     sprintf(property_list, "{"Shared Buffer Size" blimit_ text %d} ",
  397.                            blimit_);
  398.     property_list = &text[strlen(text)];
  399.     sprintf(property_list, "{"Flow Quantum" quantum_ text %d} ",
  400.                            quantum_);
  401.     property_list = &text[strlen(text)];
  402.     sprintf(property_list, "{"Exclude Port Number from Flow Identification" mask_ checkbox %d} ",
  403.                            mask_);
  404.   } else if (strcmp(type, "RED") == 0) {
  405.     property_list = &text[strlen(text)];
  406.     sprintf(property_list, "{"Enable Byte Mode RED" bytes_ checkbox %d} ",
  407.                            bytes_);
  408.     property_list = &text[strlen(text)];
  409.     sprintf(property_list, "{"Queue in Bytes" queue_in_bytes_ checkbox %d} ",
  410.                            queue_in_bytes_);
  411.     property_list = &text[strlen(text)];
  412.     sprintf(property_list, "{"Wait Interval Between Drops" wait_ checkbox %d} ",
  413.                            wait_);
  414.     property_list = &text[strlen(text)];
  415.     sprintf(property_list, "{"Mark Packets for Congestion Instead of Dropping" setbit_ checkbox %d} ",
  416.                            setbit_);
  417.     property_list = &text[strlen(text)];
  418.     sprintf(property_list, "{"Use Drop Tail instead of Random Drop" drop_tail_ checkbox %d} ",
  419.                            drop_tail_);
  420.     property_list = &text[strlen(text)];
  421.     sprintf(property_list, "{"Minimum Threshhold for Average Queue Size" thresh_ text %g} ", 
  422.                            thresh_); 
  423.     property_list = &text[strlen(text)];
  424.     sprintf(property_list, "{"Maximum Threshhold for Average Queue Size" maxthresh_ text %g} ", 
  425.                            maxthresh_);
  426.     property_list = &text[strlen(text)];
  427.     sprintf(property_list, "{"Estimate for Average Queue Size" mean_pktsize_ text %d} ", 
  428.                            mean_pktsize_);
  429.     property_list = &text[strlen(text)];
  430.     sprintf(property_list, "{"Queue Weight" q_weight_ text %g} ", 
  431.                            q_weight_);
  432.     property_list = &text[strlen(text)];
  433.     sprintf(property_list, "{"Maximum Drop Probability (1/linterm_)" linterm_ text %g} ", 
  434.                            linterm_);
  435.   }
  436.   return(text);
  437. }
  438. //----------------------------------------------------------------------
  439. //----------------------------------------------------------------------
  440. int QueueHandle::command(int argc, const char * const * argv) {
  441.   return TCL_OK;
  442. }