File: ns-mcast.tcl

package info (click to toggle)
ns2 2.35%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 78,796 kB
  • sloc: cpp: 172,923; tcl: 107,130; perl: 6,391; sh: 6,143; ansic: 5,846; makefile: 816; awk: 525; csh: 355
file content (537 lines) | stat: -rw-r--r-- 13,613 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
#
# tcl/mcast/ns-mcast.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.
# 
# Ported by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang
# 
#
###############

# The MultiSim stuff below is only for backward compatibility.
Class MultiSim -superclass Simulator

MultiSim instproc init args {
        eval $self next $args
        $self multicast on
}

Simulator instproc multicast args {
        $self set multiSim_ 1
	Node enable-module Mcast
}

Simulator instproc multicast? {} {
        $self instvar multiSim_
        if { ![info exists multiSim_] } {
                set multiSim_ 0
        }
        set multiSim_
}

Simulator instproc run-mcast {} {
        $self instvar Node_
        foreach n [array names Node_] {
                set node $Node_($n)
		$node start-mcast
        }
        $self next
}

Simulator instproc clear-mcast {} {
        $self instvar Node_
        foreach n [array names Node_] {
                $Node_($n) stop-mcast
        }
}

Simulator instproc mrtproto { mproto { nodelist "" } } {
	$self instvar Node_ MrtHandle_

	set MrtHandle_ ""
	if { $mproto == "CtrMcast" } {
		set MrtHandle_ [new CtrMcastComp $self]
		$MrtHandle_ set ctrrpcomp [new CtrRPComp $self]
	}

	# XXX This is a ugly hack! Why not delete existing classifier???
	if { $mproto == "BST" } {
		foreach n [array names Node_] {
			if ![$Node_($n) is-lan?] {
			    $Node_($n) instvar multiclassifier_ switch_
# 			    delete $multiclassifier_
			    set multiclassifier_ [new Classifier/Multicast/Replicator/BST]
			    $multiclassifier_ set node_ $Node_($n)
			    $switch_ install 1 $multiclassifier_
			}
		}
	}

	if { $nodelist == "" } {
		foreach n [array names Node_] {
			$self mrtproto-iifs $mproto $Node_($n) ""
		}
	} else {
		foreach node $nodelist {
			$self mrtproto-iifs $mproto $node ""
		}
	}
	$self at 0.0 "$self run-mcast"

	return $MrtHandle_
}
#finer control than mrtproto: specify which iifs protocols owns
Simulator instproc mrtproto-iifs {mproto node iiflist } {
	set mh [new $mproto $self $node]
	set arbiter [$node getArbiter]
	if { $arbiter != "" } {
		$arbiter addproto $mh $iiflist
	}
}

Node proc allocaddr {} {
	# return a unique mcast address
	set addr [Simulator set McastAddr_]
	Simulator set McastAddr_ [expr $addr + 1]
	return $addr
}

Node proc expandaddr {} {
        # calling set-address-format with expanded option (sets nodeid with 
	# 21 bits 
        # & sets aside 1 bit for mcast) and sets portid with 8 bits
	# if hierarchical address format is set, just expands the McastAddr_
	[Simulator instance] set-address-format expanded
	puts "Backward compatibility: Use \"set-address-format expanded\" instead of \"Node expandaddr\";" 
}

Node instproc start-mcast {} {
        $self instvar mrtObject_
        $mrtObject_ start
}

Node instproc getArbiter {} {
        $self instvar mrtObject_
	if [info exists mrtObject_] {
	        return $mrtObject_
	}
	return ""
}

Node instproc notify-mcast changes {
	$self instvar mrtObject_
	if [info exists mrtObject_] {
		$mrtObject_ notify $changes
	}
}

Node instproc stop-mcast {} {
        $self instvar mrtObject_
        $self clear-caches
        $mrtObject_ stop
}

Node instproc clear-caches {} {
        $self instvar Agents_  multiclassifier_ replicator_

        $multiclassifier_ clearAll
	$multiclassifier_ set nrep_ 0

	foreach var {Agents_ replicator_} {
		$self instvar $var
		if { [info exists $var] } {
			delete $var
			unset $var
		}
	}
        # XXX watch out for memory leaks
}

Node instproc dump-routes args {
	$self instvar mrtObject_
	if { [info exists mrtObject_] } {
		eval $mrtObject_ dump-routes $args
	}
}

Node instproc check-local { group } {
        $self instvar Agents_
        if [info exists Agents_($group)] {
                return [llength $Agents_($group)]
        }
        return 0
}

Node instproc new-group { src group iface code } {
	$self instvar mrtObject_
	$mrtObject_ upcall $code $src $group $iface
}

