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

通讯编程

开发平台:

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-compat.tcl,v 1.47 2004/02/25 22:26:17 yuri Exp $
  32. #
  33. Class OldSim -superclass Simulator
  34. #
  35. # If the "ns" command is called, set up the simulator
  36. # class to assume backward compat.  This creates an instance
  37. # of a backward-compat simulator API with the name "ns"
  38. # (which in turn overrides this proc)
  39. #
  40. proc ns args {
  41. OldSim ns
  42. eval ns $args
  43. }
  44. OldSim instproc default_catch { varName index op } {
  45. if { $index == "" } {
  46. error "ns-1 compat: default change caught, but not a default! (varName: $varName)"
  47. exit 1
  48. }
  49. if { $op == "r" || $op == "u" } {
  50. error "ns-1 compat: default change caught a $op operation"
  51. exit 1
  52. }
  53. set vname ${varName}($index)
  54. upvar $vname var
  55. $self default_assign $varName $index $var
  56. }
  57. OldSim instproc default_assign {aname index newval} {
  58. $self instvar classMap_ queueMap_
  59. if { $index == "" } {
  60. puts "something funny with default traces"
  61. exit 1
  62. }
  63. set obj [string trimleft $aname ns_]
  64. #
  65. # special case the link array
  66. #
  67. if { $obj == "link" } {
  68. if { $index == "queue-limit" } {
  69. Queue set limit_ $newval
  70. return
  71. }
  72. set ivar "$index_"
  73. if { [lsearch [DelayLink info vars] $ivar] >= 0 } {
  74. DelayLink set $ivar $newval
  75. return
  76. }
  77. error "warning: ns-1 compatibility library cannot set link default ${aname}($index)"
  78. return
  79. }
  80. #
  81. # now everyone else
  82. #
  83. if ![info exists classMap_($obj)] {
  84. if ![info exists queueMap_($obj)] {
  85. puts "error: ns-2 compatibility library cannot set ns-v1 default ${aname}($index)"
  86. exit 1
  87. } else {
  88. set ns2obj "Queue/$queueMap_($obj)"
  89. }
  90. } else {
  91. set ns2obj $classMap_($obj)
  92. }
  93. SplitObject instvar varMap_ 
  94. if ![info exists varMap_($index)] {
  95. puts "error: ns-2 compatibility library cannot map instvar $index in class $ns2obj"
  96. exit 1
  97. }
  98. $ns2obj set $varMap_($index) $newval
  99. }
  100. #
  101. # see if this array has any elements already set
  102. # if so, arrange for the value to be set in ns-2
  103. # also, add a trace hook so that future changes get
  104. # reflected into ns-2
  105. #
  106. OldSim instproc map_ns_defaults old_arr {
  107. global $old_arr ; # these were all globals in ns-1
  108. SplitObject instvar varMap_
  109. foreach el [array names $old_arr] {
  110. set val [expr "$${old_arr}($el)"]
  111. $self default_assign $old_arr $el $val
  112. }
  113. # arrange to trace any read/write/unset op
  114. trace variable $old_arr rwu "$self default_catch"
  115. }
  116. OldSim instproc trace_old_defaults {} {
  117. # all ns-v1 defaults as of 1.4
  118. $self map_ns_defaults ns_tcp
  119. $self map_ns_defaults ns_tcpnewreno
  120. $self map_ns_defaults ns_trace
  121. $self map_ns_defaults ns_fulltcp
  122. $self map_ns_defaults ns_red
  123. $self map_ns_defaults ns_cbq
  124. $self map_ns_defaults ns_class
  125. $self map_ns_defaults ns_sink
  126. $self map_ns_defaults ns_delsink
  127. $self map_ns_defaults ns_sacksink
  128. $self map_ns_defaults ns_cbr
  129. $self map_ns_defaults ns_rlm
  130. $self map_ns_defaults ns_ivs
  131. $self map_ns_defaults ns_source
  132. $self map_ns_defaults ns_telnet
  133. $self map_ns_defaults ns_bursty
  134. $self map_ns_defaults ns_message
  135. $self map_ns_defaults ns_facktcp
  136. $self map_ns_defaults ns_link
  137. $self map_ns_defaults ns_lossy_uniform
  138. $self map_ns_defaults ns_lossy_patt
  139. $self map_ns_defaults ns_queue
  140.    $self map_ns_defaults ns_srm
  141. }
  142. OldSim instproc init args {
  143. eval $self next $args
  144. puts stderr "warning: using backward compatibility mode"
  145. $self instvar classMap_
  146.  
  147.         Simulator set nsv1flag 1
  148. #
  149. # Always use the list scheduler.
  150. $self instvar scheduler_
  151. set scheduler_ [new Scheduler/List]
  152. #
  153. # in CBQ, setting the algorithm_ variable becomes invoking
  154. # the algorithm method
  155. #
  156. # also, there really isn't a limit_ for CBQ, as each queue
  157. # has its own.
  158. #
  159. Queue/CBQ instproc set args {
  160. $self instvar compat_qlim_
  161. if { [lindex $args 0] == "queue-limit" || 
  162. [lindex $args 0] == "limit_" } { 
  163. if { [llength $args] == 2 } {
  164. set val [lindex $args 1]
  165. set compat_qlim_ $val
  166. return $val
  167. }
  168. return $compat_qlim_
  169. } elseif { [lindex $args 0] == "algorithm_" } {
  170. $self algorithm [lindex $args 1]
  171. # note: no return here
  172. }
  173. eval $self next $args
  174. }
  175.         #
  176.         # Catch queue-limit variable which is now "$q limit"
  177.         #
  178.         Queue/DropTail instproc set args {
  179.                 if { [llength $args] == 2 &&
  180.                         [lindex $args 0] == "queue-limit" } {
  181.                         # this will recursively call ourself
  182.                         $self set limit_ [lindex $args 1]
  183.                         return
  184.                 }
  185.                 eval $self next $args
  186.         }
  187.         Queue/RED instproc set args {
  188.                 if { [llength $args] == 2 &&
  189.                         [lindex $args 0] == "queue-limit" } {
  190.                         # this will recursively call ourself
  191.                         $self set limit_ [lindex $args 1]
  192.                         return
  193.                 }
  194.                 eval $self next $args
  195.         }
  196. Queue/RED instproc enable-vartrace file {
  197. $self trace ave_
  198. $self trace prob_
  199. $self trace curq_
  200. $self attach $file
  201. }
  202. #
  203. # Catch set maxpkts for FTP sources, (needed because Source objects are
  204. # not derived from TclObject, and hence can't use varMap method below)
  205. #
  206. Source/FTP instproc set args {
  207. if { [llength $args] == 2 &&
  208. [lindex $args 0] == "maxpkts" } {
  209. $self set maxpkts_ [lindex $args 1]
  210. return
  211. }
  212. eval $self next $args
  213. }
  214. Source/Telnet instproc set args {
  215. if { [llength $args] == 2 &&
  216. [lindex $args 0] == "interval" } {
  217. $self set interval_ [lindex $args 1]
  218. return
  219. }
  220. eval $self next $args
  221. }
  222. #
  223. # Support for things like "set ftp [$tcp source ftp]"
  224. #
  225. Agent/TCP instproc source type {
  226. if { $type == "ftp" } {
  227. set type FTP
  228. }
  229. if { $type == "telnet" } {
  230. set type Telnet
  231. }
  232. set src [new Source/$type]
  233. $src attach $self
  234. return $src
  235. }
  236. Agent/TCP set restart_bugfix_ false
  237. #
  238. # support for new variable names
  239. # it'd be nice to set up mappings on a per-class
  240. # basis, but this is too painful.  Just do the
  241. # mapping across all objects and hope this
  242. # doesn't cause any collisions...
  243. #
  244. SplitObject instproc set args {
  245. SplitObject instvar varMap_
  246. set var [lindex $args 0] 
  247. if [info exists varMap_($var)] {
  248. set var $varMap_($var)
  249. set args "$var [lrange $args 1 end]"
  250. }
  251. # xxx: re-implement the code from tcl-object.tcl
  252. $self instvar -parse-part1 $var
  253. if {[llength $args] == 1} {
  254. return [subst $[subst $var]]
  255. } else {
  256. return [set $var [lrange $args 1 end]]
  257. }
  258. }
  259. SplitObject instproc get {var} {
  260. SplitObject instvar varMap_
  261. if [info exists varMap_($var)] {
  262. # puts stderr "TclObject::get $var -> $varMap_($var)."
  263. return [$self set $varMap_($var)]
  264. } else {
  265. return [$self next $var]
  266. }
  267. }
  268. # Agent
  269. TclObject set varMap_(addr) addr_
  270. TclObject set varMap_(dst) dst_
  271. ## now gone
  272. ###TclObject set varMap_(seqno) seqno_
  273. ###TclObject set varMap_(cls) class_
  274. ## class -> flow id
  275. TclObject set varMap_(cls) fid_
  276. # Trace
  277. TclObject set varMap_(src) src_
  278. TclObject set varMap_(show_tcphdr) show_tcphdr_
  279. # TCP
  280. TclObject set varMap_(window) window_
  281. TclObject set varMap_(window-init) windowInit_
  282. TclObject set varMap_(window-option) windowOption_
  283. TclObject set varMap_(window-constant) windowConstant_
  284. TclObject set varMap_(window-thresh) windowThresh_
  285. TclObject set varMap_(overhead) overhead_
  286. TclObject set varMap_(tcp-tick) tcpTick_
  287. TclObject set varMap_(ecn) ecn_
  288. TclObject set varMap_(bug-fix) bugFix_
  289. TclObject set varMap_(maxburst) maxburst_
  290. TclObject set varMap_(maxcwnd) maxcwnd_
  291. TclObject set varMap_(dupacks) dupacks_
  292. TclObject set varMap_(seqno) seqno_
  293. TclObject set varMap_(ack) ack_
  294. TclObject set varMap_(cwnd) cwnd_
  295. TclObject set varMap_(awnd) awnd_
  296. TclObject set varMap_(ssthresh) ssthresh_
  297. TclObject set varMap_(rtt) rtt_
  298. TclObject set varMap_(srtt) srtt_
  299. TclObject set varMap_(rttvar) rttvar_
  300. TclObject set varMap_(backoff) backoff_
  301. TclObject set varMap_(v-alpha) v_alpha_
  302. TclObject set varMap_(v-beta) v_beta_
  303. TclObject set varMap_(v-gamma) v_gamma_
  304. # Agent/TCP/NewReno
  305. TclObject set varMap_(changes) newreno_changes_
  306. # Agent/TCP/Fack
  307. TclObject set varMap_(rampdown) rampdown_ 
  308. TclObject set varMap_(ss-div4) ss-div4_
  309. # Queue
  310. TclObject set varMap_(limit) limit_
  311. # Queue/SFQ
  312. TclObject set varMap_(limit) maxqueue_
  313. TclObject set varMap_(buckets) buckets_
  314. # Queue/RED
  315. TclObject set varMap_(bytes) bytes_
  316. TclObject set varMap_(thresh) thresh_
  317. TclObject set varMap_(maxthresh) maxthresh_
  318. TclObject set varMap_(mean_pktsize) meanPacketSize_
  319. TclObject set varMap_(q_weight) queueWeight_
  320. TclObject set varMap_(wait) wait_
  321. TclObject set varMap_(linterm) linterm_
  322. TclObject set varMap_(setbit) setbit_
  323. TclObject set varMap_(drop-tail) dropTail_
  324. TclObject set varMap_(doubleq) doubleq_
  325. TclObject set varMap_(dqthresh) dqthresh_
  326. TclObject set varMap_(subclasses) subclasses_
  327. # CBQClass
  328. TclObject set varMap_(algorithm) algorithm_
  329. TclObject set varMap_(max-pktsize) maxpkt_
  330. TclObject set varMap_(priority) priority_
  331. TclObject set varMap_(maxidle) maxidle_
  332. TclObject set varMap_(extradelay) extradelay_
  333. # Agent/TCPSinnk, Agent/CBR
  334. TclObject set varMap_(packet-size) packetSize_
  335. TclObject set varMap_(interval) interval_
  336. # Agent/CBR
  337. TclObject set varMap_(random) random_
  338. # IVS
  339. TclObject set varMap_(S) S_
  340. TclObject set varMap_(R) R_
  341. TclObject set varMap_(state) state_
  342. TclObject set varMap_(rttShift) rttShift_
  343. TclObject set varMap_(keyShift) keyShift_
  344. TclObject set varMap_(key) key_
  345. TclObject set varMap_(maxrtt) maxrtt_
  346. Class traceHelper
  347. traceHelper instproc attach f {
  348. $self instvar file_
  349. set file_ $f
  350. }
  351. #
  352. # linkHelper
  353. # backward compat for "[ns link $n1 $n2] set linkVar $value"
  354. #
  355. # unfortunately, 'linkVar' in ns-1 can be associated
  356. # with a link (delay, bandwidth, generic queue requests) or
  357. # can be specific to a particular queue (e.g. RED) which
  358. # has a bunch of variables (see above).
  359. #
  360. Class linkHelper
  361. linkHelper instproc init args {
  362. $self instvar node1_ node2_ linkref_ queue_
  363. set node1_ [lindex $args 0]
  364. set node2_ [lindex $args 1]
  365. set lid [$node1_ id]:[$node2_ id]     
  366. set linkref_ [ns set link_($lid)]
  367. set queue_ [$linkref_ queue]
  368. # these will be used in support of link stats
  369. set sqi [new SnoopQueue/In]
  370. set sqo [new SnoopQueue/Out]
  371. set sqd [new SnoopQueue/Drop]
  372. set dsamples [new Samples]
  373. set qmon [new QueueMonitor/Compat]
  374. $qmon set-delay-samples $dsamples
  375. $linkref_ attach-monitors $sqi $sqo $sqd $qmon
  376. $linkref_ set bytesInt_ [new Integrator]
  377. $linkref_ set pktsInt_ [new Integrator]
  378. $qmon set-bytes-integrator [$linkref_ set bytesInt_]
  379. $qmon set-pkts-integrator [$linkref_ set pktsInt_]
  380. }
  381. linkHelper instproc trace traceObj {
  382. $self instvar node1_ node2_
  383. $self instvar queue_
  384. set tfile [$traceObj set file_]
  385. ns trace-queue $node1_ $node2_ $tfile
  386. # XXX: special-case RED queue for var tracing
  387. if { [string first Queue/RED [$queue_ info class]] == 0 } {
  388. $queue_ enable-vartrace $tfile
  389. }
  390. }
  391.   linkHelper instproc callback {fn} {
  392. # Reach deep into the guts of the link and twist...
  393. # (This code makes assumptions about how
  394. # SimpleLink instproc trace works.)
  395. # NEEDSWORK: should this be done with attach-monitors?
  396.   $self instvar linkref_
  397. foreach part {enqT_ deqT_ drpT_} {
  398. set to [$linkref_ set $part]
  399. $to set callback_ 1
  400. $to proc handle {args} "$fn $args"
  401. }
  402.   }
  403. linkHelper instproc set { var val } {
  404. $self instvar linkref_ queue_
  405. set qvars [$queue_ info vars]
  406. set linkvars [$linkref_ info vars]
  407. set linkdelayvars [[$linkref_ link] info vars]
  408. #
  409. # adjust the string to have a trailing '_'
  410. # because all instvars are constructed that way
  411. #
  412. if { [string last _ $var] != ( [string length $var] - 1) } {
  413. set var ${var}_
  414. }
  415. if { $var == "queue-limit_" } {
  416. set var "limit_"
  417. }
  418. if { [lsearch $qvars $var] >= 0 } {
  419. # set a queue var
  420. $queue_ set $var $val
  421. } elseif { [lsearch $linkvars $var] >= 0 } {
  422. # set a link OTcl var
  423. $linkref_ set $var $val
  424. } elseif { [lsearch $linkdelayvars $var] >= 0 } {
  425. # set a linkdelay object var
  426. [$linkref_ link] set $var $val
  427. } else {
  428. puts stderr "linkHelper warning: couldn't set unknown variable $var"
  429. }
  430. }
  431. linkHelper instproc get var {
  432. $self instvar linkref_ queue_
  433. set qvars [$queue_ info vars]
  434. set linkvars [$linkref_ info vars]
  435. set linkdelayvars [[$linkref_ link] info vars]
  436. #
  437. # adjust the string to have a trailing '_'
  438. # because all instvars are constructed that way
  439. #
  440. if { [string last _ $var] != ( [string length $var] - 1) } {
  441. set var ${var}_
  442. }
  443. if { $var == "queue-limit_" } {
  444. set var "limit_"
  445. }
  446. if { [lsearch $qvars $var] >= 0 } {
  447. # set a queue var
  448. return [$queue_ set $var]
  449. } elseif { [lsearch $linkvars $var] >= 0 } {
  450. # set a link OTcl var
  451. return [$linkref_ set $var]
  452. } elseif { [lsearch $linkdelayvars $var] >= 0 } {
  453. # set a linkdelay object var
  454. return [[$linkref_ link] set $var]
  455. } else {
  456. puts stderr "linkHelper warning: couldn't set unknown variable $var"
  457. return ""
  458. }
  459. return ""
  460. }
  461. #
  462. # gross, but works:
  463. #
  464. # In ns-1 queues were a sublass of link, and this compat
  465. # code carries around a 'linkHelper' as the returned object
  466. # when you do a [ns link $r1 $r2] or a [ns link $r1 $r2 $qtype]
  467. # command.  So, operations on this object could have been
  468. # either link ops or queue ops in ns-1.  It is possible to see
  469. # whether an Otcl class or object supports certain commands
  470. # but it isn't possible to look inside a C++ implemented object
  471. # (i.e. into it's cmd function) to see what it supports.  Instead,
  472. # arrange to catch the exception generated while trying into a
  473. # not-implemented method in a C++ object.
  474. #
  475. linkHelper instproc try { obj operation argv } {
  476. set op [eval list $obj $operation $argv]
  477. set ocl [$obj info class]
  478. set iprocs [$ocl info instcommands]
  479. set oprocs [$obj info commands]
  480. # if it's a OTcl-implemented method we see it in info
  481. # and thus don't need to catch it
  482. if { $operation != "cmd" } {
  483. if { [lsearch $iprocs $operation] >= 0 } {
  484. return [eval $op]
  485. }
  486. if { [lsearch $oprocs $operation] >= 0 } {
  487. return [eval $op]
  488. }
  489. }
  490. #catch the c++-implemented method in case it's not there
  491. #ret will contain error string or return string
  492. # value of catch operation will be 1 on error
  493. if [catch $op ret] {
  494. return -1
  495. }
  496. return $ret
  497. }
  498. # so, try to invoke the op on a queue and if that causes
  499. # an exception (a missing function hopefully) try it on
  500. # the link instead
  501. #
  502. # we need to override 'TclObject instproc unknown args'
  503. # (well, at least we did), because it was coded such that
  504. # if a command() function didn't exist, an exit 1 happened
  505. #
  506. linkHelper instproc unknown { m args } {
  507. # method could be in: queue, link, linkdelay
  508. # or any of its command procedures
  509. # note that if any of those have errors in them
  510. # we can get a general error by ending up at the end here
  511. $self instvar linkref_ queue_
  512. set oldbody [TclObject info instbody unknown]
  513. TclObject instproc unknown args {
  514. if { [lindex $args 0] == "cmd" } {
  515. puts stderr "Can't dispatch $args"
  516. exit 1
  517. }
  518. eval $self cmd $args
  519. }
  520. # try an OTcl queue then the underlying queue object
  521. set rval [$self try $queue_ $m $args]
  522. if { $rval != -1 } {
  523. TclObject instproc unknown args $oldbody
  524. return $rval
  525. }
  526. set rval [$self try $queue_ cmd [list $m $args]]
  527. if { $rval != -1 } {
  528. TclObject instproc unknown args $oldbody
  529. return $rval
  530. }
  531. set rval [$self try $linkref_ $m $args]
  532. if { $rval != -1 } {
  533. TclObject instproc unknown args $oldbody
  534. return $rval
  535. }
  536. set rval [$self try $linkref_ cmd [list $m $args]]
  537. if { $rval != -1 } {
  538. TclObject instproc unknown args $oldbody
  539. return $rval
  540. }
  541. set dlink [$linkref_ link]
  542. set rval [$self try $dlink $m $args]
  543. if { $rval != -1 } {
  544. TclObject instproc unknown args $oldbody
  545. return $rval
  546. }
  547. set rval [$self try $dlink cmd [list $m $args]]
  548. if { $rval != -1 } {
  549. TclObject instproc unknown args $oldbody
  550. return $rval
  551. }
  552. TclObject instproc unknown args $oldbody
  553. puts stderr "Unknown operation $m or subbordinate operation failed"
  554. exit 1
  555. }
  556. linkHelper instproc stat { classid item } {
  557. $self instvar linkref_
  558. set qmon [$linkref_ set qMonitor_]
  559. # note: in ns-1 the packets/bytes stats are counts
  560. # of the number of *departures* at a link/queue
  561. #
  562. if { $item == "packets" } {
  563. return [$qmon pkts $classid]
  564. } elseif { $item == "bytes" } {
  565. return [$qmon bytes $classid]
  566. } elseif { $item == "drops"} {
  567. return [$qmon drops $classid]
  568. } elseif { $item == "mean-qdelay" } {
  569. set dsamp [$qmon get-class-delay-samples $classid]
  570. if { [$dsamp cnt] > 0 } {
  571. return [$dsamp mean]
  572. } else {
  573. return NaN
  574. }
  575. } else {
  576. puts stderr "linkHelper: unknown stat op $item"
  577. exit 1
  578. }
  579. }
  580. linkHelper instproc integral { itype } {
  581. $self instvar linkref_
  582. if { $itype == "qsize" } {
  583. set integ [$linkref_ set bytesInt_]
  584. } elseif { $itype == "qlen" } {
  585. set integ [$linkref_ set pktsInt_]
  586. }
  587. return [$integ set sum_]
  588. }
  589. #
  590. # end linkHelper
  591. #
  592. set classMap_(tcp) Agent/TCP
  593. set classMap_(tcp-reno) Agent/TCP/Reno
  594. set classMap_(tcp-vegas) Agent/TCP/Vegas
  595. set classMap_(tcp-full) Agent/TCP/FullTcp
  596. set classMap_(fulltcp) Agent/TCP/FullTcp
  597. set classMap_(tcp-fack) Agent/TCP/Fack
  598. set classMap_(facktcp) Agent/TCP/Fack
  599. set classMap_(tcp-newreno) Agent/TCP/Newreno
  600. set classMap_(tcpnewreno) Agent/TCP/Newreno
  601. set classMap_(cbr) Agent/CBR
  602. set classMap_(tcp-sink) Agent/TCPSink
  603. set classMap_(tcp-sack1) Agent/TCP/Sack1
  604. set classMap_(sack1-tcp-sink) Agent/TCPSink/Sack1
  605. set classMap_(tcp-sink-da) Agent/TCPSink/DelAck
  606. set classMap_(sack1-tcp-sink-da) Agent/TCPSink/Sack1/DelAck
  607. set classMap_(sink) Agent/TCPSink
  608. set classMap_(delsink) Agent/TCPSink/DelAck
  609. set classMap_(sacksink) Agent/TCPSink ; # sacksink becomes TCPSink here
  610. set classMap_(loss-monitor) Agent/LossMonitor
  611. set classMap_(class) CBQClass
  612. set classMap_(ivs) Agent/IVS/Source
  613. set classMap_(trace) Trace
  614.    set classMap_(srm) Agent/SRM
  615. $self instvar queueMap_
  616. set queueMap_(drop-tail) DropTail
  617. set queueMap_(sfq) SFQ
  618. set queueMap_(red) RED
  619. set queueMap_(cbq) CBQ
  620. set queueMap_(wrr-cbq) CBQ/WRR
  621. $self trace_old_defaults
  622. #
  623. # this is a hack to deal with the unfortunate name
  624. # of a CBQ class chosen in ns-1 (i.e. "class").
  625. #
  626. # the "new" procedure in Tcl/tcl-object.tcl will end
  627. # up calling:
  628. # eval class create id ""
  629. # so, catch this here... yuck
  630.         global tcl_version
  631.         if {$tcl_version < 8} {
  632.                 set class_name "class"
  633.         } else {
  634.                 set class_name "::class"
  635.         }
  636. proc $class_name args {
  637. set arglen [llength $args]
  638. if { $arglen < 2 } {
  639. return
  640. }
  641. set op [lindex $args 0]
  642. set id [lindex $args 1]
  643. if { $op != "create" } {
  644. error "ns-v1 compat: malformed class operation: op $op"
  645. return
  646. }
  647.                 #
  648.                 # we need to prevent a "phantom" argument from
  649.                 # showing up in the argument list to [CBQClass create],
  650.                 # so, don't pass an empty string if we weren't
  651.                 # called with one!
  652.                 #
  653.                 # by calling through [eval], we suppress any {} that
  654.                 # might result from the [lrange ...] below
  655.                 #
  656.                 eval CBQClass create $id [lrange $args 2 [expr $arglen - 1]]
  657. }
  658. }
  659. #
  660. # links in ns-1 had support for statistics collection...
  661. # $link stat packets/bytes/drops
  662. #
  663. OldSim instproc simplex-link-compat { n1 n2 bw delay qtype } {
  664. $self simplex-link $n1 $n2 $bw $delay $qtype
  665. # need to call 'simplex-link', not '-Nargs' cludges, because
  666. # the queue wants to know the delay and bandwidth when it
  667. # attaches
  668.         $self link-twoargs $n1 $n2 ;#maybe this is not needed, whatever...
  669. }
  670. OldSim instproc duplex-link-compat { n1 n2 bw delay type } {
  671. ns simplex-link-compat $n1 $n2 $bw $delay $type
  672. ns simplex-link-compat $n2 $n1 $bw $delay $type
  673. }
  674. OldSim instproc get-queues { n1 n2 } {
  675. $self instvar link_
  676. set n1 [$n1 id]
  677. set n2 [$n2 id]
  678. return "[$link_($n1:$n2) queue] [$link_($n2:$n1) queue]"
  679. }
  680. OldSim instproc create-agent { node type pktClass } {
  681. $self instvar classMap_
  682. if ![info exists classMap_($type)] {
  683. puts stderr 
  684.   "backward compat bug: need to update classMap for $type"
  685. exit 1
  686. }
  687. set agent [new $classMap_($type)]
  688. # new mapping old class -> flowid
  689. $agent set fid_ $pktClass
  690. $self attach-agent $node $agent
  691. # This has been replaced by TclObject instproc get.  -johnh, 10-Sep-97
  692. #
  693. # $agent proc get var {
  694. # return [$self set $var]
  695. # }
  696. return $agent
  697. }
  698. OldSim instproc agent { type node } {
  699. return [$self create-agent $node $type 0]
  700. }
  701. OldSim instproc create-connection 
  702. { srcType srcNode sinkType sinkNode pktClass } {
  703. set src [$self create-agent $srcNode $srcType $pktClass]
  704. set sink [$self create-agent $sinkNode $sinkType $pktClass]
  705. $self connect $src $sink
  706. return $src
  707. }
  708. proc ns_connect { src sink } {
  709. return [ns connect $src $sink]
  710. }
  711. #
  712. # return helper object for backward compat of "ns link" command
  713. #
  714. OldSim instproc link args {
  715. set nargs [llength $args]
  716. set arg0 [lindex $args 0]
  717. set arg1 [lindex $args 1]
  718. if { $nargs == 2 } {
  719. return [$self link-twoargs $arg0 $arg1]
  720. } elseif { $nargs == 3 } {
  721. return [$self link-threeargs $arg0 $arg1 [lindex $args 2]]
  722. }
  723. }
  724. OldSim instproc link-twoargs { n1 n2 } {
  725. $self instvar LH_
  726. if ![info exists LH_($n1:$n2)] {
  727. set LH_($n1:$n2) 1
  728. linkHelper LH_:$n1:$n2 $n1 $n2
  729. }
  730. return LH_:$n1:$n2
  731. }
  732. OldSim instproc link-threeargs { n1 n2 qtype } {
  733. # new link with 0 bandwidth and 0 delay
  734. $self simplex-link $n1 $n2 0 0 $qtype
  735.         return [$self link-twoargs $n1 $n2]
  736. }
  737. OldSim instproc trace {} {
  738. return [new traceHelper]
  739. }
  740. OldSim instproc random { seed } {
  741. return [ns-random $seed]
  742. }
  743. proc ns_simplex { n1 n2 bw delay type } {
  744.         # this was never used in ns-1
  745.         puts stderr "ns_simplex: no backward compat"
  746.         exit 1
  747. }
  748. proc ns_duplex { n1 n2 bw delay type } {
  749. ns duplex-link-compat $n1 $n2 $bw $delay $type
  750. return [ns get-queues $n1 $n2]
  751. }
  752. #
  753. # Create a source/sink connection pair and return the source agent.
  754. proc ns_create_connection { srcType srcNode sinkType sinkNode pktClass } {
  755. ns create-connection $srcType $srcNode $sinkType 
  756. $sinkNode $pktClass
  757. }
  758. #
  759. # Create a source/sink CBR pair and return the source agent.
  760. proc ns_create_cbr { srcNode sinkNode pktSize interval fid } {
  761. set s [ns create-connection cbr $srcNode loss-monitor 
  762. $sinkNode $fid]
  763. $s set interval_ $interval
  764. $s set packetSize_ $pktSize
  765. return $s
  766. }
  767. #
  768. # compat code for CBQ
  769. #
  770. proc ns_create_class { parent borrow allot maxidle notused prio depth xdelay } {
  771. set cl [new CBQClass]
  772. #
  773. # major hack: if the prio is 8 (the highest in ns-1) it's
  774. # an internal node, hence no queue disc
  775. if { $prio < 8 } {
  776. set qtype [CBQClass set def_qtype_]
  777. set q [new Queue/$qtype]
  778. $cl install-queue $q
  779. }
  780. set depth [expr $depth + 1]
  781. if { $borrow == "none" } {
  782. set borrowok false
  783. } elseif { $borrow == $parent } {
  784. set borrowok true
  785. } else {
  786. puts stderr "CBQ: borrowing from non-parent not supported"
  787. exit 1
  788. }
  789. $cl setparams $parent $borrowok $allot $maxidle $prio $depth $xdelay
  790. return $cl
  791. }
  792. proc ns_create_class1 { parent borrow allot maxidle notused prio depth xdelay Mb } {
  793. set cl [ns_create_class $parent $borrow $allot $maxidle $notused $prio $depth $xdelay]
  794. ns_class_maxIdle $cl $allot $maxidle $prio $Mb
  795. return $cl
  796. }
  797. proc ns_class_params { cl parent borrow allot maxidle notused prio depth xdelay Mb } {
  798. set depth [expr $depth + 1]
  799. if { $borrow == "none" } {
  800. set borrowok false
  801. } elseif { $borrow == $parent } {
  802. set borrowok true
  803. } else {
  804. puts stderr "CBQ: borrowing from non-parent not supported"
  805. exit 1
  806. }
  807. $cl setparams $parent $borrowok $allot $maxidle $prio $depth $xdelay
  808. ns_class_maxIdle $cl $allot $maxidle $prio $Mb
  809. return $cl
  810. }
  811. #
  812. # If $maxIdle is "auto", set maxIdle to Max[t(1/p-1)(1-g^n)/g^n, t(1-g)].
  813. # For p = allotment, t = packet transmission time, g = weight for EWMA.
  814. # The parameter t is calculated for a medium-sized 1000-byte packet.
  815. #
  816. proc ns_class_maxIdle { cl allot maxIdle priority Mbps } {
  817.         if { $maxIdle == "auto" } {
  818.                 set g 0.9375
  819.                 set n [expr 8 * $priority]
  820.                 set gTOn [expr pow($g, $n)]
  821.                 set first [expr ((1/$allot) - 1) * (1-$gTOn) / $gTOn ]
  822.                 set second [expr (1 - $g)]
  823.                 set packetsize 1000
  824.                 set t [expr ($packetsize * 8)/($Mbps * 1000000) ]
  825.                 if { $first > $second } {
  826.                         $cl set maxidle_ [expr $t * $first]
  827.                 } else {
  828.                         $cl set maxidle_ [expr $t * $second]
  829.                 }
  830.         } else {
  831.                 $cl set maxidle_ $maxIdle
  832.         }
  833.         return $cl
  834. }
  835. #
  836. # backward compat for agent methods that were replaced
  837. # by OTcl instance variables
  838. #
  839. Agent instproc connect d {
  840. $self set dst_ $d
  841. }
  842. # XXX changed call from "handle" to "recv"
  843. Agent/Message instproc recv msg {
  844. $self handle $msg
  845. }
  846. #Renamed variables in Queue/RED and Queue/DropTail
  847. Queue/RED proc set { var {arg ""} } {
  848. if { $var == "queue-in-bytes_" } {
  849. warn "Warning: use `queue_in_bytes_' rather than `queue-in-bytes_'"
  850. set var "queue_in_bytes_"
  851. } elseif { $var == "drop-tail_" } {
  852. warn "Warning: use `drop_tail_' rather than `drop-tail_'"
  853. set var "drop_tail_"
  854. } elseif { $var == "drop-front_" } {
  855. warn "Warning: use `drop_front_' rather than `drop-front_'"
  856. set var "drop_front_"
  857. } elseif { $var == "drop-rand_" } {
  858. warn "Warning: use `drop_rand_' rather than `drop-rand_'"
  859. set var "drop_rand_"
  860. } elseif { $var == "ns1-compat_" } {
  861. warn "Warning: use `ns1_compat_' rather than `ns1-compat_'"
  862. set var "ns1_compat_"
  863. }
  864. eval $self next $var $arg
  865. }
  866. Queue/DropTail proc set { var {arg ""} } {
  867. if { $var == "drop-front_" } {
  868. warn "Warning: use `drop_front_' rather than `drop-front_'"
  869. set var "drop_front_"
  870. }
  871. eval $self next $var $arg
  872. }