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

通讯编程

开发平台:

Visual C++

  1. #
  2. # tcl/mcast/ST.tcl
  3. #
  4. # Copyright (C) 1998 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. # Simple implementation of a shared tree protocol.  No timers.  Nodes
  19. # send grafts/prunes toward the RP to join/leave the group.  The user
  20. # needs to set a protocol variable specifying the RP for a particular
  21. # group (no bootstrap):
  22. #      "ST set RP_($group) $node"
  23. # indicates that $node acts as an RP for the $group
  24. #
  25. # TO DO: local receivers receive packets from local senders only after
  26. # the trip to RP and back.  Would be nice to receive right away using
  27. # Decapsulator's decap-target...
  28. Class ST -superclass McastProtocol
  29. ST instproc init { sim node } {
  30. ST instvar RP_ decaps_ ;#RPs and decapsulators by group
  31. if ![info exists RP_] {
  32. error "ST: 'ST instvar RP_' must be set"
  33. exit 1
  34. }
  35. $self next $sim $node
  36. $self instvar ns_ node_ id_ encaps_ mctrl_
  37. set id_ [$node id]
  38. set mctrl_ [new Agent/Mcast/Control $self]
  39. $node attach $mctrl_
  40. foreach grpx [array names RP_] {
  41. set grp [expr $grpx]
  42. if [string compare $grp $grpx] {
  43. set RP_($grp) $RP_($grpx)
  44. unset RP_($grpx)
  45. }
  46. foreach agent [$node set agents_] {
  47. if {$grp == [$agent set dst_addr_]}  {
  48. #found an agent that's sending to a group.
  49. #need to insert an Encapsulator
  50. $self dbg "attaching a Encapsulator for group $grp"
  51. set e [new Agent/Encapsulator]
  52. $e set class_ 32
  53. $e set status_ 1
  54. $node attach $e
  55. $agent target $e
  56. $e decap-target ""
  57. lappend encaps_($grp) $e
  58. }
  59. }
  60. #if the node is an RP, need to attach a Decapsulator
  61. if {$RP_($grp) == $node} {
  62. $self dbg "attaching a Decapsulator for group $grp"
  63. set d [new Agent/Decapsulator]
  64. $node attach $d
  65. set decaps_($grp) $d
  66. $node set decaps_($grp) $d 
  67. }
  68. }
  69. }
  70. ST instproc start {} {
  71. ST instvar decaps_     ;# arrays built during init
  72. $self instvar encaps_  ;# call
  73. $self instvar ns_
  74. #interconnect all agents, decapsulators and encapsulators
  75. #this had better be done in init()
  76. foreach grp [array names encaps_] {
  77. foreach e $encaps_($grp) {
  78. $ns_ simplex-connect $e $decaps_($grp)
  79. }
  80. }
  81. $self next
  82. }
  83. ST instproc join-group  { group {src "x"} } {
  84. if { $src != "x" } return
  85. $self instvar node_ ns_
  86. ST instvar RP_
  87. set r [$node_ getReps "x" $group]
  88. if {$r == ""} {
  89. set iif [$node_ from-node-iface $RP_($group)]
  90. $self dbg "********* join: adding <x, $group, $iif>"
  91. $node_ add-mfc "x" $group $iif ""
  92. set r [$node_ getReps "x" $group]
  93. }
  94. if { ![$r is-active] } {
  95. $self send-ctrl "graft" $RP_($group) $group
  96. }
  97. $self next $group ; #annotate
  98. }
  99. ST instproc leave-group { group {src "x"} } {
  100. if { $src != "x" } return
  101. $self instvar node_
  102. ST instvar RP_
  103. $self next $group
  104. # check if the rep is active, then send a prune
  105. set r [$node_ getReps "x" $group]
  106. if ![$r is-active] {
  107. $self send-ctrl "prune" $RP_($group) $group
  108. }
  109. }
  110. ST instproc handle-wrong-iif { srcID group iface } {
  111. $self instvar node_
  112. $self dbg "!!!!!ST: wrong iif $iface, src $srcID, grp $group"
  113. return 0
  114. }
  115. # There should be only one mfc cache miss: the first time it receives a 
  116. # packet to the group (RP). Just install a (x,G) entry.
  117. ST instproc handle-cache-miss { srcID group iface } {
  118. $self instvar node_
  119. ST instvar RP_
  120. # RP gets packets from the local decapsulator, so iface must be "?" (-1)
  121. if { $iface != -1 } {$self dbg ".....invalid cache miss" }
  122. $self dbg "cache miss, src: $srcID, group: $group, iface: $iface"
  123. $self dbg "********* miss: adding <x, $group, $iface, >"
  124. $node_ add-mfc "x" $group $iface "" 
  125. return 1
  126. }
  127. ST instproc drop { replicator src dst iface} {
  128. $self instvar node_ ns_
  129. ST instvar RP_
  130. # No downstream listeners
  131. # Send a prune back toward the RP
  132. $self dbg "drops src: $src, dst: $dst, iface: $iface, replicator: [$replicator set srcID_]"
  133. if {$iface != -1} {
  134. # so, this packet came from outside of the node
  135. $self send-ctrl "prune" $RP_($dst) $dst
  136. }
  137. }
  138. ST instproc recv-prune { from src group iface } {
  139. $self instvar node_ ns_ id_
  140. ST instvar RP_ 
  141. set r [$node_ getReps "x" $group]
  142. if {$r == ""} {
  143. # it's a cache miss!
  144. $self dbg "recvd a prune, do nothing........"
  145. return
  146. }
  147. set oif [$node_ iif2oif $iface]
  148. if ![$r exists $oif] {
  149. warn "node $id_, got a prune from $from, trying to prune a non-existing interface?"
  150. } else {
  151. if [$r is-active-target $oif] {
  152. $r disable $oif
  153. }
  154. # If there are no remaining active output links
  155. # then send a prune upstream.
  156. if {![$r is-active]} {
  157. $self send-ctrl "prune" $RP_($group) $group
  158. }
  159. }
  160. }
  161. ST instproc recv-graft { from to group iface} {
  162. $self instvar node_ ns_ id_
  163. ST instvar RP_
  164. $self dbg "received a shared graft from: $from, to: $to"
  165. set r [$node_ getReps "x" $group]
  166. if { $r == "" } {
  167. set iif -1
  168. if { $node_ != $RP_($group) } {
  169. set nbr [$node_ rpf-nbr $RP_($group)]
  170. set iiflnk [$ns_ link $nbr $node_] 
  171. set iif [$node_ link2iif $iiflnk]
  172. }
  173. $self dbg "********* graft: adding <x, $group, $iif>"
  174. $node_ add-mfc "x" $group $iif ""
  175. set r [$node_ getReps "x" $group]
  176. }
  177. if {![$r is-active]} {
  178. # if this node isn't on the tree, propagate the graft
  179. # if it's an RP, don't need to, but send-ctrl takes care of that.
  180. $self send-ctrl "graft" $RP_($group) $group
  181. }
  182. # graft on the interface
  183. $r insert [$node_ iif2oif $iface]
  184. }
  185. #
  186. # send a graft/prune to dst/group up the RPF tree towards dst
  187. #
  188. ST instproc send-ctrl { which dst group } {
  189.         $self instvar mctrl_ ns_ node_
  190. if {$node_ != $dst} {
  191. set nbr [$node_ rpf-nbr $dst]
  192. $ns_ simplex-connect $mctrl_ 
  193. [[[$nbr getArbiter] getType [$self info class]] set mctrl_]
  194. if { $which == "prune" } {
  195. $mctrl_ set class_ 30
  196. } else {
  197. $mctrl_ set class_ 31
  198. }        
  199. $mctrl_ send $which [$node_ id] -1 $group
  200. }
  201. }
  202. ################ Helpers
  203. ST instproc dbg arg {
  204. $self instvar ns_ node_ id_
  205. puts [format "At %.4f : node $id_ $arg" [$ns_ now]]
  206. }