Node instproc join-group { agent group { src "" } } {
        $self instvar replicator_ Agents_ mrtObject_
        set group [expr $group] ;# use expr to convert to decimal

        $mrtObject_ join-group $group $src

        lappend Agents_($group) $agent
	if { $src == "" } {
		set reps [$self getReps "*" $group]
	} else {
		set reps [$self getReps $src $group]
	}
        foreach rep $reps {
                # make sure agent is enabled in each replicator for this group
                $rep insert $agent
        }
}

Node instproc leave-group { agent group { src "" } } {
        $self instvar replicator_ Agents_ mrtObject_
        set group [expr $group] ;# use expr to get rid of possible leading 0x
	if { $src == "" } {
		set reps [$self getReps "*" $group]
	} else {
		set reps [$self getReps $src $group]
	}
        foreach rep $reps  {
                $rep disable $agent
        }
        if [info exists Agents_($group)] {
                set k [lsearch -exact $Agents_($group) $agent]
		set Agents_($group) [lreplace $Agents_($group) $k $k]

                $mrtObject_ leave-group $group $src
        } else {
                warn "cannot leave a group without joining it"
        }
}

Node instproc add-mfc { src group iif oiflist } {
	$self instvar multiclassifier_ \
			replicator_ Agents_ 

	if [info exists replicator_($src:$group)] {
		set r $replicator_($src:$group)
	} else {
		set r [new Classifier/Replicator/Demuxer]
		$r set srcID_ $src
		$r set grp_ $group
		set replicator_($src:$group) $r
		$r set node_ $self
		#
		# install each agent that has previously joined this group
		#
		if [info exists Agents_($group)] {
			foreach a $Agents_($group) {
				$r insert $a
			}
		}
		# we also need to check Agents($srcID:$group)
		if [info exists Agents_($src:$group)] {
			foreach a $Agents_($src:$group) {
				$r insert $a
			}
		}
		#
		# Install the replicator.  
		#
		$multiclassifier_ add-rep $r $src $group $iif
	}

	foreach oif [lsort $oiflist] {
		$r insert $oif
	}
}

Node instproc del-mfc { srcID group oiflist } {
        $self instvar replicator_ multiclassifier_
        if [info exists replicator_($srcID:$group)] {
                set r $replicator_($srcID:$group)  
                foreach oif $oiflist {
                        $r disable $oif
                }
                return 1
        } 
        return 0
}

####################
Class Classifier/Multicast/Replicator -superclass Classifier/Multicast

#
# This method called when a new multicast group/source pair
# is seen by the underlying classifier/mcast object.
# We install a hash for the pair mapping it to a slot
# number in the classifier table and point the slot
# at a replicator object that sends each packet along
# the RPF tree.
#
Classifier/Multicast instproc new-group { src group iface code} {
	$self instvar node_
	$node_ new-group $src $group $iface $code
}

Classifier/Multicast instproc no-slot slot {
	# NOTHING
}

Classifier/Multicast/Replicator instproc init args {
	$self next
	$self instvar nrep_
	set nrep_ 0
}

Classifier/Multicast/Replicator instproc add-rep { rep src group iif } {
	$self instvar nrep_
	$self set-hash $src $group $nrep_ $iif
	$self install $nrep_ $rep
	incr nrep_
}

###################### Class Classifier/Replicator/Demuxer ##############
Class Classifier/Replicator/Demuxer -superclass Classifier/Replicator
Classifier/Replicator/Demuxer set ignore_ 0
Classifier/Replicator/Demuxer instproc init args {
	eval $self next $args
	$self instvar nslot_ nactive_
	set nactive_ 0
}

Classifier/Replicator/Demuxer instproc is-active {} {
	$self instvar nactive_
	expr $nactive_ > 0
}

Classifier/Replicator/Demuxer instproc insert target {
	$self instvar nactive_ active_ 

	if ![info exists active_($target)] {
		set active_($target) -1
	}
	if {$active_($target) < 0} {
		$self enable $target
	}
}

Classifier/Replicator/Demuxer instproc dump-oifs {} {
	set oifs ""
	if [$self is-active] {
		$self instvar active_
		foreach target [array names active_] {
			if { $active_($target) >= 0 } {
				lappend oifs [$self slot $active_($target)]
			}
		}
	}
	return [lsort $oifs]
}

Classifier/Replicator/Demuxer instproc disable target {
	$self instvar nactive_ active_
	if {[info exists active_($target)] && $active_($target) >= 0} {
		$self clear $active_($target)
		set active_($target) -1
		incr nactive_ -1
	}
}

Classifier/Replicator/Demuxer instproc enable target {
	$self instvar nactive_ active_ ignore_
	if {$active_($target) < 0} {
		set active_($target) [$self installNext $target]
		incr nactive_
		set ignore_ 0
	}
}

