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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /* 
  3.  * Copyright 2002, The University of North Carolina at Chapel Hill
  4.  * 
  5.  * Redistribution and use in source and binary forms, with or without 
  6.  * modification, are permitted provided that the following conditions are met:
  7.  * 
  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. The name of the author may not be used to endorse or promote 
  14.  * products derived from this software without specific prior written 
  15.  * permission.
  16.  * 
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  20.  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 
  21.  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  22.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  23.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  24.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  25.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  26.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  27.  * POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29. /*
  30.  * Reference
  31.  *     Stochastic Models for Generating Synthetic HTTP Source Traffic 
  32.  *     J. Cao, W.S. Cleveland, Y. Gao, K. Jeffay, F.D. Smith, and M.C. Weigle 
  33.  *     IEEE INFOCOM 2004.
  34.  *
  35.  * Documentation available at http://dirt.cs.unc.edu/delaybox/
  36.  * 
  37.  * Contacts: Michele Weigle (mcweigle@cs.unc.edu),
  38.  *           Kevin Jeffay (jeffay@cs.unc.edu)
  39.  */
  40. /*
  41.  * Overview
  42.  * --------
  43.  * Node/DelayBox consists of a Classifier/DelayBox that sits
  44.  * in front of the default classifier and delays and/or drops
  45.  * packets.  After a packet has been delayed, Classifier/DelayBox
  46.  * passes the packet on to the default classifier.
  47.  *
  48.  * There are two tables:
  49.  *   1) Rule Table - specified in the simulation script by user
  50.  *                 - gives an outline of how flows between a pair 
  51.  *                   of hosts should be treated (includes delay/loss 
  52.  *                   distributions)
  53.  *                 - entry for each src/dst pair
  54.  *                 - fields are src, dst, delayRV, lossRV, link speed RV
  55.  *
  56.  *   2) Flow Table - created by Node/DelayBox
  57.  *                 - specifies exactly how each flow should be handled
  58.  *                 - values are obtained by sampling from the distributions
  59.  *                   given in the rule table
  60.  *                 - entry for each flow
  61.  *                 - fields are src, dst, flow id, delay, loss, link
  62.  *                   speed, ptr to queue
  63.  *  
  64.  * There are also a set of queues that handle delaying packets.  There
  65.  * is one queue per flow.  Each flow table entry contains a pointer to
  66.  * the head of the flow's queue.
  67.  *
  68.  * Flows are defined as the first SYN of a new flow id to the first
  69.  * FIN received.  Packets after the first FIN that complete the 
  70.  * connection shutdown sequence are NOT delayed or dropped.
  71.  *
  72.  * Use of DelayBox in a Tcl Script
  73.  * -------------------------------
  74.  * Creating Node/DelayBox:    set db [$ns DelayBox]
  75.  *
  76.  * Adding rules:
  77.  * $db add-rule [$n(0) id] [$n(1) id] $client_delay $loss_rate $client_bw
  78.  * $db add-rule [$n(1) id] [$n(0) id] $server_delay $loss_rate $server_bw
  79.  *
  80.  * List current rules:        $db list-rules
  81.  * List current flows:        $db list-flows
  82.  *
  83.  */
  84. #include <tclcl.h>
  85. #include "delaybox.h"
  86. #include "ip.h"
  87. #include "tcp.h"
  88. #include "ranvar.h"
  89. // for packet_string() and recv()
  90. #define TH_FIN  0x01        /* FIN: closing a connection */
  91. #define TH_SYN  0x02        /* SYN: starting a connection */
  92. #define TH_PUSH 0x08        /* PUSH: used here to "deliver" data */
  93. #define TH_ACK  0x10        /* ACK: ack number is valid */
  94. #define MbPS2BPS_FACTOR 125000
  95. TclObject* lookup_obj(const char* name) {
  96. TclObject* obj = Tcl::instance().lookup(name);
  97. if (obj == NULL) 
  98. fprintf(stderr, "Bad object name %sn", name);
  99. return obj;
  100. }
  101. /*::::::::::::::::: DELAYBOX PAIR :::::::::::::::::::::::::::::::::::::*/
  102. bool DelayBoxPair::operator< (const DelayBoxPair& p2) const
  103. {
  104. if (src_ != p2.src_)
  105. return (src_ < p2.src_);
  106. else if (dst_ != p2.dst_)
  107. return (dst_ < p2.dst_);
  108. else
  109. return (fid_ < p2.fid_);
  110. }
  111. bool DelayBoxPair::operator== (const DelayBoxPair& p2) const
  112. {
  113. if (src_ != p2.src_)
  114. return false;
  115. else if (dst_ != p2.dst_)
  116. return false;
  117. else if ((fid_ == 0) || (p2.fid_ == 0))
  118. return true;
  119. else
  120. return false;
  121. }
  122. DelayBoxPair::DelayBoxPair(const DelayBoxPair& p)
  123. {
  124. src_ = p.src_;
  125. dst_ = p.dst_;
  126. fid_ = p.fid_;
  127. }
  128. const DelayBoxPair& DelayBoxPair::operator=(const DelayBoxPair& p)
  129. {
  130. if (this != &p) {
  131. src_ = p.src_;
  132. dst_ = p.dst_;
  133. fid_ = p.fid_;
  134. }
  135. return (*this);
  136. }
  137. void DelayBoxPair::format (char *str) const
  138. {
  139. sprintf (str, "%d > %d: %d", src_, dst_, fid_);
  140. }
  141. void DelayBoxPair::format_short(char *str) const
  142. {
  143. sprintf (str, "%-3d %-3d %-5d", src_, dst_, fid_);
  144. }
  145. /*::::::::::::::::: DELAYBOX FLOW :::::::::::::::::::::::::::::::::::::*/
  146. DelayBoxFlow::DelayBoxFlow(const DelayBoxFlow& f)
  147. {
  148. delay_ = f.delay_;
  149. loss_ = f.loss_;
  150. linkspd_ = f.linkspd_;
  151. queue_ = f.queue_;
  152. timer_ = f.timer_;
  153. }
  154. void DelayBoxFlow::format(char *str)
  155. {
  156. if (linkspd_ > 0)
  157. sprintf (str, "%8.3f ms delay  %5.2f%% loss  %8.3f Mbps", 
  158.  delay_ * 1000.0, loss_, linkspd_ / MbPS2BPS_FACTOR);
  159. else
  160. sprintf (str, "%8.3f ms delay  %5.2f%% loss", 
  161.  delay_ * 1000.0, loss_);
  162. }
  163. void DelayBoxFlow::format_delay(char *str)
  164. {
  165. sprintf (str, "%8.3f", delay_ * 1000.0);
  166. }
  167. /*::::::::::::::::: DELAYBOX NODE :::::::::::::::::::::::::::::::::::::*/
  168. static class DelayBoxNodeClass : public TclClass {
  169. public:
  170. DelayBoxNodeClass() : TclClass("Node/DelayBox") {};
  171. TclObject* create(int, const char*const*) {
  172. return (new DelayBoxNode);
  173. }
  174. } class_delayboxnode;
  175. DelayBoxNode::DelayBoxNode() : Node()
  176. {
  177. classifier_ = NULL;
  178. }
  179. DelayBoxNode::~DelayBoxNode()
  180. {
  181. delete classifier_;
  182. }
  183. int DelayBoxNode::command(int argc, const char*const* argv) {
  184. if (argc == 7) {
  185. /* $db add-rule [$n(0) id] [$n(1) id] $delay $loss_rate $bw */
  186. if (!strcmp (argv[1], "add-rule")) {
  187. classifier_->add_rule(argv[2], argv[3], argv[4], 
  188.      argv[5], argv[6]);
  189. return (TCL_OK);
  190. }
  191. }
  192. if (argc == 6) {
  193. /* $db add-rule [$n(0) id] [$n(1) id] $delay $loss_rate */
  194. if (!strcmp (argv[1], "add-rule")) {
  195. classifier_->add_rule(argv[2], argv[3], argv[4], 
  196.      argv[5]);
  197. return (TCL_OK);
  198. }
  199. }
  200. else if (argc == 5) {
  201. /* $db add-rule [$n(0) id] [$n(1) id] $delay */
  202. if (!strcmp (argv[1], "add-rule")) {
  203. classifier_->add_rule(argv[2], argv[3], argv[4]); 
  204. return (TCL_OK);
  205. }
  206. else if (!strcmp (argv[1], "output-delay")) {
  207. if (!rttfp_)
  208. return (TCL_ERROR);
  209. classifier_->output_delay(atoi(argv[2]), 
  210.   atoi(argv[3]), 
  211.   atoi(argv[4]), rttfp_);
  212. return (TCL_OK);
  213. }
  214. }
  215. else if (argc == 3) {
  216. if (!strcmp (argv[1], "set-debug")) {
  217. classifier_->set_debug(atoi (argv[2]));
  218. return (TCL_OK);
  219. }
  220. else if (strcmp (argv[1], "set-delay-file") == 0) {
  221. rttfp_ = fopen (argv[2], "w");
  222. classifier_->setfp(rttfp_);
  223. if (rttfp_)
  224. return (TCL_OK);
  225. else 
  226. return (TCL_ERROR);
  227. }
  228. }
  229. else if (argc == 2) {
  230. if (!strcmp (argv[1], "list-rules")) {
  231. classifier_->list_rules();
  232. return (TCL_OK);
  233. }
  234. else if (!strcmp (argv[1], "list-flows")) {
  235. classifier_->list_flows();
  236. return (TCL_OK);
  237. }
  238. else if (!strcmp (argv[1], "create-classifier")) {
  239. Tcl& tcl = Tcl::instance();
  240. tcl.evalf ("%s entry", name());
  241. classifier_ = (DelayBoxClassifier*) lookup_obj 
  242. (tcl.result());
  243. return (TCL_OK);
  244. }
  245. else if (!strcmp (argv[1], "close-delay-file")) {
  246. if (rttfp_) 
  247. fclose(rttfp_);
  248. return (TCL_OK);
  249. }
  250. else if (!strcmp (argv[1], "set-asymmetric")) {
  251. classifier_->set_asymmetric();
  252. return TCL_OK;
  253. }
  254. }
  255. return (Node::command(argc, argv));
  256. }
  257. /*::::::::::::::::: DELAYBOX CLASSIFIER ::::::::::::::::::::::::::::::::*/
  258. static class DelayBoxClassifierClass : public TclClass {
  259. public:
  260. DelayBoxClassifierClass() : TclClass("Classifier/DelayBox") {}
  261. TclObject* create (int, const char*const*) {
  262. return (new DelayBoxClassifier);
  263. }
  264. } class_delayboxclassifier;
  265. DelayBoxClassifier::~DelayBoxClassifier()
  266. {
  267. // delete the rule table
  268. map<DelayBoxPair, DelayBoxRule*>::iterator rule;
  269. for (rule = rules_.begin(); rule != rules_.end(); rule++) {
  270. delete rule->second;
  271. rules_.erase(rule);
  272. }
  273. // delete the flow table
  274. map<DelayBoxPair, DelayBoxFlow*>::iterator flow;
  275. for (flow = flows_.begin(); flow != flows_.end(); flow++) {
  276. delete flow->second->queue_;
  277. flow->second->timer_->force_cancel();
  278. delete flow->second->timer_;
  279. delete flow->second;
  280. flows_.erase(flow);
  281. }
  282. }
  283. void DelayBoxClassifier::list_rules()
  284. {
  285. if (rules_.size() == 0) {
  286. fprintf (stderr, "nClass %s> Rules table is emptyn", name());
  287. return;
  288. }
  289. map<DelayBoxPair, DelayBoxRule*>::iterator rule;
  290. char pair_str[50];
  291. int i=1;
  292. fprintf (stderr, "nClass %s> Rules:  (%d elements)n", name(),
  293.  (int) rules_.size());
  294. for (rule = rules_.begin(); rule != rules_.end(); rule++, i++) {
  295. rule->first.format(pair_str);
  296. fprintf (stderr, "%4d) %sn", i, pair_str);
  297. }
  298. fprintf (stderr, "n");
  299. }
  300. void DelayBoxClassifier::list_flows()
  301. {
  302. if (flows_.size() == 0) {
  303. fprintf (stderr, "nClass %s> Flows table is emptyn", name());
  304. return;
  305. }
  306. map<DelayBoxPair, DelayBoxFlow*>::iterator flow;
  307. char pair_str[50];
  308. char flow_str[80];
  309. int i=0;
  310. fprintf (stderr, "nClass %s> Flows:   (%d elements)n", name(),
  311.  (int) flows_.size());
  312. for (flow = flows_.begin(); flow != flows_.end(); flow++, i++) {
  313. flow->first.format(pair_str);
  314. flow->second->format(flow_str);
  315. fprintf (stderr, "%4d) %s %sn", i, pair_str, flow_str);
  316. }
  317. fprintf (stderr, "n");
  318. }
  319. void DelayBoxClassifier::output_delay(int src, int dst, int fid, FILE* fp)
  320. {
  321. double delay;
  322. // find delay information for this flow
  323. DelayBoxPair fwd_pair = DelayBoxPair (src, dst, fid);
  324. DelayBoxPair rev_pair = DelayBoxPair (dst, src, fid);
  325. map<DelayBoxPair, DelayBoxFlow*>::iterator fwd_flow = 
  326. flows_.find(fwd_pair);
  327. if (fwd_flow == flows_.end())
  328. return;    // flow not found
  329. map<DelayBoxPair, DelayBoxFlow*>::iterator rev_flow = 
  330. flows_.find(rev_pair);
  331. if (rev_flow == flows_.end())
  332. return;    // flow not found
  333. // compute delay
  334. delay = fwd_flow->second->delay_ + rev_flow->second->delay_;
  335. // output delay
  336. if (fp) {
  337. fprintf (fp, "%d  %fn", fid, delay);
  338. fflush (fp);
  339. }
  340. }
  341. void DelayBoxClassifier::add_rule(const char* src, const char* dst, 
  342.   const char* dly, const char* loss, 
  343.   const char* linkspd)
  344. /* $db add-rule [$n(0) id] [$n(1) id] $delay $loss_rate $bw */
  345. /*
  346.  * "add-rule" command - create rule struct
  347.  *                    - add rule to rule table
  348.  * 
  349.  * SYN - lookup fid in flow table
  350.  *     - if not there, create element 
  351.  *            - find src/dst in rule table
  352.  *            - sample from RVs
  353.  *            - create queue and timer
  354.  *     - add element to flow table
  355.  *
  356.  * packet - lookup fid in flow table
  357.  *        - if not there, pass to default classifier
  358.  *        - if loss > 0, sample [0:1]
  359.  *        - if not dropped, add to delay Q
  360.  *        - set flow's timer
  361.  *
  362.  * FIN - delay packet
  363.  *     - remove fid from flow table
  364.  *
  365.  * timeout - lookup flow
  366.  *         - remove packet from Q
  367.  *         - pass to default classifier
  368.  */
  369. {
  370. // parse the arguments
  371. int source = atoi (src);
  372. int dest = atoi (dst);
  373. RandomVariable* delay = (RandomVariable*) lookup_obj (dly);
  374. RandomVariable* loss_rate = (RandomVariable*) lookup_obj (loss);
  375. RandomVariable* link_speed = (RandomVariable*) lookup_obj (linkspd);
  376. // create a new pair
  377. DelayBoxPair* pair = new DelayBoxPair (source, dest);
  378. // create a new rule
  379. DelayBoxRule* rule = new DelayBoxRule (delay, loss_rate, 
  380.        link_speed);
  381. // add to the rule table
  382. rules_[*pair] = rule;
  383. }
  384. void DelayBoxClassifier::add_rule(const char* src, const char* dst, 
  385.   const char* dly, const char* loss)
  386. /* $db add-rule [$n(0) id] [$n(1) id] $delay $loss_rate */
  387. /*
  388.  * "add-rule" command - create rule struct
  389.  *                    - add rule to rule table
  390.  */
  391. {
  392. // parse the arguments
  393. int source = atoi (src);
  394. int dest = atoi (dst);
  395. RandomVariable* delay = (RandomVariable*) lookup_obj (dly);
  396. RandomVariable* loss_rate = (RandomVariable*) lookup_obj (loss);
  397. // create a new pair
  398. DelayBoxPair* pair = new DelayBoxPair (source, dest);
  399. // create a new rule
  400. DelayBoxRule* rule = new DelayBoxRule (delay, loss_rate);
  401. // add to the rule table
  402. rules_[*pair] = rule;
  403. }
  404. void DelayBoxClassifier::add_rule(const char* src, const char* dst, 
  405.   const char* dly)
  406. /* $db add-rule [$n(0) id] [$n(1) id] $delay */
  407. /*
  408.  * "add-rule" command - create rule struct
  409.  *                    - add rule to rule table
  410.  */
  411. {
  412. // parse the arguments
  413. int source = atoi (src);
  414. int dest = atoi (dst);
  415. RandomVariable* delay = (RandomVariable*) lookup_obj (dly);
  416. // create a new pair
  417. DelayBoxPair* pair = new DelayBoxPair (source, dest);
  418. // create a new rule
  419. DelayBoxRule* rule = new DelayBoxRule (delay);
  420. // add to the rule table
  421. rules_[*pair] = rule;
  422. }
  423. int DelayBoxClassifier::classify(Packet *p) {
  424. /* 
  425.  * Everything should be classified into slot 0, which points
  426.  * to the default classifier.
  427.  */
  428. return 0;
  429. }
  430. void DelayBoxClassifier::recv (Packet* p, Handler* h)
  431. {
  432. DelayBoxFlow* flow = NULL;
  433. double delay = 0.0, loss = 0, linkspd = 0;
  434. // debugging
  435. hdr_tcp *tcph = hdr_tcp::access(p);
  436. hdr_cmn *ch = hdr_cmn::access(p); 
  437. hdr_ip *iph = hdr_ip::access(p);
  438. int src = iph->src_.addr_;
  439. int dst = iph->dst_.addr_;
  440. int fid = iph->flowid();
  441. int action = -1;   // 0 - nothing, 1 - add, 2 - add rev dir
  442. // lookup flow in flow table
  443. DelayBoxPair pair = DelayBoxPair (src, dst, fid);
  444. map<DelayBoxPair, DelayBoxFlow*>::iterator flow_iter = 
  445. flows_.find(pair);
  446. if (flow_iter == flows_.end()) {
  447. /*
  448.  * flow not found in table
  449.  */
  450. if ((tcph->flags() & 0x0) == 0x0) {
  451. // one-way TCP flow
  452. int size = ch->size();
  453. int seqno = tcph->seqno();
  454. packet_t t = ch->ptype();
  455. const char* name = packet_info.name(t);
  456. if (symmetric_ && size == 40 && seqno == 0 && 
  457.  !strcmp (name, "ack")) { 
  458. // effectively a SYN/ACK
  459. action = 2;
  460. }
  461. else if (size == 40 && seqno == 0 
  462.  && !strcmp(name, "tcp")) { 
  463. // effectively a SYN
  464. action = 1;
  465. else {
  466. action = 0;
  467. }
  468. }
  469. else {
  470. if (symmetric_ && 
  471.     (tcph->flags() & TH_ACK) == TH_ACK &&
  472.     (tcph->flags() & TH_SYN) == TH_SYN) {
  473. /*
  474.  * this is a SYN/ACK, find flow for dst -> src
  475.  */
  476. action = 2;
  477. }
  478. else if ((tcph->flags() & TH_SYN) == TH_SYN) {
  479. /* 
  480.  * new flow that's not in table
  481.  */
  482. action = 1;
  483. }
  484. else {
  485. action = 0;
  486. }
  487. }
  488. if (action == 0) {
  489. /*
  490.  * no rule for this flow
  491.  */
  492. forward_packet(p);
  493. return;
  494. } else if (action == 1) {
  495. /*
  496.  * this is a new flow
  497.  */
  498. DelayBoxPair rule_pair (src, dst);
  499. map<DelayBoxPair, DelayBoxRule*>::iterator rule 
  500. = rules_.find(rule_pair);
  501. if (rule == rules_.end()) {
  502. // no rule for src/dst
  503. DelayBoxPair rev_pair (dst, src);
  504. rule = rules_.find(rev_pair);
  505. if (!symmetric_ || rule == rules_.end()) {
  506. // no rule for dst/src
  507. forward_packet(p);
  508. return;
  509. }
  510. }
  511. // sample rules for flow values
  512. if (rule->second->delay_ != NULL) {
  513. // to s
  514. delay = rule->second->delay_->value() / 1000.0;
  515. }
  516. if (rule->second->loss_ != NULL) {
  517. loss = rule->second->loss_->value();
  518. }
  519. if (rule->second->linkspd_ != NULL) {
  520. linkspd = rule->second->linkspd_->value() *
  521. MbPS2BPS_FACTOR;
  522. }
  523. // create new queue and timer
  524. DelayBoxQueue* q = new DelayBoxQueue();
  525. DelayBoxTimer* timer = new DelayBoxTimer(this, src, 
  526.  dst, fid);
  527. // create new flow table entry
  528. flow = new DelayBoxFlow(delay, loss, linkspd, q, timer);
  529. // create new pair
  530. DelayBoxPair *new_pair = new DelayBoxPair();
  531. *new_pair = pair;
  532. // add to flow table
  533. flows_[*new_pair] = flow;
  534. // output to file, if required
  535. if (rttfp_ != NULL) {
  536. char str[50] = "";
  537. new_pair->format_short(str);
  538. fprintf (rttfp_, "%s", str);
  539. flow->format_delay(str);
  540. fprintf (rttfp_, " %s msn", str);
  541. }
  542. }
  543. else if (action == 2) {
  544. /*
  545.  * find the other end of this flow
  546.  */
  547. DelayBoxPair revpair = DelayBoxPair (dst, src, fid);
  548. map<DelayBoxPair, DelayBoxFlow*>::iterator flow_iter = 
  549. flows_.find(revpair);
  550. if (flow_iter == flows_.end()) {
  551. // no flow has been set up
  552. forward_packet(p);
  553. return;
  554. }
  555. // add this direction to the flow table
  556. // create new queue and timer
  557. DelayBoxQueue* q = new DelayBoxQueue();
  558. DelayBoxTimer* timer = new DelayBoxTimer(this, src, 
  559.  dst, fid);
  560. // create new flow table entry
  561. flow = new DelayBoxFlow(flow_iter->second->delay_, 
  562. flow_iter->second->loss_, 
  563. flow_iter->second->linkspd_, q, 
  564. timer);
  565. // create new pair
  566. DelayBoxPair *new_pair = new DelayBoxPair();
  567. *new_pair = pair;
  568. // add to flow table
  569. flows_[*new_pair] = flow;
  570. // output to file, if required
  571. if (rttfp_ != NULL) {
  572. char str[50] = "";
  573. new_pair->format_short(str);
  574. fprintf (rttfp_, "%s", str);
  575. flow->format_delay(str);
  576. fprintf (rttfp_, " %s msn", str);
  577. }
  578. }
  579. }
  580. else {
  581. /*
  582.  * flow found in the table
  583.  */
  584. flow = flow_iter->second;
  585. }
  586. delay = flow->delay_;
  587. double loss_rate = flow->loss_;
  588. double link_speed = flow->linkspd_;
  589. // should this packet be dropped?
  590. double num = Random::uniform (0.0,1.0);
  591. double time = now();
  592. if (loss_rate > 0 && num <= loss_rate) {
  593. // num is between 0 and loss_rate_, so drop this packet
  594. if (debug_ > 0) {
  595. char str[50] = "";
  596. packet_string (str, tcph, iph, ch->size());
  597. fprintf (stderr, "Class %s>  %s DROPPED at %fn", 
  598.  name(), str, time);
  599. }
  600. Packet::free(p);
  601. return;
  602. }
  603. // enqueue p
  604. double time_to_send = flow->queue_->add(p, time + delay, 
  605.   link_speed);
  606. if (debug_ > 1) {
  607. char str[50] = "";
  608. packet_string (str, tcph, iph, ch->size());
  609. fprintf (stderr, "  Class %s> %s -> Q at %fn", name(), str, 
  610.  time);
  611. flow->queue_->dumplist();
  612. }
  613. // set timer for next time (time_to_recv)
  614. if (flow->queue_->oneitem()) {
  615. time = now();
  616. flow->timer_->sched(time_to_send - time);
  617. if (debug_ > 1) {
  618. fprintf (stderr, "     set sched for %fsn",
  619.  time_to_send - time);
  620. }
  621. }
  622. }
  623. void DelayBoxClassifier::forward_packet (Packet *p)
  624. {
  625. // pass this packet on to the default classifier
  626. NsObject* node = find(p);
  627. if (node == NULL) {
  628. Packet::free(p);
  629. return;
  630. }
  631. node->recv(p);
  632. }
  633. void DelayBoxClassifier::timeout(int src, int dst, int fid)
  634. {
  635. double delta;
  636. char str[50];
  637. DelayBoxPair pair (src, dst, fid);
  638. // look for this flow in the table
  639. map<DelayBoxPair, DelayBoxFlow*>::iterator flow_iter = 
  640. flows_.find(pair);
  641. if (flow_iter == flows_.end()) {
  642. pair.format(str);
  643. fprintf (stderr, "Received timeout for flow %s", str);
  644. fprintf (stderr, " - not in the flow tablen");
  645. return;
  646. }
  647. DelayBoxFlow* flow = flow_iter->second;
  648. Packet *p = flow->queue_->dequeue (&delta);
  649. if (p == NULL) {
  650. fprintf (stderr, "nothing to recv...n");
  651. return;
  652. }
  653. hdr_tcp *tcph = hdr_tcp::access(p);
  654. if (debug_ > 1) {
  655. hdr_ip *iph = hdr_ip::access(p);
  656. hdr_cmn *ch = hdr_cmn::access(p); 
  657. char tmp_str[50] = "";
  658. packet_string (tmp_str, tcph, iph, ch->size());
  659. fprintf (stderr, "  Class %s> %s <- Q at %fn", name(), 
  660.  tmp_str, now());
  661. flow->queue_->dumplist();
  662. }
  663. if ((tcph->flags() & TH_FIN) == TH_FIN) {
  664. if (debug_ > 1) {
  665. char pairstr[50];
  666. pair.format_short(pairstr);
  667. fprintf (stderr, "  Class %s> deleting flow %sn",
  668.  name(), pairstr);
  669. }
  670. // remove this flow from the flow table
  671. delete flow_iter->second->queue_;
  672. flow_iter->second->timer_->force_cancel();
  673. delete flow_iter->second->timer_;
  674. delete flow_iter->second;
  675. flows_.erase (flow_iter);
  676. /* 
  677.  * This is not needed.  The other side will
  678.  * send a FIN and it's entry will then
  679.  * be deleted from the table.
  680.  * Besides, there was an error that the
  681.  * FIN wasn't being forwarded in some cases 
  682.  */
  683. // find the other side of the flow and remove
  684. /*
  685. DelayBoxPair other_side (dst, src, fid);
  686. map<DelayBoxPair, DelayBoxFlow*>::iterator flow_iter_tmp = 
  687. flows_.find(other_side);
  688. if (flow_iter_tmp != flows_.end()) {
  689. delete flow_iter_tmp->second->queue_;
  690. flow_iter_tmp->second->timer_->force_cancel();
  691. delete flow_iter_tmp->second->timer_;
  692. delete flow_iter_tmp->second;
  693. flows_.erase (flow_iter_tmp);
  694. }
  695. */
  696. forward_packet(p);
  697. return;
  698. }
  699. if (!flow->queue_->empty()) {
  700. if (debug_ > 1) {
  701. fprintf (stderr, "    setting sched for %fsn", 
  702.  delta);
  703. }
  704. flow->timer_->resched(delta);
  705. }
  706. forward_packet(p);
  707. }
  708. /*::::::::::::::::: DELAYBOX TIMER :::::::::::::::::::::::::::::::::::::*/
  709. void DelayBoxTimer::expire(Event *) 
  710. {
  711. a_->timeout(src_, dst_, fid_);
  712. }
  713. /*::::::::::::::::: DELAYBOX QUEUE :::::::::::::::::::::::::::::::::::::*/
  714. DelayBoxQueue::~DelayBoxQueue()
  715. {
  716. clear();
  717. }
  718. void DelayBoxQueue::clear()
  719. {
  720. pktinfo* p = head_;
  721. while (head_) {
  722. p = head_;
  723. head_= head_->next_;
  724. if (p->pkt_ != NULL)
  725. Packet::free(p->pkt_);
  726. delete p;
  727. }
  728. deltasum_ = 0;
  729. head_ = tail_ = NULL;
  730. return;
  731. }
  732. double DelayBoxQueue::add(Packet* pkt, double xfer_time, double link_speed)
  733. /*
  734.          * pkt       - packet to be added to tail of queue
  735.          * xfer_time - time to transfer this packet with no queuing
  736.          *
  737.          * p->delta_ - time between sending the previous packet and 
  738.  *             this packet
  739.          *
  740.          * deltasum_ - sum of all of deltas in the queue
  741.          *           - the sending time of the first bit of the 
  742.  *             previous packet
  743.          *
  744.          * All packets in this queue are from the same connection, but
  745.          * due to variable packet sizes, the processing delay won't
  746.          * be the same for all packets.  This means that shorter packets
  747.          * may have to queue behind larger packets before being transferred.
  748.          *
  749.          * We want the transfer time to reflect the time the first bit
  750.          * gets transferred.  So, p->delta_ may include the transfer time
  751.          * of the previous packet.
  752.          *
  753.          * time packet will be xfer'd = deltasum_ + p->delta_
  754.          *
  755.          */
  756. {
  757. double process_delay = 0;
  758. int size = 0;
  759. // create new queue element 
  760. pktinfo* p = new pktinfo;
  761. p->next_ = NULL;
  762. p->pkt_ = pkt;
  763. // find the processing delay of the previous packet (tail of queue)
  764. if (tail_ != NULL) {
  765. hdr_cmn* ch = hdr_cmn::access(tail_->pkt_);
  766. size = ch->size();
  767. if (link_speed > 0)
  768. process_delay = size / link_speed;
  769. }
  770. // calculate when this packet should be transferred
  771. if (xfer_time < (deltasum_ + process_delay)) {
  772. /* 
  773.  * This packet has to queue behind previous packets
  774.  * and will be transferred as soon as last bit of the 
  775.  * previous packet has been transferred.
  776.  */
  777. p->delta_ = process_delay;
  778. }
  779. else { 
  780. /* 
  781.  * This packet won't be ready to be transferred until after
  782.  * the last bit of the previous packet has been transferred.
  783.  * It can be transferred as soon as it's ready.
  784.  */
  785. p->delta_ = xfer_time - deltasum_;
  786. }
  787. /*
  788.  * deltasum_ is now the time that the first bit of this packet
  789.  * will be sent
  790.  */
  791. deltasum_ += p->delta_;
  792. // insert at end of queue
  793. if (head_ == NULL) {
  794. head_ = p;
  795. else {
  796. tail_->next_ = p;
  797. }
  798. tail_ = p;
  799. return (p->delta_);
  800. }
  801. /*
  802.  * dequeue -- remove and return head of the queue
  803.  */
  804. Packet* DelayBoxQueue::dequeue(double* resched_time)
  805. {
  806. double head_delta;
  807. if (head_ == NULL)
  808. return NULL;
  809. pktinfo *ptr = head_;
  810. Packet* p = ptr->pkt_;
  811. // save delta value
  812. head_delta = ptr->delta_;
  813. // advance the head pointer
  814. head_ = ptr->next_;        
  815. ptr->next_ = NULL;
  816. delete ptr;
  817. if (head_ == NULL) {
  818. *resched_time = 0;
  819. deltasum_ = 0;
  820. tail_ = NULL;
  821. }
  822. else {
  823. // new head of the queue's delta should be its time to send
  824. // which is head_->delta + new_head_->delta
  825. *resched_time = head_->delta_;
  826. head_->delta_ += head_delta;   // fix the head's delta
  827. }
  828. return (p);
  829. }
  830. /*
  831.  * dumplist -- print out list (for debugging)
  832.  */
  833. void DelayBoxQueue::dumplist()
  834. {
  835. register pktinfo* p = head_;
  836. Packet *pkt;
  837. hdr_tcp *tcph;
  838. hdr_cmn *ch;
  839. hdr_ip *iph;
  840. char str[50] = "";
  841. if (head_ == NULL) {
  842. fprintf(stderr, "    head_ is NULLn");
  843. return;
  844. }
  845. while (p != NULL) {
  846. pkt = p->pkt_;
  847. tcph = hdr_tcp::access(pkt);
  848. ch = hdr_cmn::access(pkt);
  849. iph = hdr_ip::access(pkt);
  850. packet_string (str, tcph, iph, ch->size());
  851. fprintf (stderr, "t%s at %fn", str, p->delta_);
  852. p = p->next_;
  853. }
  854. }
  855. /*
  856.  * Format packet info for output
  857.  */
  858. void packet_string (char* str, hdr_tcp *tcph, hdr_ip* iph, int size)
  859. {
  860. int datalen = size - tcph->hlen();     // remove header size
  861. sprintf (str, "(%d > %d: %d)", iph->src_.addr_, iph->dst_.addr_, 
  862.  iph->flowid());
  863. /*
  864.  * In FullTcp, everything is an ACK except 1st SYN
  865.  */ 
  866. if ((tcph->flags() & TH_SYN) && (tcph->flags() & TH_ACK)) {
  867. sprintf (str, "%s SYN #%u (%d) ACK #%u", str, tcph->seqno(), 
  868.  datalen, tcph->ackno());
  869. }
  870. else if (tcph->flags() & TH_SYN) {
  871. sprintf (str, "%s SYN #%u (%d)", str, tcph->seqno(), datalen);
  872. }
  873. else if (tcph->flags() & TH_FIN) {
  874. sprintf (str, "%s FIN #%u (%d) ACK #%u", str, tcph->seqno(), 
  875.  datalen, tcph->ackno());
  876. }
  877. else if (datalen == 0) {
  878. // "pure ACK"
  879. sprintf (str, "%s ACK #%u (%d)", str, tcph->ackno(), datalen);
  880. }
  881. else {
  882. sprintf (str, "%s DATA #%u (%d) ACK #%u", str, tcph->seqno(), 
  883.  datalen, tcph->ackno());
  884. }
  885. }