[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[ns] HELP in writing code ( for ctrmcast:multi-RP )
Hi all
I am trying to mplement multiple-RP support to ctrmcast.
I have made few changes to CtrMcast.tcl & CtrMcastComp.tcl.
The basic idea is for the source to send data to multiple-RPs
and receiver's would join a specific RP.
I have attached the code. But I am facing problems in resolving
few issues like, "handle-cache-miss" , "Demux".
I would appreciate if someone could give a basic idea of how to
go about doing that. ( a pseudo code would help ).
I am facing few problems in dealing with replicator code.
I am not sure if I need to modify any of those.
Any help is greatly appreciated !!!!
- vijayan
#
# tcl/ctr-mcast/CtrMcastComp.tcl
#
# Copyright (C) 1997 by USC/ISI
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice and this paragraph are
# duplicated in all such forms and that any documentation, advertising
# materials, and other materials related to such distribution and use
# acknowledge that the software was developed by the University of
# Southern California, Information Sciences Institute. The name of the
# University may not be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
#
#
########## CtrMcastComp Class ##################################
########## init {}
########## compute-tree {src group Ttype}
########## compute-branch {src group member Ttype}
Class CtrMcastComp
CtrMcastComp instproc init sim {
$self instvar ns_
set ns_ $sim
$self init-groups
$ns_ maybeEnableTraceAll $self {}
}
CtrMcastComp instproc id {} {
return 0
}
CtrMcastComp instproc trace { f nop {op ""} } {
$self instvar ns_ dynT_
if {$op == "nam" && [info exists dynT_]} {
foreach tr $dynT_ {
$tr namattach $f
}
} else {
lappend dynT_ [$ns_ create-trace Generic $f $self $self $op]
}
}
##### Main computation functions #####
CtrMcastComp instproc reset-mroutes {} {
$self instvar ns_
foreach node [$ns_ all-nodes-list] {
foreach group [$self groups?] {
set class_info [$node info class]
if {$class_info != "LanNode"} {
$node clearReps * $group
}
# *,G match catches all sources.
# foreach src [$self sources? $group] {
# $node clearReps [$src id] $group
# }
}
}
}
CtrMcastComp instproc compute-mroutes {} {
puts "compute mroutes"
$self reset-mroutes
#addition
$self instvar ctrrpcomp
$ctrrpcomp compute-rpset
foreach group [$self groups?] {
foreach src [$self sources? $group] {
set ctrmcast [[$src getArbiter] getType "CtrMcast"]
foreach rp [$ctrmcast set rpset_] {
$self compute-tree $src $group $rp
}
set ctrmcast [[$src getArbiter] getType "CtrMcast"]
#$ctrmcast handle-cache-miss [$src id] $group -1
}
}
}
CtrMcastComp instproc compute-tree { src group rp} {
puts "compute tree [$src id] $group [$rp id]"
foreach mem [$self members? $group] {
$self compute-branch $src $group $mem $rp
}
}
CtrMcastComp instproc compute-branch { src group nodeh rp} {
puts "compute-branch [$src id] $group [$nodeh id] [$rp id]"
$self instvar ns_
### set (S,G) join target
set tt [$self treetype? $group]
if { $tt == "SPT" } {
set target $src
} elseif { $tt == "RPT" } {
#set target [$self get_rp $nodeh $group]
set target $rp
}
for {
set downstreamtmp ""
set tmp $nodeh
} { $downstreamtmp != $target } {
set downstreamtmp $tmp
set tmp [$tmp rpf-nbr $target]
} {
if {[SessionSim set MixMode_] && $downstreamtmp != "" && ![$ns_ detailed-link? [$tmp id] [$downstreamtmp id]]} {
# puts "joining into session area"
break
}
### set iif : RPF link interface label
if {$tmp == $target} {
# at src or RP
set iif -1
} else {
set rpfl [$ns_ link [$tmp rpf-nbr $target] $tmp]
if {[SessionSim set MixMode_] && $rpfl == ""} {
# in mix mode: default -1 unless find a
# detailed link on the rpf path
set iif -1
set ttmp $tmp
while {$ttmp != $target} {
set rpfl [$ns_ link [$ttmp rpf-nbr $target] $ttmp]
if {$rpfl != ""} {
set iif [$rpfl if-label?]
break
}
set ttmp [$ttmp rpf-nbr $target]
}
} else {
# in regular detailed mode
set iif [$rpfl if-label?]
}
}
### set oif : RPF link
set oiflist ""
if { $downstreamtmp != "" } {
set rpfnbr [$downstreamtmp rpf-nbr $target]
if { $rpfnbr == $tmp } {
set rpflink [$ns_ link $tmp $downstreamtmp]
if {$rpflink != ""} {
set oiflist [$tmp link2oif $rpflink]
}
}
}
if { [set r [$tmp getReps [$src id] $group]] != "" } {
if [$r is-active] {
# puts "reach merging point, $group [$src id] [$target id] [$tmp id] [$nodeh id], iif $iif, oif $oiflist"
if { $oiflist != "" } {
$r insert [lindex $oiflist 0]
}
break
} else {
# puts "hasn't reached merging point, $group [$src id] [$target id] [$tmp id] [$nodeh id], iif $iif, oif $oiflist"
# so continue to insert the oif
if { $oiflist != "" } {
$r insert [lindex $oiflist 0]
}
}
} else {
# hasn't reached merging point,
# puts "so keep creating (S,G) like a graft, $group [$src id] [$target id] [$tmp id] [$nodeh id], iif $iif, oif $oiflist"
$tmp add-mfc [$src id] $group $iif $oiflist
}
}
}
CtrMcastComp instproc prune-branch { src group nodeh rp} {
puts "prune-branch [$src id] $group [$nodeh id] [$rp id]"
$self instvar ns_
### set (S,G) prune target
set tt [$self treetype? $group]
if { $tt == "SPT" } {
set target $src
} elseif { $tt == "RPT" } {
#set target [$self get_rp $nodeh $group]
set target $rp
}
for {
set downstreamtmp ""
set tmp $nodeh
} { $downstreamtmp != $target } {
set downstreamtmp $tmp
set tmp [$tmp rpf-nbr $target]
} {
set iif -1
set oif ""
if { $downstreamtmp != "" } {
set rpfnbr [$downstreamtmp rpf-nbr $target]
if { $rpfnbr == $tmp } {
set oif [$tmp link2oif [$ns_ link $tmp $downstreamtmp]]
}
}
if { [set r [$tmp getReps [$src id] $group]] != "" } {
if { $oif != "" } {
$r disable $oif
}
if [$r is-active] {
break
}
} else {
break
}
}
}
# notify(): adapt to rtglib dynamics
CtrMcastComp instproc notify {} {
$self instvar ctrrpcomp
### need to add a delay before recomputation
$ctrrpcomp compute-rpset
$self compute-mroutes
}
#
# utility functions to track Source, Group, and Member State
#
CtrMcastComp instproc init-groups {} {
$self set Glist_ ""
}
CtrMcastComp instproc add-new-group group {
$self instvar Glist_
set group [expr $group]
if ![info exist Glist_] {
set Glist_ ""
}
if {[lsearch $Glist_ $group] < 0} {
lappend Glist_ $group
}
}
CtrMcastComp instproc add-new-member {group node} {
$self instvar Mlist_
set group [expr $group]
$self add-new-group $group
if ![info exist Mlist_($group)] {
set Mlist_($group) ""
}
if {[lsearch $Mlist_($group) $node] < 0} {
lappend Mlist_($group) $node
}
}
CtrMcastComp instproc new-source? {group node} {
$self instvar Slist_
set group [expr $group]
$self add-new-group $group
if ![info exist Slist_($group)] {
set Slist_($group) ""
}
if {[lsearch $Slist_($group) $node] < 0} {
lappend Slist_($group) $node
return 1
} else {
return 0
}
}
CtrMcastComp instproc groups? {} {
$self set Glist_
}
CtrMcastComp instproc members? group {
$self instvar Mlist_
set group [expr $group]
if ![info exists Mlist_($group)] {
set Mlist_($group) ""
}
set Mlist_($group)
}
CtrMcastComp instproc sources? group {
$self instvar Slist_
set group [expr $group]
if ![info exists Slist_($group)] {
set Slist_($group) ""
}
set Slist_($group)
}
CtrMcastComp instproc remove-member {group node} {
$self instvar Mlist_ Glist_
set group [expr $group]
set k [lsearch $Mlist_($group) $node]
if {$k < 0} {
puts "warning: removing non-member"
} else {
set Mlist_($group) [lreplace $Mlist_($group) $k $k]
}
if { $Mlist_($group) == "" } {
set k [lsearch $Glist_ $group]
if {$k < 0} {
puts "warning: removing non-existing group"
} else {
set Glist_ [lreplace $Glist_ $k $k]
}
}
}
CtrMcastComp instproc treetype? group {
$self instvar treetype_
set group [expr $group]
if [info exists treetype_($group)] {
return $treetype_($group)
} else {
return ""
}
}
CtrMcastComp instproc treetype {group tree} {
$self set treetype_([expr $group]) $tree
}
CtrMcastComp instproc switch-treetype group {
$self instvar treetype_ dynT_
set group [expr $group]
if [info exists dynT_] {
foreach tr $dynT_ {
$tr annotate "$group switch tree type"
}
}
set treetype_($group) "SPT"
$self add-new-group $group
$self compute-mroutes
}
CtrMcastComp instproc set_c_rp args {
$self instvar ns_
foreach n [$ns_ all-nodes-list] {
set arbiter [$n getArbiter]
#NS creates a virtual node per LAN. This node does
#not have any the multicast features set.
if {$arbiter != ""} {
set ctrmcast [$arbiter getType "CtrMcast"]
$ctrmcast instvar c_rp_
$ctrmcast unset_c_rp
}
}
foreach node $args {
set arbiter [$node getArbiter]
set ctrmcast [$arbiter getType "CtrMcast"]
$ctrmcast set_c_rp
}
}
CtrMcastComp instproc set_c_bsr args {
foreach node $args {
set tmp [split $node :]
set node [lindex $tmp 0]
set prior [lindex $tmp 1]
set arbiter [$node getArbiter]
set ctrmcast [$arbiter getType "CtrMcast"]
$ctrmcast set_c_bsr $prior
}
}
CtrMcastComp instproc get_rp { node group } {
set ctrmcast [[$node getArbiter] getType "CtrMcast"]
$ctrmcast get_rp $group
}
CtrMcastComp instproc get_bsr { node } {
set arbiter [$node getArbiter]
set ctrmcast [$arbiter getType "CtrMcast"]
$ctrmcast get_bsr
}
#
# tcl/ctr-mcast/CtrMcast.tcl
#
# Copyright (C) 1997 by USC/ISI
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice and this paragraph are
# duplicated in all such forms and that any documentation, advertising
# materials, and other materials related to such distribution and use
# acknowledge that the software was developed by the University of
# Southern California, Information Sciences Institute. The name of the
# University may not be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
#
#
########## CtrMcast Class: Individual Node join-group, leave-group, etc #####
Class CtrMcast -superclass McastProtocol
CtrMcast instproc init { sim node } {
$self next $sim $node
$self instvar ns_ node_
$self instvar agent_ defaultTree_ decapagent_
$self instvar c_rp_ c_bsr_ priority_
set agent_ [$ns_ set MrtHandle_]
set defaultTree_ "RPT"
set decapagent_ [new Agent/Decapsulator]
$ns_ attach-agent $node_ $decapagent_
### config PIM nodes
set a_rp_ 1
set c_rp_ 1
set c_bsr_ 1
set priority_ 0
}
CtrMcast instproc join-group { group rp } {
$self next $group
$self instvar node_ ns_ agent_
$self instvar defaultTree_
puts "join : $group [$node_ id] [$rp id]"
if { [$agent_ treetype? $group] == "" } {
$agent_ treetype $group $defaultTree_
$agent_ add-new-group $group
}
$agent_ add-new-member $group $node_
foreach src [$agent_ sources? $group] {
puts "join : [$src id] $group [$node_ id] [$rp id]"
$agent_ compute-branch $src $group $node_ $rp
}
}
CtrMcast instproc leave-group { group rp } {
$self next $group
$self instvar node_ ns_ agent_ defaultTree_
puts "prune : $group [$node_ id] [$rp id]"
$agent_ remove-member $group $node_
foreach src [$agent_ sources? $group] {
puts "prune: [$src id] $group [$node_ id] [$rp id]"
$agent_ prune-branch $src $group $node_ $rp
}
}
CtrMcast instproc handle-cache-miss { srcID group iface } {
puts "miss: $srcID $group $iface"
$self instvar ns_ agent_ node_
$self instvar defaultTree_ encapagent_
## addition
$self instvar rpset_
if ![info exists rpset_] {
[$agent_ set ctrrpcomp] compute-rpset
assert [info exists rpset_]
}
if { [$agent_ treetype? $group] == "" } {
$agent_ treetype $group $defaultTree_
#$agent_ add-new-member $group $node_
}
if { [$node_ id] == $srcID } {
foreach RP $rpset_ {
puts " if RPSET: $rpset_ RP: [$RP id] "
#set RP [$self get_rp $group]
if {[$agent_ treetype? $group] == "RPT" && $srcID != [$RP id]} {
if ![info exists encapagent_] {
set encapagent_ [new Agent/Encapsulator]
$ns_ attach-agent $node_ $encapagent_
set ctrmcast [[$RP getArbiter] getType "CtrMcast"]
$ns_ connect $encapagent_ [$ctrmcast set decapagent_]
### create (S,G,iif=-1) entry
$node_ add-mfc-reg $srcID $group -1 $encapagent_
} else {
set ctrmcast [[$RP getArbiter] getType "CtrMcast"]
$ns_ connect $encapagent_ [$ctrmcast set decapagent_]
}
}
if [$agent_ new-source? $group $node_] {
$agent_ compute-tree $node_ $group $RP
}
}
} elseif [SessionSim set MixMode_] {
set srcnode [$ns_ get-node-by-id $srcID]
foreach RP $rpset_ {
puts " else RPSET: $rpset_ RP: [$RP id] "
if [$agent_ new-source? $group $srcnode] {
$agent_ compute-tree $srcnode $group $RP
}
}
}
return 1 ;#call again
}
CtrMcast instproc drop { replicator src group iface } {
#packets got dropped only due to null oiflist
}
CtrMcast instproc handle-wrong-iif { srcID group iface } {
warn "$self: $proc for <S: $srcID, G: $group, if: $iface>?"
return 0 ;#call once
}
CtrMcast instproc notify { dummy } {
}
##### Two functions to help get RP for a group #####
##### get_rp {group} #####
##### hash {rp group} #####
CtrMcast instproc get_rp {group rp} {
$self instvar rpset_ agent_
if ![info exists rpset_] {
[$agent_ set ctrrpcomp] compute-rpset
assert [info exists rpset_]
}
set returnrp -1
set hashval -1
foreach rp $rpset_ {
if {[$self hash $rp $group] > $hashval} {
set hashval [$self hash $rp $group]
set returnrp $rp
}
}
set returnrp ;# return
}
CtrMcast instproc hash {rp group} {
$rp id
}
CtrMcast instproc set-rpset args {
eval $self set rpset_ "$args"
}
CtrMcast instproc get_bsr {} {
warn "$self: CtrMcast doesn't require a BSR"
}
CtrMcast instproc set_c_bsr { prior } {
$self instvar c_bsr_ priority_
set c_bsr_ 1
set priority_ $prior
}
CtrMcast instproc set_c_rp {} {
$self instvar c_rp_
set c_rp_ 1
}
CtrMcast instproc unset_c_rp {} {
$self instvar c_rp_
set c_rp_ 0
}
##################### MultiNode: add-mfc-reg ################
Node instproc add-mfc-reg { src group iif oiflist } {
$self instvar multiclassifier_ Regreplicator_
#XXX node addr is in upper 24 bits
if [info exists Regreplicator_($group)] {
foreach oif $oiflist {
$Regreplicator_($group) insert $oif
}
return 1
}
set r [new Classifier/Replicator/Demuxer]
$r set node_ $self
$r set srcID_ $src
set Regreplicator_($group) $r
foreach oif $oiflist {
$r insert $oif
}
# Install the replicator. We do this only once and leave
# it forever. Since prunes are data driven, we want to
# leave the replicator in place even when it's empty since
# the replicator::drop callback triggers the prune.
#
$multiclassifier_ add-rep $r $src $group $iif
}
Node instproc getRegreplicator group {
$self instvar Regreplicator_
if [info exists Regreplicator_($group)] {
return $Regreplicator_($group)
} else {
return -1
}
}
# Using Multicast in ns
set ns [new Simulator -multicast on]
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]
set n4 [$ns node]
set f [open out-cmcast.tr w]
$ns trace-all $f
set nf [open out-cmcast.nam w]
$ns namtrace-all $nf
$ns color 2 black
$ns color 1 blue
$ns color 0 yellow
$ns color 30 purple
$ns color 31 green
$ns duplex-link $n0 $n1 1.5Mb 10ms DropTail
$ns duplex-link $n1 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n1 $n3 1.5Mb 10ms DropTail
$ns duplex-link $n0 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n3 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n0 $n3 1.5Mb 10ms DropTail
$ns duplex-link $n0 $n4 1.5Mb 10ms DropTail
$ns duplex-link $n4 $n3 1.5Mb 10ms DropTail
set mproto CtrMcast
set mrthandle [$ns mrtproto $mproto {}]
$mrthandle set_c_rp $n2 $n3
set group0 [Node allocaddr]
set cbr1 [new Agent/CBR]
$ns attach-agent $n0 $cbr1
$cbr1 set dst_ $group0
$cbr1 set fid_ 0
#set cbr2 [new Agent/CBR]
#$ns attach-agent $n1 $cbr2
#$cbr2 set dst_ $group0
#$cbr2 set fid_ 1
set rcvr0 [new Agent/LossMonitor]
$ns attach-agent $n0 $rcvr0
set rcvr1 [new Agent/LossMonitor]
$ns attach-agent $n1 $rcvr1
set rcvr2 [new Agent/LossMonitor]
$ns attach-agent $n2 $rcvr2
set rcvr3 [new Agent/LossMonitor]
$ns attach-agent $n3 $rcvr3
$ns at 0.55 "$cbr1 start"
#$ns at 0.60 "$cbr2 start"
#$ns at 0.65 "$mrthandle switch-treetype $group0"
$ns at 0.2 "$n1 join-group $rcvr1 $group0 $n2"
#$ns at 0.3 "$n0 join-group $rcvr0 $group0 $n2"
$ns at 0.4 "$n3 join-group $rcvr3 $group0 $n2"
$ns at 0.5 "$n2 join-group $rcvr2 $group0 $n2"
$ns at 0.5 "$n4 join-group $rcvr2 $group0 $n2"
#$ns rtmodel-at 0.7 down $n2 $n0
#$ns rtmodel-at 0.75 up $n2 $n0
#$ns at 0.71 "change_core $n0"
#$ns at 0.8 "$n0 leave-group $rcvr0 $group0 $n2"
$ns at 1.0 "$n1 leave-group $rcvr1 $group0 $n2"
$ns at 0.85 "$n2 leave-group $rcvr2 $group0 $n2"
$ns at 0.9 "$n3 leave-group $rcvr3 $group0 $n2"
$ns at 0.9 "$n4 leave-group $rcvr3 $group0 $n2"
$ns at 1.2 "finish"
proc change_core { n } {
global ns
global mrthandle
global group0
$mrthandle set_c_rp $n
[$mrthandle set ctrrpcomp] compute-rpset
$mrthandle compute-mroutes
}
proc finish {} {
global ns
$ns flush-trace
global rcvr0 rcvr1 rcvr2 rcvr3
puts "[$rcvr0 set npkts_] [$rcvr0 set nlost_]"
puts "[$rcvr1 set npkts_] [$rcvr1 set nlost_]"
puts "[$rcvr2 set npkts_] [$rcvr2 set nlost_]"
puts "[$rcvr3 set npkts_] [$rcvr3 set nlost_]"
puts "running nam..."
exec nam out-cmcast &
exit 0
}
$ns run