[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