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

通讯编程

开发平台:

Visual C++

  1. Class SessionSim -superclass Simulator
  2. SessionSim set MixMode_ 0
  3. SessionSim set rc_ 0
  4. ### Create a session helper that associates with the src agent ###
  5. SessionSim instproc create-session { srcNode srcAgent } {
  6.     $self instvar session_
  7.     set nid [$srcNode id]
  8.     set dst [$srcAgent set dst_addr_]
  9.     set session_($nid:$dst:$nid) [new SessionHelper]
  10.     $session_($nid:$dst:$nid) set-node $nid
  11.     if {[SessionSim set rc_]} {
  12. $session_($nid:$dst:$nid) set rc_ 1
  13.     }
  14.     # If exists nam-traceall, we'll insert an intermediate trace object
  15.     set trace [$self get-nam-traceall]
  16.     if {$trace != ""} {
  17. # This will write every packet sent and received to 
  18. # the nam trace file
  19. set p [$self create-trace SessEnque $trace $nid $dst "nam"]
  20. $srcAgent target $p
  21. $p target $session_($nid:$dst:$nid)
  22.     } else {
  23. $srcAgent target $session_($nid:$dst:$nid)
  24.     }
  25.     return $session_($nid:$dst:$nid)
  26. }
  27. SessionSim instproc update-loss-dependency { src dst owner agent group } {
  28.     $self instvar session_ routingTable_ loss_
  29.     set loss_rcv 1
  30.     set tmp $dst
  31.     while {$tmp != $owner} {
  32. set next [$routingTable_ lookup $tmp $owner]
  33. if {[info exists loss_($next:$tmp)] && $loss_($next:$tmp) != 0} {
  34.     if {$loss_rcv} {
  35. #puts "update-loss-rcv $loss_($next:$tmp) $next $tmp $agent"
  36. set dep_loss [$session_($src:$group:$owner) update-loss-rcv $loss_($next:$tmp) $agent]
  37.     } else {
  38. #puts "update-loss-rcv $loss_($next:$tmp) $next $tmp $dep_loss"
  39. set dep_loss [$session_($src:$group:$owner) update-loss-loss $loss_($next:$tmp) $dep_loss]
  40.     }
  41.     if {$dep_loss == 0} { 
  42. return 
  43.     }
  44.     set loss_rcv 0
  45. }
  46. set tmp $next
  47.     }
  48.     if [info exists dep_loss] {
  49. $session_($src:$group:$owner) update-loss-top $dep_loss
  50.     }
  51. }
  52. SessionSim instproc join-group { rcvAgent group } {
  53.     $self instvar session_ routingTable_ delay_ bw_
  54.     foreach index [array names session_] {
  55. set tri [split $index :]
  56. if {[lindex $tri 1] == $group} {
  57.     set src [lindex $tri 0]
  58.     set dst [[$rcvAgent set node_] id]
  59.     set delay 0
  60.     set accu_bw 0
  61.     set ttl 0
  62.     set tmp $dst
  63.     while {$tmp != $src} {
  64. set next [$routingTable_ lookup $tmp $src]
  65. set delay [expr $delay + $delay_($tmp:$next)]
  66. if {$accu_bw} {
  67.     set accu_bw [expr 1 / (1 / $accu_bw + 1 / $bw_($tmp:$next))]
  68. } else {
  69.     set accu_bw $bw_($tmp:$next)
  70. }
  71. incr ttl
  72. set tmp $next
  73.     }
  74.     
  75.     # Create nam queues for all receivers if traceall is turned on
  76.     # XXX 
  77.     # nam will deal with the issue whether all groups share a 
  78.     # single queue per receiver. The simulator simply writes 
  79.     # this information there
  80.     $self puts-nam-config "G -t [$self now] -i $group -a $dst"
  81.     
  82.     # And we should add a trace object before each receiver,
  83.     # because only this will capture the packet before it 
  84.     # reaches the receiver and after it left the sender
  85.     set f [$self get-nam-traceall]
  86.     if {$f != ""} { 
  87. set p [$self create-trace SessDeque $f $src $dst "nam"]
  88. $p target $rcvAgent
  89. $session_($index) add-dst $accu_bw $delay $ttl $dst $p
  90. $self update-loss-dependency $src $dst $src $p $group
  91.     } else {
  92. #puts "add-dst $accu_bw $delay $ttl $src $dst"
  93. $session_($index) add-dst $accu_bw $delay $ttl $dst $rcvAgent
  94. $self update-loss-dependency $src $dst $src $rcvAgent $group
  95.     }
  96. }
  97.     }
  98. }
  99. SessionSim instproc leave-group { rcvAgent group } {
  100.     $self instvar session_
  101.     foreach index [array names session_] {
  102. set tri [split $index :]
  103. if {[lindex $tri 1] == $group} {
  104.     #$session_($index) delete-dst [[$rcvAgent set node_] id] $rcvAgent
  105. set dst [[$rcvAgent set node_] id]
  106. # remove the receiver from packet distribution list
  107. $self puts-nam-traceall 
  108. "G -t [$self now] -i $group -x $dst"
  109. }
  110.     }
  111. }
  112. SessionSim instproc insert-loss { lossmodule from to } {
  113.     $self instvar loss_ bw_ Node_
  114.     if {[SessionSim set MixMode_] && [$self detailed-link? [$from id] [$to id]]} {
  115. $self lossmodel $lossmodule $from $to
  116.     } elseif [info exists bw_([$from id]:[$to id])] {
  117. set loss_([$from id]:[$to id]) $lossmodule
  118.     }
  119. }
  120. SessionSim instproc get-delay { src dst } {
  121.     $self instvar routingTable_ delay_
  122.     set delay 0
  123.     set tmp $src
  124.     while {$tmp != $dst} {
  125. set next [$routingTable_ lookup $tmp $dst]
  126. set delay [expr $delay + $delay_($tmp:$next)]
  127. set tmp $next
  128.     }
  129.     return $delay
  130. }
  131. SessionSim instproc get-bw { src dst } {
  132.     $self instvar routingTable_ bw_
  133.     set accu_bw 0
  134.     set tmp $src
  135.     while {$tmp != $dst} {
  136. set next [$routingTable_ lookup $tmp $dst]
  137. if {$accu_bw} {
  138.     set accu_bw [expr 1 / (1 / $accu_bw + 1 / $bw_($tmp:$next))]
  139. } else {
  140.     set accu_bw $bw_($tmp:$next)
  141. }
  142. set tmp $next
  143.     }
  144.     return $accu_bw
  145. }
  146. SessionSim instproc node args {
  147.     $self instvar sessionNode_
  148.     if {[llength $args] == 0} {
  149.         set node [new SessionNode]
  150.     } else {
  151. set node [new SessionNode $args]
  152.     }
  153.     set sessionNode_([$node id]) $node
  154.     $node set ns_ $self
  155.     return $node
  156. }
  157. SessionSim instproc simplex-link { n1 n2 bw delay type } {
  158.     $self instvar bw_ delay_ linkAttr_
  159.     set sid [$n1 id]
  160.     set did [$n2 id]
  161.     set bw_($sid:$did) [bw_parse $bw]
  162.     set delay_($sid:$did) [delay_parse $delay]
  163. set linkAttr_($sid:$did:ORIENT) ""
  164. set linkAttr_($sid:$did:COLOR) "black"
  165. }
  166. SessionSim instproc duplex-link { n1 n2 bw delay type } {
  167.     $self simplex-link $n1 $n2 $bw $delay $type
  168.     $self simplex-link $n2 $n1 $bw $delay $type
  169.     $self session-register-nam-linkconfig [$n1 id]:[$n2 id]
  170. }
  171. SessionSim instproc simplex-link-of-interfaces { n1 n2 bw delay type } {
  172.     $self simplex-link $n1 $n2 $bw $delay $type
  173. }
  174. SessionSim instproc duplex-link-of-interfaces { n1 n2 bw delay type } {
  175.     $self simplex-link $n1 $n2 $bw $delay $type
  176.     $self simplex-link $n2 $n1 $bw $delay $type
  177.     $self session-register-nam-linkconfig [$n1 id]:[$n2 id]
  178. }
  179. ### mix mode detailed link
  180. SessionSim instproc detailed-node { id address } {
  181.     $self instvar Node_
  182.     if { [Simulator info vars EnableMcast_] != "" } {
  183. warn "Flag variable Simulator::EnableMcast_ discontinued.nt
  184. Use multicast methods as:ntt
  185. % set ns [new Simulator -multicast on]ntt
  186. % $ns multicast"
  187. $self multicast
  188. Simulator unset EnableMcast_
  189.     }
  190.     if ![info exist Node_($id)] {
  191. set node [new [Simulator set node_factory_] $address]
  192. # Do not count this a "real" node, and keep the old node id. 
  193. Node set nn_ [expr [Node set nn_] - 1]
  194. $node set id_ $id
  195. set Node_($id) $node
  196. return $node
  197.     } else {
  198. return $Node_($id)
  199.     }
  200. }
  201. SessionSim instproc detailed-duplex-link { from to } {
  202.     $self instvar bw_ delay_
  203.     SessionSim set MixMode_ 1
  204.     set fromNode [$self detailed-node [$from id] [$from set address_]]
  205.     set toNode [$self detailed-node [$to id] [$from set address_]]
  206.     $self simulator-duplex-link $fromNode $toNode $bw_([$from id]:[$to id]) $delay_([$from id]:[$to id]) DropTail
  207. }
  208. SessionSim instproc simulator-duplex-link { n1 n2 bw delay type args } {
  209. $self instvar link_
  210. set i1 [$n1 id]
  211. set i2 [$n2 id]
  212. if [info exists link_($i1:$i2)] {
  213. $self remove-nam-linkconfig $i1 $i2
  214. }
  215. eval $self simulator-simplex-link $n1 $n2 $bw $delay $type $args
  216. eval $self simulator-simplex-link $n2 $n1 $bw $delay $type $args
  217. }
  218. SessionSim instproc simulator-simplex-link { n1 n2 bw delay qtype args } {
  219. $self instvar link_ queueMap_ nullAgent_
  220. set sid [$n1 id]
  221. set did [$n2 id]
  222. if [info exists queueMap_($qtype)] {
  223. set qtype $queueMap_($qtype)
  224. }
  225. # construct the queue
  226. set qtypeOrig $qtype
  227. switch -exact $qtype {
  228. ErrorModule {
  229. if { [llength $args] > 0 } {
  230. set q [eval new $qtype $args]
  231. } else {
  232. set q [new $qtype Fid]
  233. }
  234. }
  235. intserv {
  236. set qtype [lindex $args 0]
  237. set q [new Queue/$qtype]
  238. }
  239. default {
  240. set q [new Queue/$qtype]
  241. }
  242. }
  243. # Now create the link
  244. switch -exact $qtypeOrig {
  245. RTM {
  246.                         set c [lindex $args 1]
  247.                         set link_($sid:$did) [new CBQLink       
  248.                                         $n1 $n2 $bw $delay $q $c]
  249.                 }
  250.                 CBQ -
  251.                 CBQ/WRR {
  252.                         # assume we have a string of form "linktype linkarg"
  253.                         if {[llength $args] == 0} {
  254.                                 # default classifier for cbq is just Fid type
  255.                                 set c [new Classifier/Hash/Fid 33]
  256.                         } else {
  257.                                 set c [lindex $args 1]
  258.                         }
  259.                         set link_($sid:$did) [new CBQLink       
  260.                                         $n1 $n2 $bw $delay $q $c]
  261.                 }
  262.                 intserv {
  263.                         #XX need to clean this up
  264.                         set link_($sid:$did) [new IntServLink   
  265.                                         $n1 $n2 $bw $delay $q
  266. [concat $qtypeOrig $args]]
  267.                 }
  268.                 default {
  269.                         set link_($sid:$did) [new SimpleLink    
  270.                                         $n1 $n2 $bw $delay $q]
  271.                 }
  272.         }
  273. $n1 add-neighbor $n2
  274. #XXX yuck
  275. if {[string first "RED" $qtype] != -1} {
  276. $q link [$link_($sid:$did) set link_]
  277. }
  278. set trace [$self get-ns-traceall]
  279. if {$trace != ""} {
  280. $self trace-queue $n1 $n2 $trace
  281. }
  282. set trace [$self get-nam-traceall]
  283. if {$trace != ""} {
  284. $self namtrace-queue $n1 $n2 $trace
  285. }
  286. # Register this simplex link in nam link list. Treat it as 
  287. # a duplex link in nam
  288. $self register-nam-linkconfig $link_($sid:$did)
  289. }
  290. # Assume ops to be performed is 'orient' only
  291. # XXX Poor hack. What should we do without a link object??
  292. SessionSim instproc duplex-link-op { n1 n2 op args } {
  293. $self instvar linkAttr_ bw_
  294. set sid [$n1 id]
  295. set did [$n2 id]
  296. if ![info exists bw_($sid:$did)] {
  297. error "Non-existent link [$n1 id]:[$n2 id]"
  298. }
  299. switch $op {
  300. "orient" {
  301. set linkAttr_($sid:$did:ORIENT) $args
  302. set linkAttr_($did:$sid:ORIENT) $args
  303. }
  304. "color" {
  305. set ns [Simulator instance]
  306. $ns puts-nam-traceall 
  307. [eval list "l -t [$self now] -s $sid -d $did 
  308. -S COLOR -c $args -o $linkAttr_($sid:$did:COLOR)"]
  309. $ns puts-nam-traceall 
  310. [eval list "l -t [$self now] -s $did -d $sid 
  311. -S COLOR -c $args -o $linkAttr_($sid:$did:COLOR)"]
  312. eval set attr_($sid:$did:COLOR) $args
  313. eval set attr_($did:$sid:COLOR) $args
  314. }
  315. default {
  316. eval puts "Duplex link option $args not implemented 
  317. in SessionSim"
  318. }
  319. }
  320. # nam support for session sim, Contributed by Haobo Yu
  321. # Because here we don't have a link object, we need to have a new 
  322. # link register method
  323. SessionSim instproc session-register-nam-linkconfig link {
  324. $self instvar sessionLinkConfigList_ bw_ linkAttr_
  325. if [info exists sessionLinkConfigList_] {
  326. # Check whether the reverse simplex link is registered,
  327. # if so, don't register this link again.
  328. # We should have a separate object for duplex link.
  329. set tmp [split $link :]
  330. set i1 [lindex $tmp 0]
  331. set i2 [lindex $tmp 1]
  332. if [info exists bw_($i2:$i1)] {
  333. set pos [lsearch $sessionLinkConfigList_ $i2:$i1]
  334. if {$pos >= 0} {
  335. set a1 $linkAttr_($i2:$i1:ORIENT)
  336. set a2 $linkAttr_($link:ORIENT)
  337. if {$a1 == "" && $a2 != ""} {
  338. # If this duplex link has not been 
  339. # assigned an orientation, do it.
  340. set sessionLinkConfigList_ [lreplace $sessionLinkConfigList_ $pos $pos]
  341. } else {
  342. return
  343. }
  344. }
  345. }
  346. # Remove $link from list if it's already there
  347. set pos [lsearch $sessionLinkConfigList_ $link]
  348. if {$pos >= 0} {
  349. set sessionLinkConfigList_ 
  350. [lreplace $sessionLinkConfigList_ $pos $pos]
  351. }
  352. }
  353. lappend sessionLinkConfigList_ $link
  354. }
  355. # write link configurations
  356. SessionSim instproc dump-namlinks {} {
  357.     $self instvar bw_ delay_ sessionLinkConfigList_ linkAttr_
  358.     set ns [Simulator instance]
  359.     foreach lnk $sessionLinkConfigList_ {
  360. set tmp [split $lnk :]
  361. set i1 [lindex $tmp 0]
  362. set i2 [lindex $tmp 1]
  363. $ns puts-nam-traceall 
  364. "l -t * -s $i1 -d $i2 -S UP -r $bw_($lnk) -D 
  365. $delay_($lnk) -o $linkAttr_($lnk:ORIENT)"
  366.     }
  367. }
  368. SessionSim instproc dump-namnodes {} {
  369.         $self instvar sessionNode_
  370.         if ![$self is-started] {
  371.                 return
  372.         }
  373.         foreach nn [array names sessionNode_] {
  374.                 if ![$sessionNode_($nn) is-lan?] {
  375.                         $sessionNode_($nn) dump-namconfig
  376.                 }
  377.         }
  378. }     
  379. ### Routing support
  380. SessionSim instproc compute-routes {} {
  381.     #
  382.     # call hierarchical routing, if applicable
  383.     #
  384.     if [Simulator hier-addr?] {
  385. $self compute-hier-routes 
  386.     } else {
  387. $self compute-flat-routes
  388.     }
  389. }
  390. SessionSim instproc compute-flat-routes {} {
  391. $self instvar bw_
  392. #
  393. # Compute all the routes using the route-logic helper object.
  394. #
  395.         set r [$self get-routelogic]
  396. foreach ln [array names bw_] {
  397. set L [split $ln :]
  398. set srcID [lindex $L 0]
  399. set dstID [lindex $L 1]
  400.         if {$bw_($ln) != 0} {
  401. $r insert $srcID $dstID
  402. } else {
  403. $r reset $srcID $dstID
  404. }
  405. }
  406. $r compute
  407. }
  408. SessionSim instproc compute-hier-routes {} {
  409.         $self instvar bw_
  410.         set r [$self get-routelogic]
  411.         #
  412.         # send hierarchical data :
  413.         # array of cluster size, #clusters, #domains
  414.         # assuming 3 levels of hierarchy --> this should be extended to
  415. # support
  416.         # n-levels of hierarchy
  417.         #
  418.         # puts "Computing Hierarchical routesn"
  419.         set level [AddrParams hlevel]
  420.         $r hlevel-is $level
  421.         $self hier-topo $r
  422.         foreach ln [array names bw_] {
  423.                 set L [split $ln :]
  424.                 set srcID [[$self get-node-by-id [lindex $L 0]] node-addr]
  425.                 set dstID [[$self get-node-by-id [lindex $L 1]] node-addr]
  426.                 if { $bw_($ln) != 0 } {
  427. #                        $r hier-insert $srcID $dstID $bw_($ln)
  428.                         $r hier-insert $srcID $dstID
  429.                 } else {
  430.                         $r hier-reset $srcID $dstID
  431.                 }
  432.         }       
  433.         $r hier-compute
  434. }
  435. SessionSim instproc compute-algo-routes {} {
  436.     set r [$self get-routelogic]
  437.     
  438.     # puts "Computing algorithmic routes"
  439.     $r BFS
  440.     $r compute
  441. }
  442. ### Route length analysis helper function
  443. SessionSim instproc dump-routelogic-distance {} {
  444. $self instvar routingTable_ sessionNode_ bw_
  445. if ![info exists routingTable_] {
  446.     puts "error: routing table is not computed yet!"
  447.     return 0
  448. }
  449. # puts "Dumping Routing Table: Distance Information"
  450. set n [Node set nn_]
  451. set i 0
  452. puts -nonewline "t"
  453. while { $i < $n } {
  454.     if ![info exists sessionNode_($i)] {
  455. incr i
  456. continue
  457.     }
  458.     puts -nonewline "$it"
  459.     incr i
  460. }
  461. set i 0
  462. while { $i < $n } {
  463. if ![info exists sessionNode_($i)] {
  464.     incr i
  465.     continue
  466. }
  467. puts -nonewline "n$it"
  468. set n1 $sessionNode_($i)
  469. set j 0
  470. while { $j < $n } {
  471. if { $i != $j } {
  472. set nh [$routingTable_ lookup $i $j]
  473. if { $nh >= 0 } {
  474.     set distance 0
  475.     set tmpfrom $i
  476.     set tmpto $j
  477.     while {$tmpfrom != $tmpto} {
  478. set tmpnext [$routingTable_ lookup $tmpfrom $tmpto]
  479. set distance [expr $distance + 1]
  480. set tmpfrom $tmpnext
  481.     }
  482.     puts -nonewline "$distancet"
  483. } else {
  484.     puts -nonewline "0t"
  485. }
  486. } else {
  487.     puts -nonewline "0t"
  488. }
  489. incr j
  490. }
  491. incr i
  492. }
  493. puts ""
  494. }
  495. ### SessionSim instproc run
  496. SessionSim instproc run args {
  497.         $self rtmodel-configure                 ;# in case there are any
  498.         [$self get-routelogic] configure
  499. $self instvar scheduler_ sessionNode_ started_
  500. set started_ 1
  501. #
  502. # Reset every node, which resets every agent
  503. #
  504. foreach nn [array names sessionNode_] {
  505. $sessionNode_($nn) reset
  506. }
  507. if {[SessionSim set MixMode_]} {
  508.     foreach nn [array names Node_] {
  509. $Node_($nn) reset
  510.     }
  511. }
  512. # We don't have queues in SessionSim
  513. $self dump-namcolors
  514. $self dump-namnodes
  515. $self dump-namlinks
  516. $self dump-namagents
  517.         return [$scheduler_ run]
  518. }
  519. # Debugging mcast tree function; Contributed by Haobo Yu
  520. # Get multicast tree in session simulator: By assembling individual 
  521. # (receiver, sender) paths into a SPT.
  522. # src is a Node.
  523. SessionSim instproc get-mcast-tree { src grp } {
  524. $self instvar treeLinks_ session_
  525. if [info exists treeLinks_] {
  526. unset treeLinks_
  527. }
  528. set sid [$src id] 
  529. # get member list
  530. foreach idx [array names session_] {
  531. set tri [split $idx :]
  532. if {[lindex $tri 0] == $sid && [lindex $tri 1] == $grp} {
  533. set mbrs [$session_($idx) list-mbr]
  534. break
  535. }
  536. }
  537. foreach mbr $mbrs {
  538. # Find path from $mbr to $src
  539. while {![string match "Agent*" [$mbr info class]]} {
  540. # In case agent is at the end of the chain... 
  541. set mbr [$mbr target]
  542. }
  543. set mid [[$mbr set node_] id]
  544. if {$sid == $mid} {
  545. continue
  546. }
  547. # get paths for each individual member
  548. $self merge-path $sid $mid
  549. }
  550. # generating tree link list
  551. foreach lnk [array names treeLinks_] {
  552. lappend res $lnk $treeLinks_($lnk)
  553. }
  554. return $res
  555. }
  556. # Merge the path from mbr to src
  557. # src is node id.
  558. SessionSim instproc merge-path { src mbr } {
  559. $self instvar routingTable_ treeLinks_ bw_
  560. # get paths from mbr to src and merge into treeLinks_
  561. set tmp $mbr
  562. while {$tmp != $src} {
  563. set nxt [$routingTable_ lookup $tmp $src]
  564. # XXX 
  565. # Assume routingTable lookup is always successful, so 
  566. #   don't validate existence of bw_($tid:$sid)
  567. # Always arrange tree links in (parent, child).
  568. if ![info exists treeLinks_($nxt:$tmp)] {
  569. set treeLinks_($nxt:$tmp) $bw_($nxt:$tmp)
  570. }
  571. if [info exists treeLinks_($tmp:$nxt)] {
  572. error "Reverse links in a SPT!"
  573. }
  574. set tmp $nxt
  575. }
  576. }
  577. SessionSim instproc get-node-by-id id {
  578. $self instvar sessionNode_ Node_
  579.     if [info exists Node_($id)] {
  580. set Node_($id)
  581.     } else {
  582. set sessionNode_($id)
  583.     }
  584. }
  585. SessionSim instproc get-node-id-by-addr address {
  586.         $self instvar sessionNode_
  587.         set n [Node set nn_]
  588.         for {set q 0} {$q < $n} {incr q} {
  589.                 set nq $sessionNode_($q)
  590.                 if {[string compare [$nq node-addr] $address] == 0} {
  591.                         return $q
  592.                 }
  593.         }
  594.         error "get-node-id-by-addr:Cannot find node with given address"
  595. }
  596. ############## SessionNode ##############
  597. Class SessionNode -superclass Node
  598. SessionNode instproc init args {
  599.     $self instvar id_ np_ address_
  600.     set id_ [Node getid]
  601.     set np_ 0
  602.     if {[llength $args] > 0} {
  603. set address_ $args
  604.     } else {
  605.         set address_ $id_
  606.     }
  607. }
  608. SessionNode instproc id {} {
  609.     $self instvar id_
  610.     return $id_
  611. }
  612. SessionNode instproc reset {} {
  613. }
  614. SessionNode instproc alloc-port {} {
  615.     $self instvar np_
  616.     set p $np_
  617.     incr np_
  618.     return $p
  619. }
  620. SessionNode instproc attach agent {
  621. $self instvar id_ address_
  622. $agent set node_ $self
  623. set port [$self alloc-port]
  624. $agent set agent_addr_ [AddrParams addr2id $address_]
  625. $agent set agent_port_ $port
  626. }
  627. SessionNode instproc join-group { rcvAgent group } {
  628.     set group [expr $group]
  629.     if {[SessionSim set MixMode_]} {
  630. [Simulator instance] join-intermediate-session $rcvAgent $group
  631.     } else {
  632. [Simulator instance] join-group $rcvAgent $group
  633.     }
  634. }
  635. SessionNode instproc leave-group { rcvAgent group } {
  636.     set group [expr $group]
  637.     [Simulator instance] leave-group $rcvAgent $group
  638. }
  639. Agent/LossMonitor instproc show-delay { seqno delay } {
  640.     $self instvar node_
  641.     puts "[$node_ id] $seqno $delay"
  642. }
  643. ####################### Mix Mode Stuff ##################################
  644. ### Create a session helper that does not associates with a src agent ###
  645. ### I.e., Create an intermediate session for mix mode operation       ###
  646. ### Return the obj to perform detailed join                           ###
  647. SessionSim instproc RPF-link { src from to } {
  648. $self instvar routingTable_ link_
  649. #
  650. # If this link is on the RPF tree, return the link object.
  651. #
  652.         if [info exists routingTable_] {
  653.     set tmp $to
  654.     while {$tmp != $src} {
  655. set reverse [$routingTable_ lookup $tmp $src]
  656. if [info exists link_($reverse:$tmp)] {
  657.     return $link_($reverse:$tmp)
  658. }
  659. set tmp $reverse
  660.     }
  661. }
  662. return ""
  663. }
  664. SessionSim instproc detailed-link? { from to } {
  665.     $self instvar link_
  666.     
  667.     return [info exist link_($from:$to)]
  668. }
  669. SessionSim instproc create-intermediate-session { src group nid } {
  670.     $self instvar session_
  671.     set session_($src:$group:$nid) [new SessionHelper]
  672.     $session_($src:$group:$nid) set-node $nid
  673.     if {[SessionSim set rc_]} {
  674. $session_($src:$group:$nid) set rc_ 1
  675.     }
  676.     # If exists nam-traceall, we'll insert an intermediate trace object
  677.     set trace [$self get-nam-traceall]
  678.     if {$trace != ""} {
  679. # This will write every packet sent and received to 
  680. # the nam trace file
  681. set p [$self create-trace SessEnque $trace $nid $dst "nam"]
  682. $p target $session_($src:$group:$nid)
  683. return $p
  684.     } else {
  685. return $session_($src:$group:$nid)
  686.     }
  687. }
  688. SessionSim instproc join-intermediate-session { rcvAgent group } {
  689.     $self instvar session_ routingTable_ delay_ bw_ link_ Node_ dlist_
  690.     foreach index [array names session_] {
  691. set tri [split $index :]
  692. set src [lindex $tri 0]
  693. set grp [lindex $tri 1]
  694. set owner [lindex $tri 2]
  695. if {$grp == $group && $src == $owner} {
  696.     set session_area 1
  697.     set dst [[$rcvAgent set node_] id]
  698.     set delay 0
  699.     set accu_bw 0
  700.     set ttl 0
  701.     set tmp $dst
  702.     while {$tmp != $src} {
  703. set next [$routingTable_ lookup $tmp $src]
  704. # Conditions to perform session/detailed join
  705. if {$session_area} {
  706.     if [info exist link_($tmp:$next)] {
  707. # walking into detailed area from session area
  708. set session_area 0
  709. if ![info exist session_($src:$grp:$tmp)] {
  710.     set inter_session [$self create-intermediate-session $src $grp $tmp]
  711. } else {
  712.     set inter_session $session_($src:$grp:$tmp)
  713. }
  714. if {![info exist dlist_($src:$grp:$tmp)] || [lsearch $dlist_($src:$grp:$tmp) $rcvAgent] < 0 } {
  715.     $inter_session add-dst $accu_bw $delay $ttl $dst $rcvAgent
  716.     $self update-loss-dependency $src $dst $tmp $rcvAgent $group
  717.     lappend dlist_($src:$grp:$tmp) $rcvAgent
  718. }
  719. $Node_($tmp) join-group $inter_session $group
  720. # puts "s->d: $dst, $rcvAgent, [$rcvAgent info class], join session $inter_session which detailed-joined the group $group, $delay, $accu_bw, $ttl"
  721.     } else {
  722. # stay in session area, keep track of accumulative
  723. # delay, bw, ttl
  724. set delay [expr $delay + $delay_($tmp:$next)]
  725. if {$accu_bw} {
  726.     set accu_bw [expr 1 / (1 / $accu_bw + 1 / $bw_($tmp:$next))]
  727. } else {
  728.     set accu_bw $bw_($tmp:$next)
  729. }
  730. incr ttl
  731. # puts "s->s: $dst, $rcvAgent, [$rcvAgent info class], $group, $delay, $accu_bw, $ttl"
  732.     }
  733. } else {
  734.     if [info exist link_($tmp:$next)] {
  735. # stay in detailed area, do nothing
  736. # puts "d->d"
  737.     } else {
  738. # walking into session area from detailed area
  739. set session_area 1
  740. set accu_bw $bw_($tmp:$next)
  741. set delay $delay_($tmp:$next)
  742. set ttl 1
  743. set dst $tmp
  744. set rcvAgent [$Node_($tmp) entry]
  745. # puts "d->s: $dst, $rcvAgent, [$rcvAgent info class], $group, $delay, $accu_bw, $ttl"
  746.     }
  747. }
  748. set tmp $next
  749.     }
  750.     
  751.     # Create nam queues for all receivers if traceall is turned on
  752.     # XXX 
  753.     # nam will deal with the issue whether all groups share a 
  754.     # single queue per receiver. The simulator simply writes 
  755.     # this information there
  756.     $self puts-nam-config "G -t [$self now] -i $group -a $dst"
  757.     
  758.     # And we should add a trace object before each receiver,
  759.     # because only this will capture the packet before it 
  760.     # reaches the receiver and after it left the sender
  761.     set f [$self get-nam-traceall]
  762.     if {$session_area} {
  763. if {$f != ""} { 
  764.     set p [$self create-trace SessDeque $f $src $dst "nam"]
  765.     $p target $rcvAgent
  766.     if {![info exist dlist_($index)] || [lsearch $dlist_($index) $rcvAgent] < 0 } {
  767. $session_($index) add-dst $accu_bw $delay $ttl $dst $p
  768. $self update-loss-dependency $src $dst $src $p $group
  769. lappend dlist_($index) $rcvAgent
  770.     }
  771. } else {
  772.     # puts "session area: add-dst $accu_bw $delay $ttl $src $dst $rcvAgent [$rcvAgent info class]"
  773.     if {![info exist dlist_($index)] || [lsearch $dlist_($index) $rcvAgent] < 0 } {
  774. $session_($index) add-dst $accu_bw $delay $ttl $dst $rcvAgent
  775. $self update-loss-dependency $src $dst $src $rcvAgent $group
  776. lappend dlist_($index) $rcvAgent
  777.     }
  778. }
  779.     } else {
  780. if {$f != ""} { 
  781.     set p [$self create-trace SessDeque $f $src $src "nam"]
  782.     $p target [$Node_($tmp) entry]
  783.     if {![info exist dlist_($index)] || [lsearch $dlist_($index) [$Node_($tmp) entry]] < 0 } {
  784. $session_($index) add-dst 0 0 0 $src $p
  785. $self update-loss-dependency $src $src $src $p $group
  786. lappend dlist_($index) [$Node_($tmp) entry]
  787.     }
  788. } else {
  789.     # puts "detailed area: add-dst $accu_bw $delay $ttl $src $dst[$Node_($tmp) entry] [[$Node_($tmp) entry] info class]"
  790.     if {![info exist dlist_($index)] || [lsearch $dlist_($index) [$Node_($tmp) entry]] < 0 } {
  791. $session_($index) add-dst 0 0 0 $src [$Node_($tmp) entry]
  792. $self update-loss-dependency $src $src $src [$Node_($tmp) entry] $group
  793. lappend dlist_($index) [$Node_($tmp) entry]
  794.     }
  795. }
  796.     }
  797. }
  798.     }
  799. }