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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * lms-receiver.cc
  3.  * Copyright (C) 2001 by the University of Southern California
  4.  * $Id: lms-receiver.cc,v 1.4 2006/02/21 15:20:19 mahrenho Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. /*
  46.  * Light-Weight Multicast Services (LMS), Reliable Multicast
  47.  *
  48.  * lms-receiver.cc
  49.  *
  50.  * This implements the Receiving LMS agent, "Agent/LMS/Receiver".
  51.  *
  52.  * Christos Papadopoulos. 
  53.  * christos@isi.edu
  54.  */
  55. #include <math.h>
  56. #include "agent.h"
  57. #include "tclcl.h"
  58. #include "packet.h"
  59. #include "ip.h"
  60. #include "rtp.h"
  61. #include "lms.h"
  62. #include "rcvbuf.h"
  63. #define LMS_NAK_TIMEOUT 0
  64. #define LMS_RDL_TIMEOUT 1
  65. #define LMS_RFR_TIMEOUT 2
  66. #define LMS_RQL_MAX 10 // requests to remember
  67. #define LMS_RDL_MAX 10 // rdata to remember
  68. #define LMS_LOSS_SMPL_IVL 0 // sample loss every LMS_LOSS_SMPL_IVL packets
  69. // a value of 0 disables adaptive repliers
  70. #define LMS_COST_THR 1 // change in packet loss required to trigger LMS_REFRESH
  71. static int rcv_uid_ = 0;
  72. class LmsReceiver;
  73. class LmsNak;
  74. //
  75. // Lms Nak Timer
  76. // When this timer expires, the Nak is sent again
  77. //
  78. class LmsNakTimer : public TimerHandler {
  79. public:
  80.         LmsNakTimer(LmsNak *a) : TimerHandler() { a_ = a; }
  81.         void expire(Event *e);
  82. protected:
  83.         LmsNak *a_;
  84. };
  85. //
  86. // LMS RECEIVER
  87. //
  88. class LmsReceiver: public Agent {
  89.  public:
  90. LmsReceiver();
  91. LmsReceiver* next_;
  92. int command (int argc, const char*const* argv);
  93. void recv (Packet* pkt, Handler*);
  94. virtual void timeout (int type, int lo, int hi);
  95.  protected:
  96. void handle_lms_pkt (Packet* pkt);
  97. void send_refresh ();
  98. void send_dmcast (hdr_lms* lh, int seqno, int fid);
  99. int  add_req (Packet *rq);
  100. void send_nak (int sqn, int lo, int hi);
  101. void create_nak (int lo, int hi);
  102. void delete_nak (LmsNak *n);
  103. LmsNak* find_nak (int i);
  104. void add_rdl (int rseq, double clock);
  105. int  exists_rdl (int rseq);
  106. void print_stats ();
  107. void print_all_stats (int drops);
  108. char uname_[8]; // unique name in the form r#
  109. RcvBuffer* rcvbuf_; // the receive buffer: see rcvbuf.{h,cc}
  110. int dataSize_; // data packet size
  111. double rtt_; // RTT to source
  112. nsaddr_t lms_src_; // address of sender
  113. nsaddr_t lms_group_; // group address
  114. // LMS related params
  115. nsaddr_t upstream_lms_; // address of upstream LMS element
  116. int lms_cost_; // our current replier cost
  117. Packet* rql_; // request list - used to detect duplicate requests
  118. int rql_sz_; // current request list size
  119. struct lms_rdl* rdl_; // rdata list - used to avoid re-retransmission
  120. int rdl_sz_; // current rdata list size
  121. LmsNak* nak_; // list of currently outstanding naks
  122. // Loss Sampling
  123. int ls_last_rq_; // # of requests at last loss sampling
  124. int ls_last_seq_; // data seq num at last loss sampling
  125. int ls_smpl_ivl_; // loss sampling interval (in packets)
  126. int ls_cntdown_; // how many packets until next loss sample
  127. // Receiver Stats
  128. int req_sent_; // number of unique requests sent
  129. int req_rcvd_; // number of requests received
  130. int dup_reqs_; // number of duplicate requests received
  131.  static int             max_dup_naks_;  // max num of duplicate naks accros RXs
  132.     
  133. // Header offsets
  134. // int off_rtp_;
  135. // int off_lms_;
  136. // int off_ip_;
  137. };
  138. //
  139. // A NAK
  140. //
  141. class LmsNak {
  142.  public:
  143. LmsNak (LmsReceiver *a, int lo, int hi);
  144. LmsNak *next_;
  145. void timeout (int type) {
  146. a_->timeout (type, lo_, hi_); }
  147. LmsNakTimer nak_timer_;
  148. int lo_;
  149. int hi_;
  150. int seqn_;
  151. double nak_timeout_;
  152.  private:
  153. LmsReceiver *a_;
  154. int fid_;
  155. };
  156. LmsNak::LmsNak(LmsReceiver *a, int lo, int hi): nak_timer_(this), lo_(lo), hi_(hi), a_(a)
  157. {
  158. seqn_ = 0;
  159. }
  160. void LmsNakTimer::expire(Event *e) {
  161.         a_->timeout(LMS_NAK_TIMEOUT);
  162. }
  163. LmsReceiver *all_lms_receivers = 0;
  164. static class LmsReceiverClass : public TclClass {
  165. public:
  166. LmsReceiverClass() : TclClass("Agent/LMS/Receiver") {}
  167. TclObject* create(int, const char*const*) {
  168. return (new LmsReceiver());
  169. }
  170. } class_lms_receiver;
  171. // Obligatory definition of the class static
  172. int LmsReceiver::max_dup_naks_ = 0;
  173. LmsReceiver::LmsReceiver(): Agent(PT_LMS)
  174. {
  175. sprintf (uname_, "rcv%d", rcv_uid_++);
  176. lms_cost_ = 0;
  177. lms_src_ = lms_group_ = LMS_NOADDR;
  178. rtt_ = 0.0;
  179. rcvbuf_ = new RcvBuffer;
  180. req_sent_ = req_rcvd_ = dup_reqs_ = max_dup_naks_ = 0;
  181. upstream_lms_ =  LMS_NOADDR;
  182. dataSize_ = 0;
  183. ls_smpl_ivl_ = LMS_LOSS_SMPL_IVL;
  184. ls_cntdown_ = ls_smpl_ivl_;
  185. ls_last_rq_ = ls_last_seq_ = 0;
  186. nak_ = NULL;
  187. rql_ = NULL;
  188. rdl_ = NULL;
  189. rdl_sz_ = 0;
  190. this->next_ = all_lms_receivers;
  191. all_lms_receivers = this;
  192. bind("lmsPacketSize_", &size_);
  193. // bind("off_rtp_", &off_rtp_);
  194. // bind("off_ip_", &off_ip_);
  195. // bind("off_lms_", &off_lms_);
  196. }
  197. //
  198. // Send request upstream
  199. //
  200. void LmsReceiver::send_nak (int sqn, int lo, int hi)
  201. {
  202. Packet* p = allocpkt(sizeof (struct lms_nak));
  203. struct lms_nak *n = (struct lms_nak*)p->accessdata ();
  204. hdr_ip* iph = HDR_IP(p);
  205. hdr_cmn* ch = HDR_CMN(p);  
  206. ch->size_ = sizeof(struct lms_nak) + sizeof(hdr_lms); 
  207. iph->daddr() = upstream_lms_;
  208. iph->flowid() = 8;
  209. #ifdef LMS_DEBUG
  210. printf("at %f %s send nak to upstream lms %d, size is %dnn",
  211.   now,uname_, upstream_lms_, (HDR_CMN(p))->size_);
  212. #endif
  213. hdr_lms* lh = HDR_LMS(p);
  214. lh->type_   = LMS_REQ;
  215. lh->from_   = addr();
  216. lh->src_    = lms_src_;
  217. lh->group_  = lms_group_;
  218. lh->tp_addr_ = LMS_NOADDR;
  219. lh->tp_port_ = -1;
  220. lh->tp_iface_ = LMS_NOIFACE;
  221. lh->lo_ = n->nak_lo_ = lo;
  222. lh->hi_ = n->nak_hi_ = hi;
  223. n->nak_seqn_ = sqn;
  224.         n->dup_cnt_ = 0;
  225.         
  226. target_->recv(p);
  227. }
  228. //
  229. // Send a replier refresh upstream.
  230. //
  231. void LmsReceiver::send_refresh ()
  232. {
  233. Packet* p = allocpkt (sizeof (struct lms_ctl));
  234. struct lms_ctl *ctl = (struct lms_ctl*)p->accessdata ();
  235. hdr_ip* iph = HDR_IP(p);
  236. hdr_cmn *ch = HDR_CMN(p);  
  237. ch->size_ = sizeof(struct lms_ctl) + sizeof(hdr_lms); 
  238. iph->daddr() = upstream_lms_;
  239. iph->flowid() = 7; // mark refresh packets black for nam
  240. #ifdef LMS_DEBUG
  241. printf("%s send refresh packet, size is %dnn",
  242.   uname_, (HDR_CMN(p))->size_);
  243. #endif
  244. hdr_lms* lh = HDR_LMS(p);
  245. lh->type_   = LMS_REFRESH;
  246. lh->from_   = addr();
  247. lh->src_    = lms_src_;
  248. lh->group_  = lms_group_;
  249. ctl->cost_ = lms_cost_;
  250. ctl->hop_cnt_ = 0;
  251.         ctl->downstream_lms_.addr_ = addr();
  252.         ctl->downstream_lms_.port_ = port();
  253.         
  254. target_->recv(p);
  255. }
  256. //
  257. // Receive a packet
  258. //
  259. void LmsReceiver::recv (Packet* pkt, Handler*)
  260. {
  261. hdr_cmn* h = HDR_CMN(pkt);
  262. // handle LMS packet
  263. if (h->ptype_ == PT_LMS)
  264. {
  265. handle_lms_pkt (pkt);
  266. return;
  267. }
  268. // DATA packet
  269. double clock = Scheduler::instance().clock();
  270. hdr_rtp* rh = HDR_RTP(pkt);
  271. int rseq = rh->seqno();
  272. dataSize_ = h->size_;  
  273. #ifdef LMS_DEBUG
  274. printf ("%s got data pkt %dn", uname_, rseq);
  275. #endif
  276. // GAP: send retransmission request
  277. if (rcvbuf_->nextpkt_ <  rseq)
  278. {
  279. int lo = rcvbuf_->nextpkt_;
  280. int hi = rseq - 1;
  281. req_sent_++;
  282. #ifdef LMS_DEBUG
  283. printf ("%s Sending REQ, lo %d, hi %dn", uname_, lo, hi);
  284. #endif
  285. create_nak (lo, hi);
  286. send_nak (0, lo, hi);
  287. }
  288. // RETRANSMISSION
  289. else if (rcvbuf_->nextpkt_ >  rseq &&
  290.  !rcvbuf_->exists_pkt (rseq))
  291. {
  292. add_rdl (rseq, clock); // remember rdata
  293. LmsNak *nak = find_nak (rseq);
  294. if (nak->lo_ !=  nak->hi_)
  295. {
  296. if (rseq == nak->lo_)
  297. create_nak (rseq+1, nak->hi_);
  298. else if (rseq == nak->hi_)
  299. create_nak (nak->lo_, rseq-1);
  300. else {
  301. create_nak (nak->lo_, rseq-1);
  302. create_nak (rseq+1, nak->hi_);
  303. }
  304. }
  305. delete_nak (nak);
  306. }
  307. rcvbuf_->add_pkt (rseq, clock);
  308. // The LMS replier cost is sampled and refreshed every
  309. // LMS_LOSS_SMPL_IVL packets - data or retransmnissions.
  310. // New cost is the number of lost packets during LMS_LOSS_SMPL_IVL.
  311. // We update cost only if loss >= LMS_COST_THR.
  312. // The previous value is forgotten, making cost refresh very responsive.
  313. //
  314. // (XXX: We need a better algorithm here.
  315. if (ls_smpl_ivl_ && --ls_cntdown_ == 0)
  316. {
  317. int newcost = req_sent_ - ls_last_rq_;
  318. assert (newcost >= 0);
  319. if (abs (newcost - lms_cost_) >= LMS_COST_THR)
  320. {
  321. lms_cost_ = newcost;
  322. if (newcost > 0)
  323. ls_last_rq_ = req_sent_;
  324. #ifdef LMS_DEBUG
  325. printf ("%s NEW LMS_COST %dn", uname_, lms_cost_);
  326. #endif
  327. }
  328. send_refresh ();
  329. ls_cntdown_ = ls_smpl_ivl_;
  330. }
  331. Packet::free(pkt);
  332. }
  333. /*
  334.  * Handle LMS packets
  335.  */
  336. void LmsReceiver::handle_lms_pkt (Packet* pkt)
  337. {
  338. hdr_lms* lh = HDR_LMS(pkt);
  339. hdr_ip* iph = HDR_IP(pkt);
  340. int st = 0;
  341. #ifdef LMS_DEBUG
  342. int a1, a2;
  343. #endif
  344. switch (lh->type())
  345. {
  346. case LMS_REQ:
  347. {
  348. struct lms_nak *n = (struct lms_nak *)pkt->accessdata ();
  349. req_rcvd_++;
  350. #ifdef LMS_DEBUG
  351. a1 = lh->from(); a2 = lh->src();
  352. printf ("%s got LMS_REQ from %d:%d src %d:%d group 0x%x ",
  353.   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group());
  354. printf ("TP: (%d:%d, %d)nn", lh->tp_addr_>>8, lh->tp_addr_&0xff, lh->tp_iface_);
  355. #endif
  356. if ((st = add_req (pkt)) != 0)
  357. {
  358. for (int i = lh->lo_; i <= lh->hi_; i++)
  359. if (!(n->nak_seqn_ == 0 && exists_rdl (i)) &&
  360. (rcvbuf_->exists_pkt (i)))
  361. send_dmcast (lh, i, 3);
  362. }
  363. else dup_reqs_++;
  364. break;
  365. }
  366. case LMS_SETUP:
  367.                         {
  368. lms_src_ = iph->saddr();
  369. lms_group_ = iph->daddr();
  370. rtt_ = 2.0*(Scheduler::instance().clock() - lh->ts_);
  371. upstream_lms_ = lh->from_;
  372. dataSize_ = lh->cost_; // XXX
  373. Tcl& tcl = Tcl::instance();
  374. char wrk[64];
  375. sprintf (wrk, "set_max_rtt %f", rtt_);
  376. tcl.eval (wrk); 
  377. #ifdef LMS_DEBUG
  378. a1 = lh->from(); a2 = lh->src();
  379. //printf("%d %d, %ld %ldnn ", a1, a2, iph->saddr(), iph->daddr());
  380. printf("%s the upstream_lms is %dnn", uname_, upstream_lms_);
  381. printf ("%s LMS_SETUP from %d:%d src %d:%d group 0x%x RTT %f dataSize %dnn",
  382.   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group(), rtt_, dataSize_);
  383. #endif
  384.                         send_refresh ();
  385. break;
  386. }
  387. case LMS_SPM:
  388. {
  389. struct lms_spm *spm = (struct lms_spm *)pkt->accessdata ();
  390. #ifdef LMS_DEBUG    
  391. printf ("%s LMS_SPM seqno %d, upstream %d:%dnn",
  392.   uname_, spm->spm_seqno_, adr>>8, adr&0xff);
  393. #endif
  394. if (upstream_lms_ != spm->spm_path_)
  395. upstream_lms_ = spm->spm_path_;
  396. }
  397. break;
  398. case LMS_LINKS:
  399. case LMS_SRC_REFRESH:
  400. break;
  401. default:
  402. printf ("ERROR: %s Unexpected LMS packet type: %dnn", uname_, lh->type());
  403. abort ();
  404.         }
  405. if (!st)
  406. Packet::free(pkt);
  407. }
  408. int LmsReceiver::command(int argc, const char*const* argv)
  409. {
  410. if (argc == 2) {
  411. if (strcmp(argv[1], "clear") == 0) {
  412. return (TCL_OK);
  413. }
  414.                 if (strcmp(argv[1], "print-stats") == 0) {
  415.                         print_stats ();
  416.                         return (TCL_OK);
  417.                 }
  418. }
  419. if (argc == 3)
  420. {
  421.                 if (strcmp(argv[1], "print-all-stats") == 0) {
  422.                         print_all_stats (atoi (argv[2]));
  423.                         return (TCL_OK);
  424.                 }
  425. if (strcmp(argv[1], "set-replier-cost") == 0)
  426. {
  427. lms_cost_  = atoi (argv[2]);
  428.                         send_refresh ();
  429. return (TCL_OK);
  430. }
  431. if (strcmp(argv[1], "loss-smpl-ivl") == 0)
  432. {
  433. ls_cntdown_ = ls_smpl_ivl_ = atoi (argv[2]);
  434. return (TCL_OK);
  435. }
  436. }
  437. return (Agent::command(argc, argv));
  438. }
  439. /*
  440.  * Send a LMS_DMCAST in response to LMS_REQ packet
  441.  */
  442. void LmsReceiver::send_dmcast (hdr_lms* lh, int seqno, int fid)
  443. {
  444. Packet *p = allocpkt();
  445. hdr_cmn *ch = HDR_CMN(p);
  446. hdr_rtp *rh = HDR_RTP(p);
  447. hdr_ip *piph = HDR_IP(p);
  448. #ifdef LMS_DEBUG
  449. printf ("%s Sending DMCAST %d to %d:%d, size is %dn",
  450.   uname_, seqno, lh->tp_addr_>>8, lh->tp_addr_&0xff, ch->size_);
  451. #endif
  452. hdr_lms *plh = HDR_LMS(p);
  453. ch->ptype_ = PT_CBR;
  454. ch->size() = dataSize_; 
  455. rh->seqno() = seqno;
  456. piph->daddr() = lh->tp_addr_;
  457. piph->dport() = lh->tp_port_;
  458. piph->flowid() = fid; // to color packets in NAM
  459. plh->type_ = LMS_DMCAST;
  460. plh->from_ = addr();
  461. plh->src_ = lms_src_;
  462. plh->group_ = lms_group_;
  463. plh->tp_addr_ = lh->tp_addr_;
  464. plh->tp_port_ = lh->tp_port_;
  465. plh->tp_iface_ = lh->tp_iface_;
  466. target_->recv(p);
  467. }
  468. // Add a new request to rql_
  469. // Return 1 if the request was added,
  470. // 0 if this was a duplicate request and was not added.
  471. // Requests are added to the head of the list
  472. // and the list size is limited to LMS_RQL_MAX
  473. // (XXX: should have timer to expire old entries)
  474. //
  475. int LmsReceiver::add_req (Packet *rq)
  476. {
  477. hdr_lms *lh = HDR_LMS(rq);
  478.         Packet  *p = rql_;
  479.         int     i = 0;
  480.         if (!p)
  481.         {
  482.             rql_ = rq;
  483.             rq->next_ = 0;
  484.             rql_sz_ = 1;
  485.             return 1;
  486.         }
  487. #ifdef LMS_DEBUG
  488. printf("%s REQ: tlo=%d thi=%d ttp_addr=%d ttp_if=%dn",
  489.   uname_, lh->lo_, lh->hi_, lh->tp_addr_, lh->tp_iface_);
  490. #endif
  491.       while (p)
  492.         {
  493.             if (++i > LMS_RQL_MAX)
  494.                 break;
  495.             
  496.             hdr_lms *plh = HDR_LMS(p);
  497. #ifdef LMS_DEBUG
  498. printf("%s DB: tlo=%d thi=%d ttp_addr=%d ttp_if=%dn",
  499.   uname_, plh->lo_, plh->hi_, plh->tp_addr_, plh->tp_iface_);
  500. #endif            
  501.             
  502.             if ((plh->lo_ == lh->lo_) &&
  503.                 (plh->hi_ == lh->hi_) &&
  504.                 (plh->tp_addr_ == lh->tp_addr_) &&
  505.                 (plh->tp_iface_ == lh->tp_iface_)) 
  506.             {
  507.                 struct lms_nak *nh = (struct lms_nak *)p->accessdata();
  508.                 // increments the dup_cnt_ for this NAK, and updates
  509.                 // max_dup_naks_ if appropriate
  510.                 ++nh->dup_cnt_;
  511. #ifdef LMS_DEBUG
  512.    printf ("%s got %d dup reqs, max is %dn", uname_, nh->dup_cnt_, max_dup_naks_);
  513. #endif                
  514.                 
  515.                 if( nh->dup_cnt_ > max_dup_naks_)
  516.                     max_dup_naks_ = nh->dup_cnt_;
  517.                                 
  518.                 return 0;
  519.             }
  520.             
  521.             p = p->next_;
  522.         }
  523.         
  524.         if (i > LMS_RQL_MAX && p && p->next_)
  525.         {
  526.             Packet::free (p->next_);
  527.             p->next_ = 0;
  528.             rql_sz_--;
  529.         }
  530.         rq->next_ = rql_;
  531.         rql_ = rq;
  532.         rql_sz_++;
  533.         return 1;
  534. }
  535. void LmsReceiver::print_all_stats (int drops)
  536. {
  537. LmsReceiver *r = all_lms_receivers;
  538. int nrcvs = 0; 
  539. int cnt1 = 0; 
  540. int cnt2 = 0; 
  541. int dup_replies = 0;
  542. double          avg_norm_latency = 0.0;
  543. double min = 1000000.0, max = 0.0;
  544.         float           aveTotalDupReqs = 0.0;
  545.         
  546. while (r)
  547.         {
  548.             ++nrcvs;
  549.             // first, we'll add up all dupReqs, and after the loop we'll
  550.             // div. by nrcvrs
  551.             aveTotalDupReqs += float(r->dup_reqs_);
  552.             if (r->rcvbuf_->duplicates_)
  553.             {
  554.                 cnt1++;
  555.                 dup_replies += r->rcvbuf_->duplicates_;
  556.             }
  557.             if (r->rcvbuf_->pkts_recovered_)
  558.             {
  559.                 cnt2++;
  560.                 double avl = r->rcvbuf_->delay_sum_/(double)r->rcvbuf_->pkts_recovered_;
  561.                 avg_norm_latency += avl / r->rtt_;
  562.                 
  563.                 double m = r->rcvbuf_->min_delay_/r->rtt_;
  564.                 double x = r->rcvbuf_->max_delay_/r->rtt_;
  565.                 if (m < min)
  566.                     min = m;
  567.                 if (x > max)
  568.                     max = x;
  569.             }
  570.             r = r->next_;
  571.         }
  572.         if(drops) 
  573.             aveTotalDupReqs = (float(aveTotalDupReqs) / float(nrcvs)) / float(drops);
  574.         else 
  575.             aveTotalDupReqs = 0.0;
  576.         
  577. //
  578. // Print stats in the form: <avg duplicate replies> <avg recovery latency> <min> <max>
  579. //
  580. if (drops)
  581. {
  582.                     printf ("t%.5ft  %dt%.4f", aveTotalDupReqs, max_dup_naks_,
  583.     ((double)dup_replies/(double)(nrcvs*drops)) );
  584. }
  585. else {
  586. printf ("t0.0t  0t0.0");
  587. }
  588. //printf ("t%d/%d/%.2f", nrcvs, cnt1, (cnt1)?((double)dup_replies/(double)cnt1):0.0);
  589. if (cnt2) 
  590. {
  591. printf ("t%.2ft%.2ft%.2fn", avg_norm_latency/(double)cnt2, min, max);
  592. }
  593. else
  594. {
  595. printf ("t0.0t0.0t0.0n");
  596. }
  597. printf ("n");
  598. //printf ("Avg duplicates: %lfn", (double)dup_replies / (double) cnt1);
  599. //printf ("Avg norm latency: %lfn", avg_norm_latency / (double) cnt2);
  600. }
  601. void LmsReceiver::print_stats ()
  602. {
  603.         printf ("%s:n", uname_);
  604.         printf ("tLast packet:tt%dn", rcvbuf_->nextpkt_-1);
  605.         printf ("tMax packet:tt%dn", rcvbuf_->maxpkt_);
  606.         printf ("tRequests sent:tt%dn", req_sent_);
  607.         printf ("tRequests received:t%dn", req_rcvd_);
  608.         if (rcvbuf_->pkts_recovered_)
  609.                 {
  610.                 printf ("tPackets recovered:t%dn", rcvbuf_->pkts_recovered_);
  611.                 printf ("tNormalized latency (min, max, avg):t%f, %f, %fn",
  612.                         rcvbuf_->min_delay_/rtt_, rcvbuf_->max_delay_/rtt_,
  613.                         (rcvbuf_->delay_sum_/(double)rcvbuf_->pkts_recovered_)/rtt_);
  614.                 }
  615.         printf ("tDuplicate Replies:t%dn", rcvbuf_->duplicates_);
  616.         printf ("tDuplicate Requests:t%dn", dup_reqs_);
  617.         printf ("tRtt:ttt%fn", rtt_);
  618.         printf ("n");
  619. }
  620. void LmsReceiver::timeout (int type, int lo, int hi)
  621. {
  622. if (type == LMS_NAK_TIMEOUT)
  623. {
  624. #ifdef LMS_DEBUG
  625. double now= Scheduler::instance().clock();
  626. printf ("at %f %s LMS_NAK_TIMEOUT for %d, %dn", now, uname_, lo, hi);
  627. #endif
  628. LmsNak *nak = find_nak (lo);
  629. send_nak (++nak->seqn_, lo, hi);
  630. nak->nak_timeout_ *= 2.0; // exponential back-off
  631. nak->nak_timer_.resched (nak->nak_timeout_);
  632. }
  633. }
  634. void LmsReceiver::create_nak (int lo, int hi)
  635. {
  636. #ifdef LMS_DEBUG
  637. printf ("%s Creating NAK %d, %dn", uname_, lo, hi);
  638. #endif
  639. LmsNak *nak = new LmsNak (this, lo, hi);
  640. nak->nak_timeout_ = rtt_ * 2.0; // set initial timeout to twice rtt
  641. nak->nak_timer_.resched (nak->nak_timeout_);
  642. nak->next_ = nak_;
  643. nak_ = nak;
  644. }
  645. LmsNak *LmsReceiver::find_nak (int i)
  646. {
  647. for (LmsNak *n = nak_; n; n = n->next_)
  648. if (n->lo_ <= i && i <= n->hi_)
  649. return n;
  650. // NOT REACHED
  651. printf("ERROR: %s nak %d not foundn", uname_, i);
  652. abort ();
  653. return 0;
  654. }
  655. void LmsReceiver::delete_nak (LmsNak *n)
  656. {
  657. if (n == nak_)
  658. nak_ = nak_->next_;
  659. else {
  660. LmsNak *cur, *prev = nak_;
  661. cur = nak_->next_;
  662. while (cur)
  663. {
  664. if (cur == n)
  665. {
  666. prev->next_ = cur->next_;
  667. break;
  668. }
  669. prev = cur;
  670. cur = cur->next_;
  671. }
  672. }
  673. n->nak_timer_.cancel();
  674. #ifdef LMS_DEBUG
  675. printf ("%s Deleting NAK %d, %dn", uname_, n->lo_, n->hi_);
  676. #endif
  677. delete n;
  678. }
  679. //
  680. // Remember retransmissions. Uses a linked list
  681. // whose size is limited to LMS_RDL_MAX.
  682. // (Perhaps better to use an array and a timer to expire entries)
  683. //
  684. void LmsReceiver::add_rdl (int rseq, double clock)
  685. {
  686. struct lms_rdl *r = new (struct lms_rdl);
  687. r->seqn_ = rseq;
  688. r->ts_ = clock;
  689. r->next_ = rdl_;
  690. rdl_ = r;
  691. if (++rdl_sz_ > LMS_RDL_MAX)
  692. {
  693. struct lms_rdl *r = rdl_;
  694. for (int i = 0; i < LMS_RDL_MAX; i++)
  695. r = r->next_;
  696. delete r->next_;
  697. r->next_ = NULL;
  698. --rdl_sz_;
  699. }
  700. }
  701. int LmsReceiver::exists_rdl (int rseq)
  702. {
  703. struct lms_rdl *r = rdl_;
  704. for (; r; r = r->next_)
  705. if (r->seqn_ == rseq)
  706. return 1;
  707. return 0;
  708. }