Classifier/Replicator/Demuxer instproc exists target {
	$self instvar active_
	info exists active_($target)
}

Classifier/Replicator/Demuxer instproc is-active-target target {
	$self instvar active_
	if { [info exists active_($target)] && $active_($target) >= 0 } {
		return 1
	} else {
		return 0
	}
}

Classifier/Replicator/Demuxer instproc drop { src dst {iface -1} } {
	$self instvar node_
	[$node_ getArbiter] drop $self $src $dst $iface
}

Node instproc change-iface { src dst oldiface newiface} {
	$self instvar multiclassifier_
        $multiclassifier_ change-iface $src $dst $oldiface $newiface
}

Node instproc lookup-iface { src dst } {
	$self instvar multiclassifier_
        $multiclassifier_ lookup-iface $src $dst
}

Classifier/Replicator/Demuxer instproc reset {} {
	$self instvar nactive_ active_
	foreach { target slot } [array get active_] {
		$self clear $slot
	}
	set nactive_ 0
	unset active_
}

Agent/Mcast/Control instproc init { protocol } {
	 $self next
	 $self instvar proto_
	 set proto_ $protocol
}

Agent/Mcast/Control array set messages {}
Agent/Mcast/Control set mcounter 0

Agent/Mcast/Control instproc send {type from src group args} {
	Agent/Mcast/Control instvar mcounter messages
	set messages($mcounter) [concat [list $from $src $group] $args]
	$self cmd send $type $mcounter
	incr mcounter
}

Agent/Mcast/Control instproc recv {type iface m} {
	Agent/Mcast/Control instvar messages
	eval $self recv2 $type $iface $messages($m)
        #unset messages($m)
}

Agent/Mcast/Control instproc recv2 {type iface from src group args} {
        $self instvar proto_
        eval $proto_ recv-$type $from $src $group $iface $args
}

Node instproc rpf-nbr src {
	$self instvar ns_ id_
	if [catch "$src id" srcID] {	
		set srcID $src
	}
	$ns_ get-node-by-id [[$ns_ get-routelogic] lookup $id_ $srcID]
}

LanNode instproc rpf-nbr src {
	$self instvar ns_ id_
	if [catch "$src id" srcID] {	
		set srcID $src
	}
	$ns_ get-node-by-id [[$ns_ get-routelogic] lookup $id_ $srcID]
}
	
Node instproc getReps { src group } {
        $self instvar replicator_
        set reps ""
        foreach key [array names replicator_ "$src:$group"] { 
                lappend reps $replicator_($key)
        }
        return [lsort $reps]
}

Node instproc getReps-raw { src group } {
        $self array get replicator_ "$src:$group"
}

Node instproc clearReps { src group } {
        $self instvar multiclassifier_
        foreach {key rep} [$self getReps-raw $src $group] {
                $rep reset
                delete $rep

                foreach {slot val} [$multiclassifier_ adjacents] {
                        if { $val == $rep } {
                                $multiclassifier_ clear $slot
                        }
                }

                $self unset replicator_($key)
        }
}

Node instproc add-oif {head link} {
	$self instvar outLink_
	set outLink_($head) $link
}

Node instproc add-iif {iflbl link} {
	# array mapping ifnum -> link
	$self set inLink_($iflbl) $link
}

Node instproc get-all-oifs {} {
        $self instvar outLink_
	# return a sorted list of all "heads"
	return [lsort [array names outLink_]]
}

Node instproc get-all-iifs {} {
	$self instvar inLink_
	# return a list of "labels"
	return [array names inLink_]
}

Node instproc iif2oif ifid {
	$self instvar ns_
	set link [$self iif2link $ifid]
	# assuming that there have to be a reverse link
	# that is, all links are duplex.
	set outlink [$ns_ link $self [$link src]]
	return [$self link2oif $outlink]
}

Node instproc iif2link ifid {
        $self set inLink_($ifid)
}

Node instproc link2iif link {
	return [[$link set iif_] label]
}

Node instproc link2oif link {
	$link head
}

Node instproc oif2link oif {
	$oif set link_
}

# Find out what interface packets sent from $node will arrive at
# this node. $node need not be a neighbor. $node can be a node object
# or node id.
Node instproc from-node-iface { node } {
	$self instvar ns_
	catch {
		set node [$ns_ get-node-by-id $node]
	}
	set rpfnbr [$self rpf-nbr $node]
	set rpflink [$ns_ link $rpfnbr $self]
	if { $rpflink != "" } {
		return [$rpflink if-label?]
	}
	return "?" ;#unknown iface
}

Vlink instproc if-label? {} {
	$self instvar iif_
	$iif_ label
}