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

通讯编程

开发平台:

Visual C++

  1. #
  2. # Copyright (c) 1996 Regents of the University of California.
  3. # All rights reserved.
  4. # Redistribution and use in source and binary forms, with or without
  5. # modification, are permitted provided that the following conditions
  6. # are met:
  7. # 1. Redistributions of source code must retain the above copyright
  8. #    notice, this list of conditions and the following disclaimer.
  9. # 2. Redistributions in binary form must reproduce the above copyright
  10. #    notice, this list of conditions and the following disclaimer in the
  11. #    documentation and/or other materials provided with the distribution.
  12. # 3. All advertising materials mentioning features or use of this software
  13. #    must display the following acknowledgement:
  14. #  This product includes software developed by the MASH Research
  15. #  Group at the University of California Berkeley.
  16. # 4. Neither the name of the University nor of the Research Group may be
  17. #    used to endorse or promote products derived from this software without
  18. #    specific prior written permission.
  19. # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. # SUCH DAMAGE.
  30. #
  31. # @(#) $Header: /cvsroot/nsnam/ns-2/tcl/rlm/rlm.tcl,v 1.1 1998/05/18 22:34:03 aswan Exp $
  32. #
  33. #
  34. # exponential factor for backing off join-timer
  35. #
  36. set rlm_param(alpha) 4
  37. set rlm_param(alpha) 2
  38. set rlm_param(beta) 0.75
  39. set rlm_param(init-tj) 1.5
  40. set rlm_param(init-tj) 10
  41. set rlm_param(init-tj) 5
  42. set rlm_param(init-td) 5
  43. #XXX
  44. #set rlm_param(init-td) 10
  45. set rlm_param(init-td-var) 2
  46. set rlm_param(max) 600
  47. #XXX
  48. set rlm_param(max) 60
  49. set rlm_param(g1) 0.25
  50. set rlm_param(g2) 0.25
  51. #XXX
  52. #set rlm_param(target-exp-time) 5
  53. #puts stderr "rlm: scaling min-rate by M=$M"
  54. #set rlm_param(max) [expr $rlm_param(target-exp-time) * 60 * $M]
  55. #XXX
  56. #puts stderr "rlm: scaling alpha by M=$M"
  57. #set rlm_param(alpha) [expr $rlm_param(alpha) * $M]
  58. #
  59. # The MMG (Multiple Multicast Groups) class implements the RLM
  60. # protocol (Receiver-driven Layered Multicast).  See
  61. # <a href=http://www.cs.berkeley.edu/~mccanne/phd-work/>McCanne's
  62. # thesis</a> for a detailed description of RLM.<p>
  63. #
  64. # This class implements only the basic protocol machinery, it
  65. # does not know anything about either ns or mash.  MMG is an
  66. # abstract class -- you should not instantiate it directly.
  67. # Instead, to use RLM a subclass needs to be created that
  68. # actually joins and leaves groups, makes upcalls on packet
  69. # losses, etc...<p>
  70. #
  71. # Two such subclasses are implemented at the moment, one for
  72. # ns and one for mash.  Note that since all code in the MMG
  73. # base class is shared between ns and mash, you should not
  74. # change anything in this file without being certain that the
  75. # changes will work properly in both ns and mash.<p>
  76. #
  77. # See documentation for the appropriate subclass (i.e., MMG/ns
  78. # or MMG/mash) for details about RLM in different environments.
  79. Class MMG
  80. MMG instproc init { levels } {
  81. $self next
  82. $self instvar debug_ env_ maxlevel_
  83. set debug_ 0
  84. set env_ [lindex [split [$self info class] /] 1]
  85. set maxlevel_ $levels
  86. #XXX
  87. global rlm_debug_flag
  88. if [info exists rlm_debug_flag] {
  89. set debug_ $rlm_debug_flag
  90. }
  91. $self instvar TD TDVAR state_ subscription_
  92. #XXX
  93. global rlm_param
  94. set TD $rlm_param(init-td)
  95. set TDVAR $rlm_param(init-td-var)
  96. set state_ /S
  97. #
  98. # we number the subscription level starting at 1.
  99. # level 0 means no groups are subscribed to.
  100. $self instvar layer_ layers_
  101. set i 1
  102. while { $i <= $maxlevel_ } {
  103. set layer_($i) [$self create-layer [expr $i - 1]]
  104. lappend layers_ $layer_($i)
  105. incr i
  106. }
  107. #
  108. # set the subscription level to 0 and call add_layer
  109. # to start out with at least one group
  110. #
  111. set subscription_ 0
  112. $self add-layer
  113. set state_ /S
  114. #
  115. # Schedule the initial join-timer.
  116. #
  117. $self set_TJ_timer
  118. }
  119. MMG instproc set-state s {
  120. $self instvar state_
  121. set old $state_
  122. set state_ $s
  123. $self debug "FSM: $old -> $s"
  124. }
  125. MMG instproc drop-layer {} {
  126. $self dumpLevel
  127. $self instvar subscription_ layer_
  128. set n $subscription_
  129. #
  130. # if we have an active layer, drop it
  131. #
  132. if { $n > 0 } {
  133. $self debug "DRP-LAYER $n"
  134. $layer_($n) leave-group 
  135. incr n -1
  136. set subscription_ $n
  137. }
  138. $self dumpLevel
  139. }
  140. MMG instproc add-layer {} {
  141. $self dumpLevel
  142. $self instvar maxlevel_ subscription_ layer_
  143. set n $subscription_
  144. if { $n < $maxlevel_ } {
  145. $self debug "ADD-LAYER"
  146. incr n
  147. set subscription_ $n
  148. $layer_($n) join-group
  149. }
  150. $self dumpLevel
  151. }
  152. MMG instproc current_layer_getting_packets {} {
  153. $self instvar subscription_ layer_ TD
  154. set n $subscription_
  155. if { $n == 0 } {
  156. return 0
  157. }
  158. set l $layer_($subscription_)
  159. $self debug "npkts [$l npkts]"
  160. if [$l getting-pkts] {
  161. return 1
  162. }
  163. #XXX hack to adjust TD for large latency case
  164. set delta [expr [$self now] - [$l last-add]]
  165. if { $delta > $TD } {
  166. set TD [expr 1.2 * $delta]
  167. }
  168. return 0
  169. }
  170. #
  171. # return the amount of loss across all the groups of the given mmg
  172. #
  173. MMG instproc mmg_loss {} {
  174. $self instvar layers_
  175. set loss 0
  176. foreach l $layers_ {
  177. incr loss [$l nlost]
  178. }
  179. return $loss
  180. }
  181. #
  182. # return the number of packets received across all the groups of the given mmg
  183. #
  184. MMG instproc mmg_pkts {} {
  185. $self instvar layers_
  186. set npkts 0
  187. foreach l $layers_ {
  188. incr npkts [$l npkts]
  189. }
  190. return $npkts
  191. }
  192. #XXX what is this for?
  193. # deleted some code that didn't seem to be used...
  194. MMG instproc check-equilibrium {} {
  195. global rlm_param
  196. $self instvar subscription_ maxlevel_ layer_
  197. # see if the next higher-level is maxed out
  198. set n [expr $subscription_ + 1]
  199. if { $n >= $maxlevel_ || [$layer_($n) timer] >= $rlm_param(max) } {
  200. set eq 1
  201. } else {
  202. set eq 0
  203. }
  204. $self debug "EQ $eq"
  205. }
  206. MMG instproc backoff-one { n alpha } {
  207. $self debug "BACKOFF $n by $alpha"
  208. $self instvar layer_
  209. $layer_($n) backoff $alpha
  210. }
  211. MMG instproc backoff n {
  212. $self debug "BACKOFF $n"
  213. global rlm_param
  214. $self instvar maxlevel_ layer_
  215. set alpha $rlm_param(alpha)
  216. set L $layer_($n)
  217. $L backoff $alpha
  218. incr n
  219. while { $n <= $maxlevel_ } {
  220. $layer_($n) peg-backoff $L
  221. incr n
  222. }
  223. $self check-equilibrium
  224. }
  225. MMG instproc highest_level_pending {} {
  226. $self instvar maxlevel_
  227. set m ""
  228. set n 0
  229. incr n
  230. while { $n <= $maxlevel_ } {
  231. if [$self level_pending $n] {
  232. set m $n
  233. }
  234. incr n
  235. }
  236. return $m
  237. }
  238. MMG instproc rlm_update_D  D {
  239. #
  240. # update detection time estimate
  241. #
  242. global rlm_param
  243. $self instvar TD TDVAR
  244. set v [expr abs($D - $TD)]
  245. set TD [expr $TD * (1 - $rlm_param(g1)) 
  246. + $rlm_param(g1) * $D]
  247. set TDVAR [expr $TDVAR * (1 - $rlm_param(g2)) 
  248.        + $rlm_param(g2) * $v]
  249. }
  250. MMG instproc exceed_loss_thresh {} {
  251. $self instvar h_npkts h_nlost
  252. set npkts [expr [$self mmg_pkts] - $h_npkts]
  253. if { $npkts >= 10 } {
  254. set nloss [expr [$self mmg_loss] - $h_nlost]
  255. #XXX 0.4
  256. set loss [expr double($nloss) / ($nloss + $npkts)]
  257. $self debug "H-THRESH $nloss $npkts $loss"
  258. if { $loss > 0.25 } {
  259. return 1
  260. }
  261. }
  262. return 0
  263. }
  264. MMG instproc enter_M {} {
  265. $self set-state /M
  266. $self set_TD_timer_wait
  267. $self instvar h_npkts h_nlost
  268. set h_npkts [$self mmg_pkts]
  269. set h_nlost [$self mmg_loss]
  270. }
  271. MMG instproc enter_D {} {
  272. $self set-state /D
  273. $self set_TD_timer_conservative
  274. }
  275. MMG instproc enter_H {} {
  276. $self set_TD_timer_conservative
  277. $self set-state /H
  278. }
  279. MMG instproc log-loss {} {
  280. $self debug "LOSS [$self mmg_loss]"
  281. $self instvar state_ subscription_ pending_ts_
  282. if { $state_ == "/M" } {
  283. if [$self exceed_loss_thresh] {
  284. $self cancel_timer TD
  285. $self drop-layer
  286. $self check-equilibrium
  287. $self enter_D
  288. }
  289. return
  290. }
  291. if { $state_ == "/S" } {
  292. $self cancel_timer TD
  293. set n [$self highest_level_pending]
  294. if { $n != "" } {
  295. #
  296. # there is a join-experiment in progress --
  297. # back off the join-experiment rate for the
  298. # layer that was doing the experiment
  299. # if we're at that layer, drop it, and
  300. # update the detection time estimator.
  301. #
  302. $self backoff $n
  303. if { $n == $subscription_ } {
  304. set ts $pending_ts_($subscription_)
  305. $self rlm_update_D [expr [$self now] - $ts]
  306. $self drop-layer
  307. $self check-equilibrium
  308. $self enter_D
  309. return
  310. }
  311. #
  312. # If we're at the level just below the experimental
  313. # layer that cause a problem, reset our join timer.
  314. # The logic is that we just effectively ran an
  315. # experiment, so we might as well reset our timer.
  316. # This improves the scalability of the algorithm
  317. # by limiting the frequency of experiments.
  318. #
  319. if { $n == [expr $subscription_ + 1] } {
  320. $self cancel_timer TJ
  321. $self set_TJ_timer
  322. }
  323. }
  324. if [$self our_level_recently_added] {
  325. $self enter_M
  326. return
  327. }
  328. $self enter_H
  329. return
  330. }
  331. if { $state_ == "/H" || $state_ == "/D" } {
  332. return
  333. }
  334. puts stderr "rlm state machine botched"
  335. exit -1
  336. }
  337. MMG instproc relax_TJ {} {
  338. $self instvar subscription_ layer_
  339. if { $subscription_ > 0 } {
  340. $layer_($subscription_) relax
  341. $self check-equilibrium
  342. }
  343. }
  344. MMG instproc trigger_TD {} {
  345. $self instvar state_
  346. if { $state_ == "/H" } {
  347. $self enter_M
  348. return
  349. }
  350. if { $state_ == "/D" || $state_ == "/M" } {
  351. $self set-state /S
  352. $self set_TD_timer_conservative
  353. return
  354. }
  355. if { $state_ == "/S" } {
  356. $self relax_TJ
  357. $self set_TD_timer_conservative
  358. return
  359. }
  360. puts stderr "trigger_TD: rlm state machine botched $state)"
  361. exit -1
  362. }
  363. MMG instproc set_TJ_timer {} {
  364. global rlm_param
  365. $self instvar subscription_ layer_
  366. set n [expr $subscription_ + 1]
  367. if ![info exists layer_($n)] {
  368. #
  369. # no timer -- means we're maximally subscribed
  370. #
  371. return
  372. }
  373. set I [$layer_($n) timer]
  374. set d [expr $I / 2.0 + [trunc_exponential $I]]
  375. $self debug "TJ $d"
  376. $self set_timer TJ $d
  377. }
  378. MMG instproc set_TD_timer_conservative {} {
  379. $self instvar TD TDVAR
  380. set delay [expr $TD + 1.5 * $TDVAR]
  381. $self set_timer TD $delay
  382. }
  383. MMG instproc set_TD_timer_wait {} {
  384. $self instvar TD TDVAR
  385. #XXX factor of 2?
  386. $self instvar subscription_
  387. set k [expr $subscription_ / 2. + 1.5]
  388. # set k 2
  389. $self set_timer TD [expr $TD + $k * $TDVAR]
  390. }
  391. #
  392. # Return true iff the time given by $ts is recent enough
  393. # such that any action taken since then is likely to influence the
  394. # present or future
  395. #
  396. MMG instproc is-recent { ts } {
  397. $self instvar TD TDVAR
  398. set ts [expr $ts + ($TD + 2 * $TDVAR)]
  399. if { $ts > [$self now] } {
  400. return 1
  401. }
  402. return 0
  403. }
  404. MMG instproc level_pending n {
  405. $self instvar pending_ts_
  406. if { [info exists pending_ts_($n)] && 
  407.  [$self is-recent $pending_ts_($n)] } {
  408. return 1
  409. }
  410. return 0
  411. }
  412. MMG instproc level_recently_joined n {
  413. $self instvar join_ts_
  414. if { [info exists join_ts_($n)] && 
  415.  [$self is-recent $join_ts_($n)] } {
  416. return 1
  417. }
  418. return 0
  419. }
  420. MMG instproc pending_inferior_jexps {} {
  421. set n 0
  422. $self instvar subscription_
  423. while { $n <= $subscription_ } { 
  424. if [$self level_recently_joined $n] {
  425. return 1
  426. }
  427. incr n
  428. }
  429. $self debug "NO-PEND-INF"
  430. return 0
  431. }
  432. #
  433. # join the next higher layer when in /S
  434. #
  435. MMG instproc trigger_TJ {} {
  436. $self debug "trigger-TJ"
  437. $self instvar state_ ctrl_ subscription_
  438. if { ($state_ == "/S" && ![$self pending_inferior_jexps] && 
  439.   [$self current_layer_getting_packets])  } {
  440. $self add-layer
  441. $self check-equilibrium
  442. set msg "add $subscription_"
  443. $ctrl_ send $msg
  444. #XXX loop back message
  445. $self local-join
  446. }
  447. $self set_TJ_timer
  448. }
  449. MMG instproc our_level_recently_added {} {
  450. $self instvar subscription_ layer_
  451. return [$self is-recent [$layer_($subscription_) last-add]]
  452. }
  453. MMG instproc recv-ctrl msg {
  454. $self instvar join_ts_ pending_ts_ subscription_
  455. $self debug "X-JOIN $msg"
  456. set what [lindex $msg 0]
  457. if { $what != "add" } {
  458. #puts RECV/$msg
  459. return
  460. }
  461. set level [lindex $msg 1]
  462. #
  463. #XXX
  464. # only set the join-ts if the outside J.E. is greater
  465. # than our level.  if not, then we do not want to falsely
  466. # increase the ts of our levels.XXX say this better.
  467. #
  468. set join_ts_($level) [$self now]
  469. if { $level > $subscription_ } {
  470. set pending_ts_($level) [$self now]
  471. }
  472. }
  473. MMG instproc local-join {} {
  474. $self instvar subscription_ pending_ts_ join_ts_
  475. set join_ts_($subscription_) [$self now]
  476. set pending_ts_($subscription_) [$self now]
  477. }
  478. MMG instproc debug { msg } {
  479. $self instvar debug_ subscription_ state_
  480. if {$debug_} {
  481. puts stderr "[gettimeofday] layer $subscription_ $state_ $msg"
  482. }
  483. }
  484. #XXX
  485. MMG instproc dumpLevel {} {
  486. # global rlmTraceFile rates
  487. # if [info exists rlmTraceFile] {
  488. # $self instvar subscription node rateMap
  489. # #XXX
  490. # if ![info exists rateMap] {
  491. # set s 0
  492. # set rateMap "0"
  493. # foreach r $rates {
  494. # set s [expr $s + $r]
  495. # lappend rateMap $s
  496. # }
  497. # }
  498. # set r [lindex $rateMap $subscription]
  499. # puts $rlmTraceFile "[$node id] [ns-now] $r"
  500. # }
  501. }
  502. Class Layer
  503. Layer instproc init { mmg } {
  504. $self next
  505. $self instvar mmg_ TJ npkts_
  506. global rlm_param
  507. set mmg_ $mmg
  508. set TJ $rlm_param(init-tj)
  509. set npkts_ 0
  510. # loss trace created in constructor of derived class
  511. }
  512. #Layer should relax by beta and not alpha
  513. Layer instproc relax {} {
  514. global rlm_param
  515. $self instvar TJ
  516. set TJ [expr $TJ * $rlm_param(beta)]
  517. if { $TJ <= $rlm_param(init-tj) } {
  518. set TJ $rlm_param(init-tj)
  519. }
  520. }
  521. Layer instproc backoff alpha {
  522. global rlm_param
  523. $self instvar TJ
  524. set TJ [expr $TJ * $alpha]
  525. if { $TJ >= $rlm_param(max) } {
  526. set TJ $rlm_param(max)
  527. }
  528. }
  529. Layer instproc peg-backoff L {
  530. $self instvar TJ
  531. set t [$L set TJ]    
  532. if { $t >= $TJ } {
  533. set TJ $t
  534. }
  535. }
  536. Layer instproc timer {} {
  537. $self instvar TJ
  538. return $TJ
  539. }
  540. Layer instproc last-add {} {
  541. $self instvar add_time_
  542. return $add_time_
  543. }
  544. Layer instproc join-group {} {
  545. $self instvar npkts_ add_time_ mmg_
  546. set npkts_ [$self npkts]
  547. set add_time_ [$mmg_ now]
  548. # derived class actually joins group
  549. }
  550. Layer instproc leave-group {} {
  551. # derived class actually leaves group
  552. }
  553. Layer instproc getting-pkts {} {
  554. $self instvar npkts_
  555. return [expr [$self npkts] != $npkts_]
  556. }