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

通讯编程

开发平台:

Visual C++

  1. #
  2. # tcl/mcast/ns-mcast.tcl
  3. #
  4. # Copyright (C) 1997 by USC/ISI
  5. # All rights reserved.                                            
  6. #                                                                
  7. # Redistribution and use in source and binary forms are permitted
  8. # provided that the above copyright notice and this paragraph are
  9. # duplicated in all such forms and that any documentation, advertising
  10. # materials, and other materials related to such distribution and use
  11. # acknowledge that the software was developed by the University of
  12. # Southern California, Information Sciences Institute.  The name of the
  13. # University may not be used to endorse or promote products derived from
  14. # this software without specific prior written permission.
  15. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  16. # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18. # Ported by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
  19. #
  20. ###############
  21. # The MultiSim stuff below is only for backward compatibility.
  22. Class MultiSim -superclass Simulator
  23. MultiSim instproc init args {
  24.         eval $self next $args
  25.         $self multicast on
  26. }
  27. Simulator instproc multicast args {
  28.         $self set multiSim_ 1
  29. Node enable-module Mcast
  30. }
  31. Simulator instproc multicast? {} {
  32.         $self instvar multiSim_
  33.         if { ![info exists multiSim_] } {
  34.                 set multiSim_ 0
  35.         }
  36.         set multiSim_
  37. }
  38. Simulator instproc run-mcast {} {
  39.         $self instvar Node_
  40.         foreach n [array names Node_] {
  41.                 set node $Node_($n)
  42. $node start-mcast
  43.         }
  44.         $self next
  45. }
  46. Simulator instproc clear-mcast {} {
  47.         $self instvar Node_
  48.         foreach n [array names Node_] {
  49.                 $Node_($n) stop-mcast
  50.         }
  51. }
  52. Simulator instproc mrtproto { mproto { nodelist "" } } {
  53. $self instvar Node_ MrtHandle_
  54. set MrtHandle_ ""
  55. if { $mproto == "CtrMcast" } {
  56. set MrtHandle_ [new CtrMcastComp $self]
  57. $MrtHandle_ set ctrrpcomp [new CtrRPComp $self]
  58. }
  59. # XXX This is a ugly hack! Why not delete existing classifier???
  60. if { $mproto == "BST" } {
  61. foreach n [array names Node_] {
  62. if ![$Node_($n) is-lan?] {
  63.     $Node_($n) instvar multiclassifier_ switch_
  64. #      delete $multiclassifier_
  65.     set multiclassifier_ [new Classifier/Multicast/Replicator/BST]
  66.     $multiclassifier_ set node_ $Node_($n)
  67.     $switch_ install 1 $multiclassifier_
  68. }
  69. }
  70. }
  71. if { $nodelist == "" } {
  72. foreach n [array names Node_] {
  73. $self mrtproto-iifs $mproto $Node_($n) ""
  74. }
  75. } else {
  76. foreach node $nodelist {
  77. $self mrtproto-iifs $mproto $node ""
  78. }
  79. }
  80. $self at 0.0 "$self run-mcast"
  81. return $MrtHandle_
  82. }
  83. #finer control than mrtproto: specify which iifs protocols owns
  84. Simulator instproc mrtproto-iifs {mproto node iiflist } {
  85. set mh [new $mproto $self $node]
  86. set arbiter [$node getArbiter]
  87. if { $arbiter != "" } {
  88. $arbiter addproto $mh $iiflist
  89. }
  90. }
  91. Node proc allocaddr {} {
  92. # return a unique mcast address
  93. set addr [Simulator set McastAddr_]
  94. Simulator set McastAddr_ [expr $addr + 1]
  95. return $addr
  96. }
  97. Node proc expandaddr {} {
  98.         # calling set-address-format with expanded option (sets nodeid with 
  99. # 21 bits 
  100.         # & sets aside 1 bit for mcast) and sets portid with 8 bits
  101. # if hierarchical address format is set, just expands the McastAddr_
  102. [Simulator instance] set-address-format expanded
  103. puts "Backward compatibility: Use "set-address-format expanded" instead of "Node expandaddr";" 
  104. }
  105. Node instproc start-mcast {} {
  106.         $self instvar mrtObject_
  107.         $mrtObject_ start
  108. }
  109. Node instproc getArbiter {} {
  110.         $self instvar mrtObject_
  111. if [info exists mrtObject_] {
  112.         return $mrtObject_
  113. }
  114. return ""
  115. }
  116. Node instproc notify-mcast changes {
  117. $self instvar mrtObject_
  118. if [info exists mrtObject_] {
  119. $mrtObject_ notify $changes
  120. }
  121. }
  122. Node instproc stop-mcast {} {
  123.         $self instvar mrtObject_
  124.         $self clear-caches
  125.         $mrtObject_ stop
  126. }
  127. Node instproc clear-caches {} {
  128.         $self instvar Agents_  multiclassifier_ replicator_
  129.         $multiclassifier_ clearAll
  130. $multiclassifier_ set nrep_ 0
  131. foreach var {Agents_ replicator_} {
  132. $self instvar $var
  133. if { [info exists $var] } {
  134. delete $var
  135. unset $var
  136. }
  137. }
  138.         # XXX watch out for memory leaks
  139. }
  140. Node instproc dump-routes args {
  141. $self instvar mrtObject_
  142. if { [info exists mrtObject_] } {
  143. eval $mrtObject_ dump-routes $args
  144. }
  145. }
  146. Node instproc check-local { group } {
  147.         $self instvar Agents_
  148.         if [info exists Agents_($group)] {
  149.                 return [llength $Agents_($group)]
  150.         }
  151.         return 0
  152. }
  153. Node instproc new-group { src group iface code } {
  154. $self instvar mrtObject_
  155. $mrtObject_ upcall $code $src $group $iface
  156. }
  157. Node instproc join-group { agent group { src "" } } {
  158.         $self instvar replicator_ Agents_ mrtObject_
  159.         set group [expr $group] ;# use expr to convert to decimal
  160.         $mrtObject_ join-group $group $src
  161.         lappend Agents_($group) $agent
  162. if { $src == "" } {
  163. set reps [$self getReps "*" $group]
  164. } else {
  165. set reps [$self getReps $src $group]
  166. }
  167.         foreach rep $reps {
  168.                 # make sure agent is enabled in each replicator for this group
  169.                 $rep insert $agent
  170.         }
  171. }
  172. Node instproc leave-group { agent group { src "" } } {
  173.         $self instvar replicator_ Agents_ mrtObject_
  174.         set group [expr $group] ;# use expr to get rid of possible leading 0x
  175. if { $src == "" } {
  176. set reps [$self getReps "*" $group]
  177. } else {
  178. set reps [$self getReps $src $group]
  179. }
  180.         foreach rep $reps  {
  181.                 $rep disable $agent
  182.         }
  183.         if [info exists Agents_($group)] {
  184.                 set k [lsearch -exact $Agents_($group) $agent]
  185. set Agents_($group) [lreplace $Agents_($group) $k $k]
  186.                 $mrtObject_ leave-group $group $src
  187.         } else {
  188.                 warn "cannot leave a group without joining it"
  189.         }
  190. }
  191. Node instproc add-mfc { src group iif oiflist } {
  192. $self instvar multiclassifier_ 
  193. replicator_ Agents_ 
  194. if [info exists replicator_($src:$group)] {
  195. set r $replicator_($src:$group)
  196. } else {
  197. set r [new Classifier/Replicator/Demuxer]
  198. $r set srcID_ $src
  199. $r set grp_ $group
  200. set replicator_($src:$group) $r
  201. $r set node_ $self
  202. #
  203. # install each agent that has previously joined this group
  204. #
  205. if [info exists Agents_($group)] {
  206. foreach a $Agents_($group) {
  207. $r insert $a
  208. }
  209. }
  210. # we also need to check Agents($srcID:$group)
  211. if [info exists Agents_($src:$group)] {
  212. foreach a $Agents_($src:$group) {
  213. $r insert $a
  214. }
  215. }
  216. #
  217. # Install the replicator.  
  218. #
  219. $multiclassifier_ add-rep $r $src $group $iif
  220. }
  221. foreach oif [lsort $oiflist] {
  222. $r insert $oif
  223. }
  224. }
  225. Node instproc del-mfc { srcID group oiflist } {
  226.         $self instvar replicator_ multiclassifier_
  227.         if [info exists replicator_($srcID:$group)] {
  228.                 set r $replicator_($srcID:$group)  
  229.                 foreach oif $oiflist {
  230.                         $r disable $oif
  231.                 }
  232.                 return 1
  233.         } 
  234.         return 0
  235. }
  236. ####################
  237. Class Classifier/Multicast/Replicator -superclass Classifier/Multicast
  238. #
  239. # This method called when a new multicast group/source pair
  240. # is seen by the underlying classifier/mcast object.
  241. # We install a hash for the pair mapping it to a slot
  242. # number in the classifier table and point the slot
  243. # at a replicator object that sends each packet along
  244. # the RPF tree.
  245. #
  246. Classifier/Multicast instproc new-group { src group iface code} {
  247. $self instvar node_
  248. $node_ new-group $src $group $iface $code
  249. }
  250. Classifier/Multicast instproc no-slot slot {
  251. # NOTHING
  252. }
  253. Classifier/Multicast/Replicator instproc init args {
  254. $self next
  255. $self instvar nrep_
  256. set nrep_ 0
  257. }
  258. Classifier/Multicast/Replicator instproc add-rep { rep src group iif } {
  259. $self instvar nrep_
  260. $self set-hash $src $group $nrep_ $iif
  261. $self install $nrep_ $rep
  262. incr nrep_
  263. }
  264. ###################### Class Classifier/Replicator/Demuxer ##############
  265. Class Classifier/Replicator/Demuxer -superclass Classifier/Replicator
  266. Classifier/Replicator/Demuxer set ignore_ 0
  267. Classifier/Replicator/Demuxer instproc init args {
  268. eval $self next $args
  269. $self instvar nslot_ nactive_
  270. set nactive_ 0
  271. }
  272. Classifier/Replicator/Demuxer instproc is-active {} {
  273. $self instvar nactive_
  274. expr $nactive_ > 0
  275. }
  276. Classifier/Replicator/Demuxer instproc insert target {
  277. $self instvar nactive_ active_ 
  278. if ![info exists active_($target)] {
  279. set active_($target) -1
  280. }
  281. if {$active_($target) < 0} {
  282. $self enable $target
  283. }
  284. }
  285. Classifier/Replicator/Demuxer instproc dump-oifs {} {
  286. set oifs ""
  287. if [$self is-active] {
  288. $self instvar active_
  289. foreach target [array names active_] {
  290. if { $active_($target) >= 0 } {
  291. lappend oifs [$self slot $active_($target)]
  292. }
  293. }
  294. }
  295. return [lsort $oifs]
  296. }
  297. Classifier/Replicator/Demuxer instproc disable target {
  298. $self instvar nactive_ active_
  299. if {[info exists active_($target)] && $active_($target) >= 0} {
  300. $self clear $active_($target)
  301. set active_($target) -1
  302. incr nactive_ -1
  303. }
  304. }
  305. Classifier/Replicator/Demuxer instproc enable target {
  306. $self instvar nactive_ active_ ignore_
  307. if {$active_($target) < 0} {
  308. set active_($target) [$self installNext $target]
  309. incr nactive_
  310. set ignore_ 0
  311. }
  312. }
  313. Classifier/Replicator/Demuxer instproc exists target {
  314. $self instvar active_
  315. info exists active_($target)
  316. }
  317. Classifier/Replicator/Demuxer instproc is-active-target target {
  318. $self instvar active_
  319. if { [info exists active_($target)] && $active_($target) >= 0 } {
  320. return 1
  321. } else {
  322. return 0
  323. }
  324. }
  325. Classifier/Replicator/Demuxer instproc drop { src dst {iface -1} } {
  326. $self instvar node_
  327. [$node_ getArbiter] drop $self $src $dst $iface
  328. }
  329. Node instproc change-iface { src dst oldiface newiface} {
  330. $self instvar multiclassifier_
  331.         $multiclassifier_ change-iface $src $dst $oldiface $newiface
  332. }
  333. Node instproc lookup-iface { src dst } {
  334. $self instvar multiclassifier_
  335.         $multiclassifier_ lookup-iface $src $dst
  336. }
  337. Classifier/Replicator/Demuxer instproc reset {} {
  338. $self instvar nactive_ active_
  339. foreach { target slot } [array get active_] {
  340. $self clear $slot
  341. }
  342. set nactive_ 0
  343. unset active_
  344. }
  345. Agent/Mcast/Control instproc init { protocol } {
  346.  $self next
  347.  $self instvar proto_
  348.  set proto_ $protocol
  349. }
  350. Agent/Mcast/Control array set messages {}
  351. Agent/Mcast/Control set mcounter 0
  352. Agent/Mcast/Control instproc send {type from src group args} {
  353. Agent/Mcast/Control instvar mcounter messages
  354. set messages($mcounter) [concat [list $from $src $group] $args]
  355. $self cmd send $type $mcounter
  356. incr mcounter
  357. }
  358. Agent/Mcast/Control instproc recv {type iface m} {
  359. Agent/Mcast/Control instvar messages
  360. eval $self recv2 $type $iface $messages($m)
  361.         #unset messages($m)
  362. }
  363. Agent/Mcast/Control instproc recv2 {type iface from src group args} {
  364.         $self instvar proto_
  365.         eval $proto_ recv-$type $from $src $group $iface $args
  366. }
  367. Node instproc rpf-nbr src {
  368. $self instvar ns_ id_
  369. if [catch "$src id" srcID] {
  370. set srcID $src
  371. }
  372. $ns_ get-node-by-id [[$ns_ get-routelogic] lookup $id_ $srcID]
  373. }
  374. LanNode instproc rpf-nbr src {
  375. $self instvar ns_ id_
  376. if [catch "$src id" srcID] {
  377. set srcID $src
  378. }
  379. $ns_ get-node-by-id [[$ns_ get-routelogic] lookup $id_ $srcID]
  380. }
  381. Node instproc getReps { src group } {
  382.         $self instvar replicator_
  383.         set reps ""
  384.         foreach key [array names replicator_ "$src:$group"] { 
  385.                 lappend reps $replicator_($key)
  386.         }
  387.         return [lsort $reps]
  388. }
  389. Node instproc getReps-raw { src group } {
  390.         $self array get replicator_ "$src:$group"
  391. }
  392. Node instproc clearReps { src group } {
  393.         $self instvar multiclassifier_
  394.         foreach {key rep} [$self getReps-raw $src $group] {
  395.                 $rep reset
  396.                 delete $rep
  397.                 foreach {slot val} [$multiclassifier_ adjacents] {
  398.                         if { $val == $rep } {
  399.                                 $multiclassifier_ clear $slot
  400.                         }
  401.                 }
  402.                 $self unset replicator_($key)
  403.         }
  404. }
  405. Node instproc add-oif {head link} {
  406. $self instvar outLink_
  407. set outLink_($head) $link
  408. }
  409. Node instproc add-iif {iflbl link} {
  410. # array mapping ifnum -> link
  411. $self set inLink_($iflbl) $link
  412. }
  413. Node instproc get-all-oifs {} {
  414.         $self instvar outLink_
  415. # return a sorted list of all "heads"
  416. return [lsort [array names outLink_]]
  417. }
  418. Node instproc get-all-iifs {} {
  419. $self instvar inLink_
  420. # return a list of "labels"
  421. return [array names inLink_]
  422. }
  423. Node instproc iif2oif ifid {
  424. $self instvar ns_
  425. set link [$self iif2link $ifid]
  426. # assuming that there have to be a reverse link
  427. # that is, all links are duplex.
  428. set outlink [$ns_ link $self [$link src]]
  429. return [$self link2oif $outlink]
  430. }
  431. Node instproc iif2link ifid {
  432.         $self set inLink_($ifid)
  433. }
  434. Node instproc link2iif link {
  435. return [[$link set iif_] label]
  436. }
  437. Node instproc link2oif link {
  438. $link head
  439. }
  440. Node instproc oif2link oif {
  441. $oif set link_
  442. }
  443. # Find out what interface packets sent from $node will arrive at
  444. # this node. $node need not be a neighbor. $node can be a node object
  445. # or node id.
  446. Node instproc from-node-iface { node } {
  447. $self instvar ns_
  448. catch {
  449. set node [$ns_ get-node-by-id $node]
  450. }
  451. set rpfnbr [$self rpf-nbr $node]
  452. set rpflink [$ns_ link $rpfnbr $self]
  453. if { $rpflink != "" } {
  454. return [$rpflink if-label?]
  455. }
  456. return "?" ;#unknown iface
  457. }
  458. Vlink instproc if-label? {} {
  459. $self instvar iif_
  460. $iif_ label
  461. }