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

通讯编程

开发平台:

Visual C++

  1. #
  2. # Copyright (c) 1997 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/rtp/session-scuba.tcl,v 1.4 1997/11/29 05:42:53 elan Exp $
  32. #
  33. Class Session/RTP/Scuba -superclass Session/RTP
  34. Session/RTP/Scuba instproc init {} {
  35. $self next
  36. $self instvar repAgent_ cchan_
  37. set repAgent_ [new Agent/Message/Scuba]
  38.      $repAgent_ set session_ $self
  39. $self set reptimer_ [new Timer/Scuba $self timeout 0]
  40. $self set agetimer_ [new Timer $self age_scores]
  41. $self set localrepid_ 0
  42. $self set prep_ {}
  43. $self set share_ 0.05
  44. $self set scuba_srctab_ {}
  45. $self set tx_ 0
  46. }
  47. Session/RTP/Scuba instproc start { tx rx } {
  48.      $self next
  49. $self instvar reptimer_ agetimer_ tx_ srcid_
  50. if { $rx == 1 } {
  51. $reptimer_ start
  52. }
  53. set tx_ $tx  
  54.    if { $tx_ == 1 } {
  55. $self scuba_register $srcid_ 0
  56. $self set_allocation 
  57. $agetimer_ msched 5000
  58. }
  59. }
  60. Session/RTP/Scuba instproc session_bw { bspec } {
  61. #XXX Should pass on 0.95*session_bw
  62. $self next $bspec
  63. set b [bw_parse $bspec]
  64. $self instvar reptimer_
  65. $reptimer_ set ctrl_bw_ [expr 0.05*$b]
  66. }
  67. Session/RTP/Scuba instproc attach-node { node } {
  68.      $self next $node
  69.     
  70. global ns 
  71.      $self instvar repAgent_
  72. $ns attach-agent $node $repAgent_
  73.      $repAgent_ set node $node
  74. }
  75. Session/RTP/Scuba instproc detach-node { node } {
  76.      $self next $node
  77.     
  78. global ns 
  79.      $self instvar repAgent_
  80. $ns detach-agent $node $repAgent_
  81.      $repAgent_ unset node
  82. }
  83. Session/RTP/Scuba instproc join-group { g } {
  84.      $self next $g
  85.     
  86.      $self instvar repAgent_ node_
  87.      set g [expr $g+2]
  88. $repAgent_ set dst_ $g
  89. $node_ join-group $repAgent_ $g
  90. }
  91.  
  92. Session/RTP/Scuba instproc leave-group { } {
  93.      $self next
  94.      $self instvar_ node_ group_ repAgent_
  95. $node_ leave-group $repAgent_ [expr $group_+2]
  96. }
  97. Session/RTP/Scuba instproc timeout {} {
  98. $self instvar localrepid_ repAgent_ srcid_ rx_
  99. set rep [$self build_report]
  100. $repAgent_ send "$srcid_/$localrepid_/$rep"
  101. incr localrepid_
  102. $self instvar scuba_srctab_ reptimer_
  103. set nsrcs [llength $scuba_srctab_]
  104. set rint [$reptimer_ adapt $nsrcs]
  105. #XXX
  106. if { $rint < 0.5 } {
  107. set rint 0.5
  108. }
  109. $reptimer_ msched $rint
  110. }
  111. Session/RTP/Scuba instproc scuba_register { sender repid } {
  112. # Add new source if we hear a ctrl message from it as well
  113. $self instvar scuba_srctab_ last_repid_ agetab_
  114. if { [lsearch -exact $scuba_srctab_ $sender] < 0 } {
  115. lappend scuba_srctab_ $sender
  116. }
  117. # XXX get rid of repid_...
  118. set last_repid_($sender) $repid
  119. set agetab_($sender) 0
  120. }
  121. Session/RTP/Scuba instproc recv_priority_report { sender repid rep } {
  122. $self scuba_register $sender $repid
  123. #puts "$self: $proc $sender/$repid/$rep"
  124. foreach e $rep {
  125. set srcid [lindex $e 0]
  126. set val [lindex $e 1]
  127. $self recv_scuba_entry $sender $repid $srcid $val
  128. }
  129. $self clean_scoretab $sender $repid
  130. $self instvar tx_
  131. if { $tx_ == 1 } {
  132. $self set_allocation
  133. }
  134. }
  135. Session/RTP/Scuba instproc recv_scuba_entry { sender repid srcid val } {
  136. $self instvar scoretab_ agetab_
  137. #puts "$self: $proc $sender/$repid/$srcid/$val"
  138. set scoretab_($sender:$srcid:$repid) [expr $val/1e6]
  139. set agetab_($sender) 0
  140. }
  141. Session/RTP/Scuba instproc clean_scoretab { sender repid } {
  142. $self instvar scoretab_ agetab_
  143. set idxs [array names scoretab_ $sender:*]
  144. foreach i $idxs {
  145. set r [split $i :]
  146. set r [lindex $r 2]
  147. if { $r < $repid } {
  148. unset scoretab_($i)
  149. }
  150. }
  151. }
  152. Session/RTP/Scuba instproc set_allocation {} {
  153. $self instvar scoretab_ scuba_srctab_ share_ srcid_
  154. set lsrcid $srcid_
  155. #
  156. # Tabulate scores
  157. #
  158. # For now, just find ourselves in the score table and allocate
  159. # our bandwith proportionally.  If our bandwidth is 0, we get a 
  160. # proportional fraction of 5% of the bandwidth which is set aside for
  161. # this purpose.
  162. set total 0
  163. set tot($lsrcid) 0
  164. $self instvar srctab_
  165. foreach src $srctab_ {
  166. set srcid [$src set srcid_]
  167. set voters [array names scoretab_ *:$srcid:*]
  168. set subtotal 0
  169. foreach v $voters {
  170. set subtotal [expr $subtotal+$scoretab_($v)]
  171. }
  172. set tot($srcid) $subtotal
  173. set total [expr $total+$subtotal]
  174. }
  175. #puts "total=$total localtot=$tot($lsrcid)"
  176. if { $total > 0 } {
  177. set avg [expr $tot($lsrcid)/$total]
  178. } else {
  179. set avg 0
  180. }
  181. if { $avg > 0 } {
  182. # 5% for rtcp, 5% scuba
  183. set share_ [expr 0.90*$avg]
  184. } else {
  185. $self instvar srctab_
  186. set nsrcs [llength $srctab_]
  187. if { $nsrcs == 0 } {
  188. set nsrcs 1
  189. }
  190. set share_ [expr 0.05/$nsrcs]
  191. }
  192. $self instvar session_bw_
  193. global ns
  194. #puts "[$ns now] $self: $lsrcid set_bps $share_ of $session_bw_=[expr $share_*$session_bw_]"
  195. $self set_bps [expr $share_*$session_bw_]
  196. }
  197. Session/RTP/Scuba instproc set_bps { bps } {
  198. $self transmit $bps
  199. }
  200. Session/RTP/Scuba instproc build_report {} {
  201. $self instvar focus_set_ localrepid_ srcid_
  202. if ![info exists focus_set_] {
  203. return {}
  204. }
  205. set rep {}
  206. set localsrc $srcid_
  207. # Divvy up score equally among all in focus set
  208. set t 0
  209. set srcs [array names focus_set_]
  210. foreach s $srcs {
  211. # focus_set is 0-1 valued.
  212. # Ignore our own focus
  213. if { [$s set srcid_] != $localsrc } {
  214. set t [expr $t+$focus_set_($s)]
  215. }
  216. }
  217. set lid $localrepid_
  218. # Loopback our report
  219. $self scuba_register $localsrc $lid
  220. if { $t != 0 } {
  221. set score [expr int(1e6/$t)]
  222. foreach s $srcs {
  223. if { $focus_set_($s) != 0 } {
  224. set srcid [$s set srcid_]
  225. lappend rep "$srcid $score"
  226. # Loopback our votes, but ignore our own.
  227. if {[$s set srcid_] != $localsrc} {
  228. $self recv_scuba_entry $localsrc $lid 
  229. $srcid $score
  230. }
  231. }
  232. }
  233. }
  234. # Complete loopback with cleanup and reallocation
  235. $self clean_scoretab $localsrc $lid
  236. $self instvar tx_
  237. if { $tx_ == 1 } {
  238. $self set_allocation
  239. }
  240. return $rep
  241. }
  242. Session/RTP/Scuba instproc scuba_focus { src } {
  243. #puts "focus $src"
  244. $self set focus_set_($src) 1
  245. }
  246. Session/RTP/Scuba instproc scuba_unfocus { src } {
  247. #puts "unfocus $src"
  248. $self set focus_set_($src) 0
  249. }
  250. Session/RTP/Scuba instproc age_scores { } {
  251. $self instvar agetab_ last_repid_ agetimer_
  252. if ![info exists agetab_] {
  253. $agetimer_ msched 5000
  254. return
  255. }
  256. set senders [array names agetab_]
  257. # For now, if we haven't heard from you in 30 seconds - we ignore the
  258. # entries.
  259. # What we want to do is have a sliding window.  Get to that later.
  260. set age_thresh 6
  261. set localsrc [$self set srcid_]
  262. foreach s $senders {
  263. if { $s == $localsrc } {
  264. continue
  265. }
  266. incr agetab_($s)
  267. if { $agetab_($s) > $age_thresh } {
  268. $self delete_sender $s
  269. }
  270. }
  271. $agetimer_ msched 5000
  272. }
  273. Session/RTP/Scuba instproc delete_sender { s } {
  274. $self instvar last_repid_ agetab_ scuba_srctab_
  275. $self clean_scoretab $s [expr $last_repid_($s)+1]
  276. unset agetab_($s)
  277. set i [lsearch -exact $scuba_srctab_ $s]
  278. set scuba_srctab_ [lreplace $scuba_srctab_ $i $i]
  279. $self instvar tx_
  280. if { $tx_ == 1 } {
  281. $self set_allocation
  282. }
  283. }
  284. Class Agent/Message/Scuba -superclass Agent/Message
  285. Agent/Message/Scuba instproc handle { report } {
  286. set R [split $report /]
  287. set sender [lindex $R 0]
  288. set repid [lindex $R 1]
  289. set rep [lindex $R 2]
  290.      $self instvar session_
  291. $session_ recv_priority_report $sender $repid $rep
  292. }
  293. Agent/Message/Scuba set class_ 33
  294. Agent/Message/Scuba set packetSize_ 52
  295. Class Timer
  296. Timer instproc init { manager callback } {
  297. $self next 
  298. $self set callback_ $callback
  299. $self set manager_ $manager
  300. }
  301. Timer instproc msched { t } {
  302. global ns
  303. $self instvar id_ manager_ callback_
  304. if [info exists id_] {
  305. puts stderr "warning: $self ($class): overlapping timers."
  306. }
  307. set id_ [$ns at [expr [$ns now]+$t/1000.] "$self timeout"]
  308. }
  309. Timer instproc timeout {} {
  310. $self instvar id_ manager_ callback_
  311. unset id_
  312. eval $manager_ $callback_
  313. }
  314. Timer instproc cancel {} {
  315. global ns
  316. $self instvar id_
  317. if [info exists id_] {
  318. $ns cancel $id_
  319. unset id_
  320. }
  321. }
  322. Class Timer/Scuba -superclass Timer
  323. Timer/Scuba instproc init { manager callback rand } {
  324. $self next $manager $callback
  325. $self set avgsize_ [Agent/Message/Scuba set packetSize_]
  326. $self set randomize_ $rand
  327. ns-random 0
  328. }
  329. Timer/Scuba instproc adapt { nsrcs } {
  330. $self instvar ctrl_bw_ avgsize_ randomize_
  331. set t [expr 1000*($nsrcs*$avgsize_*8)/$ctrl_bw_]
  332. if { $randomize_ != 0 } {
  333. # Random number in U[-0.5,0.5]
  334. set r [expr [ns-random]/double(0x7fffffff)-0.5]
  335. set t [expr $t+$t*$r]
  336. }
  337. return $t
  338. }
  339. Timer/Scuba instproc start { } {
  340. $self msched [$self adapt 1]
  341. }