File: McastProto.tcl

package info (click to toggle)
ns2 2.35%2Bdfsg-2.1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 78,780 kB
  • ctags: 27,490
  • sloc: cpp: 172,923; tcl: 107,130; perl: 6,391; sh: 6,143; ansic: 5,846; makefile: 816; awk: 525; csh: 355
file content (315 lines) | stat: -rw-r--r-- 8,797 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
#
# tcl/mcast/McastProto.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
# 
#
Class McastProtocol

McastProtocol instproc init {sim node} {
	$self next
	$self instvar ns_ node_ status_ type_ id_
	set ns_   $sim
	set node_ $node
	set status_ "down"
	set type_   [$self info class]
	set id_ [$node id]

	$ns_ maybeEnableTraceAll $self $node_
}

McastProtocol instproc getType {} { $self set type_ }

McastProtocol instproc start {}		{ $self set status_ "up"   }
McastProtocol instproc stop {}		{ $self set status_ "down" }
McastProtocol instproc getStatus {}	{ $self set status_	   }

McastProtocol instproc upcall {code args} {
	# currently expects to handle cache-miss and wrong-iif
	eval $self handle-$code $args
}
 
McastProtocol instproc handle-wrong-iif { srcID group iface } {
	# return values: 
	#   0 : do not call classify on this packet again
	#   1 : changed iif for the corresponding mfc-entry, classify again
	return 0
}

McastProtocol instproc handle-cache-miss { srcID group iface } {
	# return values: 
	#   0 : do not call classify on this packet again
	#   1 : changed iif for the corresponding mfc-entry, classify again
	return 0
}

McastProtocol instproc annotate args {
	$self instvar dynT_ node_ ns_
	set s "[$ns_ now] [$node_ id] $args" ;#nam wants uinique first arg???
	if [info exists dynT_] {
		foreach tr $dynT_ {
			$tr annotate $s
		}
	}
}

McastProtocol instproc join-group arg	{ 
	$self annotate $proc $arg 
}
McastProtocol instproc leave-group arg	{ 
	$self annotate $proc $arg
}

McastProtocol instproc trace { f src {op ""} } {
        $self instvar ns_ dynT_
	if {$op == "nam" && [info exists dynT_] > 0} {
		foreach tr $dynT_ {
			$tr namattach $f
		}
	} else {
		lappend dynT_ [$ns_ create-trace Generic $f $src $src $op]
	}
}
# This method is called when a change in routing occurs.
McastProtocol instproc notify { dummy } {
        $self instvar ns_ node_ PruneTimer_

	#build list of current sources
        foreach r [$node_ getReps "*" "*"] {
		set src_id [$r set srcID_]
		set sources($src_id) 1
	}
	set sourceIDs [array names sources]
	foreach src_id $sourceIDs {
		set src [$ns_ get-node-by-id $src_id]
		if {$src != $node_} {
			set upstream [$node_ rpf-nbr $src]
			if { $upstream != ""} {
				set inlink [$ns_ link $upstream $node_]
				set newiif [$node_ link2iif $inlink]
				set reps [$node_ getReps $src_id "*"]
				foreach r $reps {
					set oldiif [$node_ lookup-iface $src_id [$r set grp_]]
					if { $oldiif != $newiif } {
						$node_ change-iface $src_id [$r set grp_] $oldiif $newiif
					}
				}
			}
		}
		#next update outgoing interfaces
		set oiflist ""
		foreach nbr [$node_ neighbors] {
			set nbr_id [$nbr id]
			set nh [$nbr rpf-nbr $src] 
			if { $nh != $node_ } {
				# are we ($node_) the next hop from ($nbr) to 
				# the source ($src)
				continue
			}
			set oif [$node_ link2oif [$ns_ link $node_ $nbr]]
			# oif to such neighbor
			set oifs($oif) 1
		}
		set oiflist [array names oifs]

		set reps [$node_ getReps $src_id "*"]
		foreach r $reps {
			set grp [$r set grp_]
			set oldoifs [$r dump-oifs]
			set newoifs $oiflist
			foreach old $oldoifs {
				if [catch "$node_ oif2link $old" ] {
					# this must be a local agent, not an oif
					continue
				}
				set idx [lsearch $newoifs $old]
				if { $idx < 0} {
					$r disable $old
					if [info exists PruneTimer_($src_id:$grp:$old)] {
						delete $PruneTimer_($src_id:$grp:$old)
						unset PruneTimer_($src_id:$grp:$old)
					}
				} else {
					set newoifs [lreplace $newoifs $idx $idx]
				}
			}
			foreach new $newoifs {
				foreach r $reps {
					$r insert $new
				}
			}
		}
	}
}

