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

通讯编程

开发平台:

Visual C++

  1. #
  2. # Copyright (c) 1996-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/lib/ns-queue.tcl,v 1.28 2005/03/21 18:51:30 haldar Exp $
  32. #
  33. #
  34. # This file contains auxillary support for CBQ and CBQ links, and
  35. # some embryonic stuff for Queue Monitors. -KF
  36. #
  37. # Also contains some support for queue tracing and 
  38. # procs for some queues like FQ and RED/PD
  39. #
  40. #
  41. # CBQ
  42. #
  43. #
  44. # set up the baseline CBQ or CBQ/WRR object
  45. # baseline object contains only an empty classifier
  46. # and the scheduler (CBQ or CBQ/WRR) object itself
  47. #
  48. # After initialized, the structure is as follows:
  49. #
  50. #
  51. # head_-> (classifier)
  52. # queue_-> (cbq) ==> link_
  53. # drophead_ -> (connector) ==> nullAgent
  54. #
  55. # == is data flow
  56. # -- is a pointer reference
  57. #
  58. Class CBQLink -superclass SimpleLink
  59. CBQLink instproc init { src dst bw delay q cl {lltype "DelayLink"} } {
  60.         $self next $src $dst $bw $delay $q $lltype ; # SimpleLink ctor
  61.         $self instvar head_ queue_ link_
  62. $self instvar  classifier_ ; # not found in a SimpleLink
  63. # $self instvar  drophead_ ; # not found in a SimpleLink
  64. $queue_ link $link_ ; # queue_ set by SimpleLink ctor, CBQ needs $link_
  65.         set classifier_ $cl
  66. $head_ target $classifier_
  67. # set drophead_ [new Connector]
  68. # $drophead_ target [[Simulator instance] set nullAgent_]
  69. #
  70. # the following is merely to inject 'algorithm_' in the
  71. # $queue_ class' name space.  It is not used in ns-2, but
  72. # is needed here for the compat code to recognize that
  73. # 'set algorithm_ foo' commands should work
  74. #
  75. set defalg [Queue/CBQ set algorithm_]
  76. $queue_ set algorithm_ $defalg
  77. # this part actually sets the default
  78. $queue_ algorithm $defalg
  79. }
  80. #
  81. # set up a trace.  Calling the SimpleLink version is harmless, but doesn't
  82. # do exactly what we need
  83. #
  84. #CBQLink instproc trace { ns f } {
  85. # $self next $ns $f
  86. # $self instvar drpT_ drophead_
  87. # set nxt [$drophead_ target]
  88. # $drophead_ target $drpT_
  89. # $drpT_ target $nxt
  90. #}
  91. #
  92. # set up monitors.  Once again, the base version is close, but not
  93. # exactly what's needed
  94. #
  95. #CBQLink instproc attach-monitors { isnoop osnoop dsnoop qmon } {
  96. # $self next $isnoop $osnoop $dsnoop $qmon
  97. # $self instvar drophead_
  98. # set nxt [$drophead_ target]
  99. # $drophead_ target $dsnoop
  100. # $dsnoop target $nxt
  101. #}
  102. CBQLink instproc classifier {} {
  103. $self instvar classifier_
  104. return $classifier_
  105. }
  106. #
  107. #
  108. # for flow-id based classification, bind c
  109. # CBQClass to a given flow id # (or range)
  110. #
  111. # OTcl usage:
  112. #  bind $cbqclass id
  113. #     or
  114. #  bind $cbqclass idstart idend
  115. #
  116. # these use flow id's as id's
  117. #
  118. CBQLink instproc bind args {
  119. # this is to perform '$cbqlink bind $cbqclass id'
  120. # and '$cbqlink insert $cbqclass bind $cbqclass idstart idend'
  121. $self instvar classifier_
  122. set nargs [llength $args]
  123. set cbqcl [lindex $args 0]
  124. set a [lindex $args 1]
  125. if { $nargs == 3 } {
  126. set b [lindex $args 2]
  127. } else {
  128. set b $a
  129. }
  130. # bind the class to the flow id's [a..b]
  131. while { $a <= $b } {
  132. # first install the class to get its slot number
  133. # use the flow id as the hash bucket
  134. set slot [$classifier_ installNext $cbqcl]
  135. $classifier_ set-hash auto 0 0 $a $slot
  136. incr a
  137. }
  138. }
  139. #
  140. # insert the class into the link
  141. # each class will have an associated queue
  142. # we must create a set of snoop qs with an associated qmon
  143. # which cbq uses to monitor demand.  The qmon may either be
  144. # given, or defaults to just a QueueMonitor type.
  145. #
  146. # Otcl usage:
  147. # insert $cbqclass
  148. # insert $cbqclass $qmon
  149. #
  150. # the two different usages are used to make backward compat with
  151. # ns-1 easier, since in ns-2, insert was in c++
  152. #
  153. # general idea:
  154. #  pkt--> Classifier --> CBQClass --> snoopin --> qdisc --> snoopout --> CBQ
  155. #
  156. CBQLink instproc insert args {
  157. # queue_ refers to the cbq object
  158. $self instvar queue_ drophead_ link_
  159. set nargs [llength $args]
  160. set cbqcl [lindex $args 0]
  161. set qdisc [$cbqcl qdisc]
  162. if { $nargs == 1 } {
  163. set qmon [new QueueMonitor]
  164. } else {
  165. set qmon [lindex $args 1]
  166. }
  167. # qdisc can be null for internal classes
  168. if { $qmon == "" } {
  169. error "CBQ requires a q-monitor for class $cbqcl"
  170. }
  171. if { $qdisc != "" } {
  172. # create in, out, and drop snoop queues
  173. # and attach them to the same monitor
  174. # this is used by CBQ to assess demand
  175. # (we don't need bytes/pkt integrator or stats here)
  176. set in [new SnoopQueue/In]
  177. set out [new SnoopQueue/Out]
  178. set drop [new SnoopQueue/Drop]
  179. $in set-monitor $qmon
  180. $out set-monitor $qmon
  181. $drop set-monitor $qmon
  182. # output of cbqclass -> snoopy inq
  183. $in target $qdisc
  184. $cbqcl target $in
  185. # drop from qdisc -> snoopy dropq
  186. # snoopy dropq's target is overall cbq drop target
  187. $qdisc drop-target $drop
  188. $drop target $drophead_
  189. # output of queue -> snoopy outq
  190. # output of snoopy outq is cbq
  191. $qdisc target $out
  192. $out target $queue_
  193. # tell this class about its new queue monitor
  194. $cbqcl qmon $qmon
  195. }
  196. $cbqcl instvar maxidle_
  197. if { $maxidle_ == "auto" } {
  198. $cbqcl automaxidle [$link_ set bandwidth_] 
  199. [$queue_ set maxpkt_]
  200. set maxidle_ [$cbqcl set maxidle_]
  201. }
  202. $cbqcl maxidle $maxidle_
  203. # tell cbq about this class
  204. # (this also tells the cbqclass about the cbq)
  205. $queue_ insert-class $cbqcl
  206. }
  207. #
  208. # procedures on a cbq class
  209. #
  210. CBQClass instproc init {} {
  211. $self next
  212. $self instvar automaxidle_gain_
  213. set automaxidle_gain_ [$class set automaxidle_gain_]
  214. }
  215. CBQClass instproc automaxidle { linkbw maxpkt } {
  216. $self instvar automaxidle_gain_ maxidle_
  217. $self instvar priority_
  218. set allot [$self allot]
  219. set g $automaxidle_gain_
  220. set n [expr 8 * $priority_]
  221. if { $g == 0 || $allot == 0 || $linkbw == 0 } {
  222. set maxidle_ 0.0
  223. return
  224. }
  225. set gTOn [expr pow($g, $n)]
  226. set first [expr ((1/$allot) - 1) * (1-$gTOn) / $gTOn ]
  227. set second [expr (1 - $g)]
  228. set t [expr ($maxpkt * 8.0)/$linkbw]
  229. if { $first > $second } {
  230. set maxidle_ [expr $t * $first]
  231. } else {
  232. set maxidle_ [expr $t * $second]
  233. }
  234. return $maxidle_
  235. }
  236. CBQClass instproc setparams { parent okborrow allot maxidle prio level xdelay } {
  237.         $self allot $allot
  238. $self parent $parent
  239. $self set okborrow_ $okborrow
  240.         $self set maxidle_ $maxidle
  241.         $self set priority_ $prio
  242.         $self set level_ $level
  243.         $self set extradelay_ $xdelay
  244.         return $self
  245. }
  246. #
  247. # insert a queue into a CBQ class:
  248. # arrange for the queue to initally be blocked
  249. # and for it to block when resumed
  250. # (provides flow control on the queue)
  251. CBQClass instproc install-queue q {
  252. $q set blocked_ true
  253. $q set unblock_on_resume_ false
  254. $self qdisc $q
  255. }
  256. #
  257. # QueueMonitor
  258. #
  259. QueueMonitor instproc reset {} {
  260. $self instvar size_ pkts_
  261. $self instvar parrivals_ barrivals_
  262. $self instvar pdepartures_ bdepartures_
  263. $self instvar pdrops_ bdrops_
  264. # don't reset size_ and pkts_ here
  265. # because they are not cumulative measurements
  266. # the way the following values are
  267. set parrivals_ 0
  268. set barrivals_ 0
  269. set pdepartures_ 0
  270. set bdepartures_ 0
  271. set pdrops_ 0
  272. set bdrops_ 0
  273. set bint [$self get-bytes-integrator]
  274. if { $bint != "" } {
  275. $bint reset
  276. }
  277. set pint [$self get-pkts-integrator]
  278. if { $pint != "" } {
  279. $pint reset
  280. }
  281. set samp [$self get-delay-samples]
  282. if { $samp != "" } {
  283. $samp reset
  284. }
  285. }
  286. QueueMonitor/ED instproc reset {} {
  287. $self next
  288. $self instvar epdrops_ ebdrops_ mon_epdrops_ mon_ebdrops_
  289. set epdrops_ 0
  290. set ebdrops_ 0
  291. set mon_epdrops_ 0
  292. set mon_ebdrops_ 0
  293. }
  294. Class AckReconsClass -superclass Agent
  295. AckReconsControllerClass instproc demux { src dst } {
  296. $self instvar reconslist_ queue_
  297. set addr $src:$dst
  298. if { ![info exists reconslist_($addr)] } {
  299. set recons [new Agent/AckReconsClass $src $dst]
  300. $recons target $queue_
  301. set reconslist_($addr) $recons
  302. }
  303. # return an ack reconstructor object
  304. return $reconslist_($addr)
  305. }
  306. # Calculate number and spacing of acks to be sent
  307. # deltaAckThresh_ = threshold after which reconstructor kicks in
  308. # ackInterArr_ = estimate of arrival rate of acks ("counting process")
  309. # ackSpacing_ = duration in time between acks sent by reconstructor
  310. # delack_ = generate an ack at least every delack_ acks at reconstructor
  311. Agent/AckReconsClass instproc spacing { ack } {
  312. $self instvar ackInterArr_ ackSpacing_ delack_ 
  313. lastAck_ lastRealAck_ lastRealTime_ adaptive_ size_
  314. global ns
  315. set deltaTime [expr [$ns now] - $lastRealTime_]
  316. set deltaAck [expr $ack - $lastAck_]
  317. if {$adaptive_} {
  318. set bw [expr $deltaAck*$size_/$deltaTime]
  319. set ackSpacing_ $ackInterArr_
  320. if { $deltaAck > 0 } {
  321. # set ackSpacing_ [expr $ackInterArr_*$delack_/$deltaAck]
  322. }
  323. } else {
  324. set deltaT [expr $deltaTime / ($deltaAck/$delack_ +1)]
  325. set ackSpacing_ $deltaT
  326. }
  327. }
  328. # Estimate rate at which acks are arriving
  329. Agent/AckReconsClass instproc ackbw {ack time} {
  330. $self instvar ackInterArr_ lastRealTime_ lastRealAck_ alpha_
  331. set sample [expr $time - $lastRealTime_]
  332. # EWMA
  333. set ackInterArr_ [expr $alpha_*$sample + (1-$alpha_)*$ackInterArr_]
  334. }
  335. Class Classifier/Hash/Fid/FQ -superclass Classifier/Hash/Fid
  336. Classifier/Hash/Fid/FQ instproc unknown-flow { src dst fid } {
  337. $self instvar fq_
  338. $fq_ new-flow $src $dst $fid
  339. }
  340. Class FQLink -superclass SimpleLink
  341. FQLink instproc init { src dst bw delay q } {
  342. $self next $src $dst $bw $delay $q
  343. $self instvar link_ queue_ head_ toNode_ ttl_ classifier_ 
  344. nactive_ 
  345. $self instvar drophead_ ;# idea stolen from CBQ and Kevin
  346. set nactive_ 0
  347. set classifier_ [new Classifier/Hash/Fid/FQ 33]
  348. $classifier_ set fq_ $self
  349. #$self add-to-head $classifier_
  350. $head_ target $classifier_
  351. # XXX
  352. # put the ttl checker after the delay
  353. # so we don't have to worry about accounting
  354. # for ttl-drops within the trace and/or monitor
  355. # fabric
  356. #
  357. $queue_ set secsPerByte_ [expr 8.0 / [$link_ set bandwidth_]]
  358. }
  359. FQLink instproc new-flow { src dst fid } {
  360. $self instvar classifier_ nactive_ queue_ link_ drpT_
  361. incr nactive_
  362. set type [$class set queueManagement_]
  363. set q [new Queue/$type]
  364. #XXX yuck
  365. if { $type == "RED" } {
  366.   set bw [$link_ set bandwidth_]
  367. $q set ptc_ [expr $bw / (8. * [$q set mean_pktsize_])]
  368. }
  369. $q drop-target $drpT_
  370. set slot [$classifier_ installNext $q]
  371. $classifier_ set-hash auto $src $dst $fid $slot
  372. $q target $queue_
  373. $queue_ install $fid $q
  374. }
  375. #XXX ask Kannan why this isn't in otcl base class.
  376. FQLink instproc up? { } {
  377. return up
  378. }
  379. #
  380. #Added by ratul for RedPDQueue
  381. #
  382. Queue/RED/PD instproc makeflowmon { link {cltype "SrcDestFid"} {cslots 29}} {
  383.     set flowmon [new QueueMonitor/ED/Flowmon]
  384.     set cl [new Classifier/Hash/$cltype $cslots]
  385.     
  386.     $cl proc unknown-flow { src dst fid } {
  387. set nflow [new QueueMonitor/ED/Flow/RedPD]
  388. set slot [$self installNext $nflow]
  389. #      puts "New Flow : $nflow at slot $slot"
  390. $self set-hash auto $src $dst $fid $slot
  391. #      puts "Installed Itn";
  392.     }
  393.     
  394.     $cl proc no-slot slotnum {
  395. puts stderr "classifier $self, no-slot for slotnum $slotnum"
  396.     }
  397.     
  398.     $flowmon classifier $cl
  399.     $self attach-flowmon $flowmon
  400.     
  401.     set isnoop [new SnoopQueue/In]
  402.     set osnoop [new SnoopQueue/Out]
  403.     set dsnoop [new SnoopQueue/Drop]
  404.     set edsnoop [new SnoopQueue/EDrop]
  405.     
  406.     $link attach-monitors $isnoop $osnoop $dsnoop $flowmon
  407.     $edsnoop set-monitor $flowmon
  408.     $self early-drop-target $edsnoop 
  409.     set ns [Simulator instance]
  410.     $edsnoop target [$ns set nullAgent_]
  411.     # $edsnoop target [$dsnoop target]
  412.     # $edsnoop drop-target [$dsnoop drop-target]
  413.  
  414.     $self drop-target $dsnoop
  415.     
  416.     return $flowmon
  417. }
  418. #############################################################
  419. # Stuff below has been added to enable queue specific tracing
  420. #
  421. #Blame me if anything is broken below - ratul
  422. ##########################################################
  423. #
  424. # attach-nam-traces: Only conventional trace objects are understood by nam currently. 
  425. # do not attach fancy trace objects here. nam will crash in this case.
  426. #
  427. Queue instproc attach-nam-traces {src dst file} {
  428.     
  429. #valid only if the default trace type in attach-traces is Drop, Enque, Deque.
  430. #see comment above.
  431. #this function should be different for different queue when needed.
  432. $self attach-traces $src $dst $file "nam"
  433. }
  434. #
  435. # Dummy function for all the queues that don't implement attach-traces
  436. #
  437. Queue instproc attach-traces {src dst file {op ""}} {
  438. #Do nothing here
  439. }
  440. #
  441. # Added to be able to trace the edrop events 
  442. #
  443. Queue/RED instproc attach-traces {src dst file {op ""}} {
  444.         set ns [Simulator instance]
  445. set type [$self trace-type]
  446. #nam does not understand anything else yet. 
  447. if {$op == "nam"} {
  448. set type "Drop"
  449. }
  450. #puts "In attach-trace: $type"
  451. set newtrace [$ns create-trace $type $file $src $dst $op]
  452. set oldTrace [$self edrop-trace]
  453. #    puts "oldTrace - $oldTrace"
  454. if {$oldTrace!=0} {
  455. # puts "exists"
  456. $newtrace target $oldTrace
  457. } else {
  458. # puts "Does not exist"
  459. $newtrace target [$ns set nullAgent_]
  460. }
  461. $self edrop-trace $newtrace
  462. }
  463. #
  464. # Added to be able to trace the mon_edrop and edrop events
  465. #
  466. Queue/RED/PD instproc attach-traces {src dst file {op ""}} {
  467. $self next $src $dst $file $op
  468. set ns [Simulator instance]
  469. set type [$self mon-trace-type]
  470. #nam does not understand anything else yet
  471. if {$op == "nam"} {
  472. set type "Drop"
  473. }
  474. set medtrace [$ns create-trace $type $file $src $dst $op]
  475. set oldTrace [$self mon-edrop-trace]
  476. if {$oldTrace!=0} {
  477. puts "exists"
  478. $medtrace target $oldTrace
  479. } else {
  480. # puts "Does not exist"
  481. $medtrace target [$ns set nullAgent_]
  482. }
  483. $self mon-edrop-trace $medtrace
  484. }
  485. Delayer instproc init {} {
  486.     $self next
  487. }
  488. Simulator instproc insert-delayer {src dst delayer} {
  489.     set link [$self link $src $dst]
  490.     $link insert-delayer $delayer
  491. }
  492. SimpleLink instproc insert-delayer args  {
  493.     $self instvar delayer_ queue_
  494.     if {[info exists delayer_]} {
  495.         puts stderr "Delayer already inserted"
  496.     } else {
  497.         set delayer_ [lindex $args 0]
  498. $delayer_ target [$queue_ target]
  499.         $queue_ target $delayer_
  500.     }
  501. }
  502. # XCP queue consists of underlying virtual queues, for xcp, tcp and other flows. 
  503. Queue/XCP instproc init {} {
  504. $self next
  505. $self create-vqueues
  506. }
  507. Queue/XCP instproc create-vqueues {} {
  508. $self instvar vq_ limit_
  509. # create virtual queues for xcp/tcp flows
  510. $self set-xcpQ [set vq_(0) [new Queue/DropTail/XCPQ]]
  511. $self set-tcpQ [set vq_(1) [new Queue/RED]]
  512. $self set-otherQ [set vq_(2) [new Queue/RED]]
  513. }
  514. Queue/XCP instproc link {del} {
  515. $self instvar vq_ 
  516. # XXX yuck
  517. #link info to RED queue
  518. $vq_(1) link $del
  519. $vq_(2) link $del
  520. }
  521. Queue/XCP instproc queue-limit { limit } {
  522. $self instvar vq_
  523. $vq_(0) set limit_ $limit
  524. $vq_(1) set limit_ $limit
  525. $vq_(2) set limit_ $limit
  526. }
  527. Queue/XCP instproc reset {} {
  528. $self instvar vq_
  529. $vq_(0) reset
  530. $vq_(1) reset
  531. $vq_(2) reset
  532. }