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

通讯编程

开发平台:

Visual C++

  1. #
  2. # tcl/mcast/BST.tcl
  3. #
  4. #
  5. # Copyright (C) 1998 by USC/ISI
  6. # All rights reserved.                                            
  7. #                                                                
  8. # Redistribution and use in source and binary forms are permitted
  9. # provided that the above copyright notice and this paragraph are
  10. # duplicated in all such forms and that any documentation, advertising
  11. # materials, and other materials related to such distribution and use
  12. # acknowledge that the software was developed by the University of
  13. # Southern California, Information Sciences Institute.  The name of the
  14. # University may not be used to endorse or promote products derived from
  15. # this software without specific prior written permission.
  16. # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  17. # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19. #
  20. #
  21. # Written by Yuri Pryadkin
  22. # Modified by Nader Saelhi
  23. #
  24. ###############
  25. # Implementation of a simple shared bi-directional tree protocol.  No
  26. # timers.  Nodes send grafts/prunes toward the RP to join/leave the
  27. # group.  The user needs to set two protocol variables: 
  28. #
  29. # "BST set RP_($group) $node" - indicates that $node 
  30. #                               acts as an RP for the $group
  31. Class BST -superclass McastProtocol
  32. BST instproc init { sim node } {
  33. $self instvar mctrl_ oiflist_
  34. BST instvar RP_
  35. set mctrl_ [new Agent/Mcast/Control $self]
  36. $node attach $mctrl_
  37. $self next $sim $node
  38. }
  39. BST instproc start {} {
  40. $self instvar node_ oiflist_
  41. BST instvar RP_
  42. # need to do it in start when unicast routing is computed
  43. foreach grpx [array names RP_] {
  44.                 set grp [expr $grpx]
  45. #        $self dbg "BST: grp $grp, node [$node_ id]"
  46.                 if { [string compare $grp $grpx] } {
  47. set RP_($grp) $RP_(grpx)
  48. unset RP_($grpx)
  49.                 }
  50. set rpfiif [$node_ from-node-iface $RP_($grp)]
  51. # $self dbg "BST: rpfiif $rpfiif"
  52. if { $rpfiif != "?" } {
  53. set rpfoif [$node_ iif2oif $rpfiif]
  54. } else {
  55. set rpfoif ""
  56. }
  57. # initialize with the value of rpfoif
  58. set oiflist_($grp) $rpfoif
  59. set neighbors [$node_ set neighbor_]
  60. if [info exists neighbors] {
  61. for {set i 0} {$i < [llength $neighbors]} {incr i} {
  62. set neighbor [lindex $neighbors $i]
  63. set class_info [$neighbor info class]
  64. if {$class_info == "LanNode"} {
  65. # This node is on a LAN, we
  66. # must designate a router for
  67. # the mcast group   
  68. $neighbor designate-ump-router $grp 
  69.     $RP_($grp)
  70. }
  71. }
  72. }
  73. }
  74. }
  75. BST instproc join-group  { group {src "x"} } {
  76. $self instvar node_ ns_ oiflist_
  77. BST instvar RP_
  78. set nbr [$node_ rpf-nbr $RP_($group)]
  79. set nbrs($nbr) 1
  80. $node_ add-mark m1 blue "[$node_ get-shape]"
  81. foreach nbr [array names nbrs] {
  82. if [$nbr is-lan?] {
  83. $nbr instvar receivers_
  84. if [info exists receivers_($group)] {
  85. incr receivers_($group)
  86. } else {
  87. $self send-ctrl "graft" $RP_($group) $group
  88. set receivers_($group) 1
  89. }
  90. }
  91. $self next $group ; #annotate
  92. }
  93. if { ![$node_ check-local $group] || [$node_ getReps "x" 
  94.       $group] == ""} { 
  95. #  $self dbg "Sending join-group"
  96. $self send-ctrl "graft" $RP_($group) $group
  97. }
  98. }
  99. BST instproc leave-group { group {src "x"} } {
  100. BST instvar RP_ 
  101. $self next $group ;#annotate
  102. $self instvar node_ oiflist_
  103. set nbr [$node_ rpf-nbr $RP_($group)]
  104. if  [$nbr is-lan?] {
  105. $nbr instvar receivers_
  106. if [info exists receivers_($group)] {
  107. if {$receivers_($group) > 0} {
  108. incr receivers_($group) -1
  109. if {$receivers_($group) == 0} {
  110. $node_ delete-mark m1
  111. $self send-ctrl "prune" $RP_($group) $group
  112. }
  113. }
  114. } else {
  115. # Nobody has joined yet
  116. return
  117. }
  118. } else {
  119. set rpfiif [$node_ from-node-iface $RP_($group)]
  120. if { $rpfiif != "?" } {
  121. set rpfoif [$node_ iif2oif $rpfiif]
  122. } else {
  123. set rpfoif ""
  124. }
  125. if { $oiflist_($group) == 
  126.  $rpfoif && ![$node_ check-local $group] } {
  127. # propagate
  128. $self send-ctrl "prune" $RP_($group) $group
  129. $node_ delete-mark m1
  130. } else {
  131. $node_ delete-mark m1
  132. $node_ add-mark m2 red circle
  133. }
  134. }
  135. }
  136. # handle-wrong-iif
  137. # This function does nothing
  138. BST instproc handle-wrong-iif { srcID group iface } {
  139. $self instvar node_ oiflist_
  140. BST instvar RP_
  141. #     $self dbg "BST: wrong iif $iface, src $srcID, grp $group"
  142. #     $self dbg "t oiflist: $oiflist_($group)"
  143. set rep [$node_ getReps "x" $group]
  144. $node_ add-mfc "x" $group $iface $oiflist_($group)
  145. set iif [$node_ lookup-iface "x" $group]
  146. if { $iface >= 0 } {
  147. set oif [$node_ iif2oif $iface]
  148. set rpfiif [$node_ from-node-iface $RP_($group)]
  149. if { $iface == $rpfiif } {
  150. # forward direction: disable oif to RP
  151. $rep disable [$node_ iif2oif $rpfiif]
  152. } else {
  153. # reverse direction: disable where it came from
  154. $rep disable $oif
  155. if { $node_ != $RP_($group) } {
  156. $rep insert [$node_ iif2oif $rpfiif]
  157. }
  158. }
  159. }
  160. $node_ change-iface "x" $group $iif $iface
  161. return 1 ;#classify packet again
  162. }
  163. # handle-cache-miss
  164. # Creates a (*, G) entry for a group.  
  165. BST instproc handle-cache-miss { srcID group iface } {
  166. $self instvar node_  ns_ oiflist_
  167. BST instvar RP_
  168. if { [$node_ getReps "x" $group] != "" } {
  169. error
  170. }
  171. #       $self dbg 
  172. #       "handle-cache-miss, src: $srcID, group: $group, iface: $iface"
  173. #      $self dbg 
  174. #       "********* miss: adding <x, $group, $iface, $oiflist_($group)>"
  175. # Check if the node is on a LAN.  If so we should NOT resume
  176. # if:
  177. # 1) The node is not the next upstream router, and
  178. # 2) The incoming interface is to a LanNode, and
  179. # 3) The node is not a source.
  180.   if {$iface != -1} {
  181. # if the node is not a source (3)
  182.   set neighbors [$node_ set neighbor_]
  183. if [info exists neighbors] {
  184. for {set i 0} {$i < [llength $neighbors]} {incr i} {
  185. set neighbor [lindex $neighbors $i]
  186. set nbr [$node_ rpf-nbr $RP_($group)]
  187. if {[$neighbor is-lan?] && 
  188. [$nbr info class] != "LanNode"} {
  189. # The node is directly
  190. # connected to RP --or at
  191. # least not via LanNode
  192. $neighbor instvar up_
  193. set up [$neighbor set up_($group)]
  194. if {$node_ != $up} {
  195. # If not the upstream
  196. # router (1) 
  197. if [$self link2lan? $neighbor 
  198. $iface] {
  199. # The interface is to 
  200. # the LAN
  201. return 0
  202. }
  203. }
  204. }
  205. }
  206. }
  207.   }
  208.     
  209. $node_ add-mfc "x" $group $iface $oiflist_($group)
  210. if { $iface > 0 } {
  211. #disable reverse iface
  212. set rep [$node_ getReps "x" $group]
  213. $rep disable [$node_ iif2oif $iface]
  214. }
  215. return 1 ;# classify the packet again.
  216. }
  217. BST instproc drop { replicator src dst iface} {
  218. $self instvar node_ ns_
  219. BST instvar RP_
  220. # No downstream listeners? Just drop the packet. No purning is
  221. # necessary  
  222. #  $self dbg "drops src: $src, dst: $dst, replicator: [$replicator set srcID_]"
  223. if {$iface >= 0} {
  224. # so, this packet came from outside of the node.
  225. # Since PIM works based on explicit join mechanism,
  226. # the only action is to drop unwanted packets.
  227. #  $self dbg "drops the unwanted packet"
  228. }
  229. }
  230. BST instproc recv-prune { from src group iface} {
  231. $self instvar node_ ns_ oiflist_ 
  232. BST instvar RP_ 
  233. #  $self dbg "received a prune from: $from, src: $src, grp: $group, if: $iface"
  234. set rep [$node_ getReps "x" $group]
  235. if {$rep != ""} {
  236. set oif [$node_ iif2oif $iface]
  237. set idx [lsearch $oiflist_($group) $oif]
  238. if { $idx >= 0 } {
  239. set oiflist_($group) [lreplace $oiflist_($group) $idx $idx]
  240. $rep disable $oif
  241. set rpfiif [$node_ from-node-iface $RP_($group)]
  242. if { $rpfiif != "?" } {
  243. set rpfoif [$node_ iif2oif $rpfiif]
  244. } else {
  245. set rpfoif ""
  246. }
  247. if { $oiflist_($group) == $rpfoif && ![$node_ check-local $group] } {
  248. # propagate
  249. $node_ delete-mark m2
  250. $self send-ctrl "prune" $RP_($group) $group
  251. }
  252. }
  253. }
  254. }
  255. BST instproc recv-graft { from to group iface } {
  256. $self instvar node_ ns_ oiflist_
  257. BST instvar RP_
  258. #   $self dbg "received a graft from: $from, to: $to, if: $iface"
  259. set oif [$node_ iif2oif $iface]
  260. set rpfiif [$node_ from-node-iface $RP_($group)]
  261. if { $rpfiif != "?" } {
  262. set rpfoif [$node_ iif2oif $rpfiif]
  263. } else {
  264. set rpfoif ""
  265. }
  266. if { $oiflist_($group) == $rpfoif && ![$node_ check-local $group] } {
  267. # propagate
  268. $node_ add-mark m2 red circle
  269. $self send-ctrl "graft" $RP_($group) $group
  270. }
  271. if { [lsearch $oiflist_($group) $oif] < 0 } {
  272. lappend oiflist_($group) $oif
  273. if { [$node_ lookup-iface "x" $group] != $iface } {
  274. set rep [$node_ getReps "x" $group]
  275. if { $rep != "" } {
  276. $rep insert $oif
  277. }
  278. }
  279. }
  280. }
  281. #
  282. # send a graft/prune for src/group up the RPF tree towards dst
  283. #
  284. BST instproc send-ctrl { which dst group } {
  285.         $self instvar mctrl_ ns_ node_
  286. if {$node_ != $dst} {
  287. set nbr [$node_ rpf-nbr $dst]
  288. if [$nbr is-lan?] {
  289. # we're requested to send via a lan
  290. $nbr instvar receivers_
  291. # send graft/prune only if there's no other receiver.
  292. if { [info exists receivers_($group)] && 
  293.  $receivers_($group) > 0 } return
  294. set nbr [$nbr rpf-nbr $dst]
  295. #   $self dbg "BST::send-ctrl The first hop router to LAN is node [$nbr id]"
  296. }
  297. #   $self dbg "BST::send-ctrl $ns_ simplex-connect [[[$nbr getArbiter] getType [$self info class]] set mctrl_]"
  298. $ns_ simplex-connect $mctrl_ 
  299. [[[$nbr getArbiter] getType [$self info class]] set mctrl_]
  300. if { $which == "prune" } {
  301. $mctrl_ set fid_ 2
  302. } else {
  303. $mctrl_ set fid_ 3
  304. }
  305. #  $self dbg "BST::send-ctrl $mctrl_ ([$mctrl_ info class]) send $which [$node_ id] $dst $group"
  306. $mctrl_ send $which [$node_ id] $dst $group
  307. }
  308. }
  309. ################ Helpers
  310. BST instproc dbg arg {
  311. $self instvar ns_ node_
  312. puts [format "At %.4f : node [$node_ id] $arg" [$ns_ now]]
  313. }
  314. # designate-ump-router
  315. # Designates a router on a LAN in order to avoid transmission of
  316. # duplicate and redundant messages.  The node with the highest ID is
  317. # chosen as the designated router.
  318. LanNode instproc designate-ump-router {group dst} {
  319. $self instvar nodelist_
  320. $self instvar up_
  321. set nbr [$self rpf-nbr $dst]
  322. set up_($group) $nbr
  323. return
  324. }
  325. # Returns the next hop router to a node
  326. BST instproc next-hop-router {node group} {
  327. BST instvar RP_
  328. set nbr [$node rpf-nbr $RP_($group)]
  329. if [$nbr is-lan?] {
  330. set nbr [$nbr rpf-nbr $RP_($group)]
  331. }
  332. return $nbr
  333. }
  334. # Checks if an mcast group is BST 
  335. BST instproc is-group-bidir? {group} {
  336. BST instvar RP_
  337. foreach grp [array names RP_] {
  338. if {$grp == $group} {
  339. return 1
  340. }
  341. }
  342. return 0
  343. }
  344. # Finds out which Connector or Vlink corresponds to (link)
  345. BST instproc match-oif {group link} {
  346. $self instvar oiflist_
  347.   set oiflist $oiflist_($group)
  348.    if {$oiflist != ""} {
  349. foreach oif $oiflist {
  350. set oiflink [$oif set link_]
  351. if {$oiflink == $link} {
  352. return $oiflink
  353. }
  354. }
  355.    }
  356. return
  357. }
  358. # Finds the outgoing link to the next node (dst)
  359. BST instproc find-oif {dst group} {
  360. $self instvar node_ ns_
  361. if {$node_ != $dst} {
  362. set ns [$self set ns_]
  363. $ns instvar link_
  364. set link [$ns set link_([$node_ id]:[$dst id])]
  365. # Now find which Connector or VLink corresponds to this link
  366. return [$self match-oif $group $link]
  367. } else {
  368. return ""
  369. }
  370. }
  371. # Finds if the interface (iface) is toward the LAN represented by (neighbor) 
  372. # or not.
  373. BST instproc link2lan? {neighbor iface} {
  374. $self instvar node_ ns_
  375. set link1 [[[$node_ iif2oif $iface] set link_] set iif_]
  376. set link2 [[$ns_ link $node_ $neighbor] set iif_]
  377.      if {$link1 == $link2} {
  378. return 1
  379. } else {
  380. return 0
  381. }
  382. }
  383. ####################
  384. Class Classifier/Multicast/Replicator/BST -superclass Classifier/Multicast/BST
  385. #
  386. # This method called when a new multicast group/source pair
  387. # is seen by the underlying classifier/mcast object.
  388. # We install a hash for the pair mapping it to a slot
  389. # number in the classifier table and point the slot
  390. # at a replicator object that sends each packet along
  391. # the RPF tree.
  392. #
  393. Classifier/Multicast/BST instproc new-group { src group iface code} {
  394. $self instvar node_
  395. $node_ new-group $src $group $iface $code
  396. }
  397. Classifier/Multicast/BST instproc no-slot slot {
  398. # NOTHING
  399. }
  400. Classifier/Multicast/Replicator/BST instproc init args {
  401. $self next
  402. $self instvar nrep_
  403. set nrep_ 0
  404. }
  405. Classifier/Multicast/Replicator/BST instproc add-rep { rep src group iif } {
  406. $self instvar nrep_
  407. $self set-hash $src $group $nrep_ $iif
  408. $self install $nrep_ $rep
  409. incr nrep_
  410. }
  411. ####################
  412. # match-BST-iif
  413. # Performs the RPF 
  414. Classifier/Multicast/Replicator/BST instproc match-BST-iif {iface group} {
  415. $self instvar node_
  416. list retval_
  417. set agents [$node_ set agents_]
  418. for {set i 0} {$i < [llength $agents]} {incr i} {
  419. # Check if you can find a BST agent
  420. set agent [lindex $agents $i]
  421. $agent instvar proto_
  422. if [info exists proto_] {
  423. set protocol [$agent set proto_]
  424. if {[$protocol info class] == "BST"} {
  425. # See if the group is a BST group
  426. BST instvar RP_
  427. $protocol instvar oiflist_
  428. set bidir [$protocol is-group-bidir? $group]
  429. if {$bidir == 1} {
  430. if {$node_ == $RP_($group)} {
  431. return 1
  432. }
  433. # Find the incoming interface
  434. # from RP.
  435. set iif [$node_ from-node-iface 
  436.      $RP_($group)]
  437. if {$iif == $iface} {
  438. return 1
  439. } else {
  440. return 0
  441. }
  442. }
  443. }
  444. }
  445. }
  446. return -1
  447. }
  448. # Classifier/Multicast/Replicator upstream-link
  449. # Finds the link from the next hop upstream router to the current
  450. # node.  This function is called from C++ to provide the classifier
  451. # with appropriate information to set the UMP option.
  452. Classifier/Multicast/Replicator/BST instproc upstream-link {group} {
  453. $self instvar node_
  454. list retval_
  455. set agents [$node_ set agents_]
  456. for {set i 0} {$i < [llength $agents]} {incr i} {
  457. # Check if you can find a BST agent
  458. set agent [lindex $agents $i]
  459. $agent instvar proto_
  460. if [info exists proto_] {
  461. set protocol [$agent set proto_]
  462. if {[$protocol info class] == "BST"} {
  463. # See if the group is a BST group
  464. BST instvar RP_
  465. $protocol instvar oiflist_
  466. set bidir [$protocol is-group-bidir? $group]
  467. if {$bidir == 1} {
  468. # Get the next node, REAL or VIRTUAL!
  469. set nbr [$node_ rpf-nbr $RP_($group)]
  470. # Find the outgoing link to the next
  471. # node 
  472. set oif [$protocol find-oif $nbr 
  473.      $group]
  474. if {$oif == ""} {
  475. set oif "self"
  476. lappend retval_ $oif
  477. # Now attach the next node's ID
  478. # If the neighbor is a virtual
  479. # name, we need to find the
  480. # designated router on the
  481. # LAN. Currently, the
  482. # designated router is the one
  483. # which is the closest to the RP.
  484. if [$nbr is-lan?] {
  485.     set nbr [$nbr rpf-nbr $RP_($group)]
  486. }
  487. lappend retval_ [$nbr id]
  488. return $retval_
  489. }
  490. }
  491. }
  492. }
  493. #  $self dbg "There is no agent for this node!"
  494. return {}
  495. }
  496. # check-rpf-link 
  497. # Finds out the RPF link for a node
  498. Classifier/Multicast/Replicator/BST instproc check-rpf-link {node group} {
  499. $self instvar node_
  500. set agents [$node_ set agents_]
  501. for {set i 0} {$i < [llength $agents]} {incr i} {
  502. # Check if you can find a BST agent
  503. set agent [lindex $agents $i]
  504. $agent instvar proto_
  505. if [info exists proto_] {
  506. set protocol [$agent set proto_]
  507. set classInfo [$protocol info class]
  508. if {$classInfo == "BST"} {
  509. # See if the group is a BST group
  510. BST instvar RP_
  511. set rpfiif [$node_ from-node-iface 
  512. $RP_($group)]
  513. return $rpfiif
  514. }
  515. }
  516. }
  517. return -1
  518. }