McastProtocol instproc dump-routes {chan {grp ""} {src ""}} {
	$self instvar ns_ node_
	if { $grp == "" } {
		# dump all replicator entries
		array set reps [$node_ getReps-raw * *]
	} elseif { $src == "" } {
		# dump entries for group
		array set reps [$node_ getReps-raw * $grp]  ;# actually, more than *,g
	} else {
		# dump entries for src, group.
		array set reps [$node_ getReps-raw $src $grp]
	}
	puts $chan [concat "Node:\t${node_}([$node_ id])\tat t ="	\
			[format "%4.2f" [$ns_ now]]]
	puts $chan "\trepTag\tActive\t\tsrc\tgroup\tiifNode\t\tdest_nodes"
	foreach ent [lsort [array names reps]] {
		set sg [split $ent ":"]
		if { [$reps($ent) is-active] } {
			set active Y
		} else {
			set active N
		}
		# translate each oif to a link and then the neighbor node
		set dest ""
		foreach oif [$reps($ent) dump-oifs] {
			if ![catch { set nbr [[$node_ oif2link $oif] dst] } ] {
				set nbrid [$nbr id]
				if [$nbr is-lan?] {
					set nbrid ${nbrid}(L)
				}
				lappend dest $nbrid
			}
		}
		set s [lindex $sg 0]
		set g [lindex $sg 1]
		set iif [$node_ lookup-iface $s $g]

		set iif_node_id $iif
		catch {
			# catch: iif can be negative for senders
			set iif_node [[$node_ iif2link $iif] src]
			if [$iif_node is-lan?] {
				set iif_node_id [$iif_node id](L)
			} else {
				set iif_node_id [$iif_node id]
			}
		}

		puts $chan [format "\t%5s\t  %s\t\t%d\t0x%x\t%s\t\t%s"	\
				$reps($ent) $active $s $g $iif_node_id $dest]
	}
}


###################################################
Class mrtObject

#XXX well-known groups (WKG) with local multicast/broadcast
mrtObject set mask-wkgroups	0xfff0
mrtObject set wkgroups(Allocd)	[mrtObject set mask-wkgroups]

mrtObject proc registerWellKnownGroups name {
	set newGroup [mrtObject set wkgroups(Allocd)]
	mrtObject set wkgroups(Allocd) [expr $newGroup + 1]
	mrtObject set wkgroups($name)  $newGroup
}

mrtObject proc getWellKnownGroup name {
	assert "\"$name\" != \"Allocd\""
	mrtObject set wkgroups($name)
}

mrtObject registerWellKnownGroups ALL_ROUTERS
mrtObject registerWellKnownGroups ALL_PIM_ROUTERS

mrtObject proc expandaddr {} {
	# extend the space to 32 bits
	mrtObject set mask-wkgroups	0x7fffffff

	foreach {name group} [mrtObject array get wkgroups] {
		mrtObject set wkgroups($name) [expr $group | 0x7fffffff]
	}
}

mrtObject instproc init { node } {
        $self next
	$self set node_	     $node
}

mrtObject instproc addproto { proto { iiflist "" } } {
        $self instvar node_ protocols_
	# if iiflist is empty, protocol runs on all iifs
	if { $iiflist == "" } {
		set iiflist [$node_ get-all-iifs]
		lappend iiflist -1 ;#for local packets
	}
	foreach iif $iiflist {
		set protocols_($iif) $proto
	}
}

mrtObject instproc getType { protocolType } {
        $self instvar protocols_
        foreach iif [array names protocols_] {
                if { [$protocols_($iif) getType] == $protocolType } {
                        return $protocols_($iif)
                }
        }
        return ""
}

mrtObject instproc all-mprotos {op args} {
	$self instvar protocols_
	foreach iif [array names protocols_] {
		set p $protocols_($iif)
		if ![info exists protos($p)] {
			set protos($p) 1
			eval $p $op $args
		}
	}
}

mrtObject instproc start {}	{ $self all-mprotos start	}
mrtObject instproc stop {}	{ $self all-mprotos stop	}
mrtObject instproc notify dummy { $self all-mprotos notify $dummy }
mrtObject instproc dump-routes args {
	$self all-mprotos dump-routes $args
}

# similar to membership indication by igmp.. 
mrtObject instproc join-group { grp src } {
	eval $self all-mprotos join-group $grp $src
}

mrtObject instproc leave-group { grp src } {
	eval $self all-mprotos leave-group $grp $src
}

mrtObject instproc upcall { code source group iface } {
  # check if the group is local multicast to well-known group
	set wkgroup [expr [$class set mask-wkgroups]]
	if { [expr ( $group & $wkgroup ) == $wkgroup] } {
                $self instvar node_
		$node_ add-mfc $source $group -1 {}
		return 1
        } else {
		$self instvar protocols_
		$protocols_($iface) upcall $code $source $group $iface
	}
}

mrtObject instproc drop { replicator src dst {iface -1} } {
	$self instvar protocols_
	$protocols_($iface) drop $replicator $src $dst $iface
}