File: topo-gen.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 (661 lines) | stat: -rw-r--r-- 19,398 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
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
# Created May 98 by Ahmed Helmy; updated June 98
# topology generator class
Class TG

proc usage { } {
	puts stderr {usage: topology [options]

where options are given as: -key value
example options:
-outfile mytopo -type random -nodes 50 -method pure-random

"topology -h" help
}
	return
#	exit 1
}

proc detailed-usage { } {
puts {usage: topology [-<key 1> <value 1> -<key 2> <value 2> -<key n> <value n>]

example options: 
-generator itm -outfile myfile -type random -nodes 20 -connection_prob 0.6 

keys and corresponding values:
-generator
  possible value: itm (default) [the georgia tech topology generator]
  [note: you need to invoke itm and sgb2ns, e.g. by setting your path]

-outfile [the output file that will contain the ns script describing the
	  generated topology. This must be given.]

-type
  possible values: random (default), transit_stub

-seed
  possible values: integer (default = random [uses ns-random])

-nodes [the number of nodes in the topology; used with `-type random']
  possible values: integer (default = 50 with random, 100 with 
  transit-stub)

-scale [used by itm to place nodes in topologies] (default = nodes)

-method [the node connection/linking method; used with `-type random']
  possible values: waxman1, waxman2, pure-random, doar-leslie, exponential, 
                   and  locality (default = pure-random)

-connection_prob [the connection probability between nodes; used in 
       all methods] [this sometimes is called `alpha']
  possible values: 0.0 <= connection_prob <= 1.0 (default = 0.5)

-beta [used only with waxman1, waxman2, doar-leslie and locality]
  possible values: 0.0 <= beta (default = 0.5)

-gamma [used only with doar-leslie and locality]
  possible values: 0.0 <= gamma (default = 0.5)
  }
}

proc itm-random-help { } {
	puts {Comment from ITM, on edge connection methods:
   1. Edge is placed between two nodes by a probabilistic method, which
      is determined by the "method" parameter.  Edge is placed with
      probability p, where p is calculated by one of the methods below,
      using:
        alpha, beta, gamma: input parameters,
        L is scale * sqrt(2.0): the max distance between two points,
        d: the Euclidean distance between two nodes.
        e: a random number uniformly distributed in [0,L]
 
      Method 1: (Waxman's RG2, with alpha,beta)
           p = alpha * exp(-e/L*beta)
      Method 2: (Waxmans's RG1, with alpha,beta)
           p = alpha * exp(-d/L*beta)
      Method 3: (Pure random graph)
           p = alpha
      Method 4: ("EXP" - another distance varying function)
           p = alpha * exp(-d/(L-d))
      Method 5: (Doar-Leslie, with alpha,beta, gamma)
           p = (gamma/n) * alpha * exp(-d/(L*beta))
      Method 6: (Locality with two regions)
           p = alpha     if d <= L*gamma,
           p = beta      if d > L*gamma
 
   2. Constraints
        0.0 <=  alpha  <= 1.0  [alpha is a probability]
        0.0 <= beta            [beta is nonnegative]
        0.0 <= gamma           [gamma is nonnegative]
        n <  scale*scale       [enough room for nodes]
  }
}

proc itm-transit-stub-help { } {
	puts {Parameters for transit_stub topology by itm:

-stubs_per_transit [number of stubs per transit node] (default = 3)
-ts_extra_edges [number of extra transit-stub edges] (default = 0)
-ss_extra_edges [number of extra stub-stub edges] (default = 0) 

-transit_domains [number of transit domains] (default = 1)
-domains_scale [top level scale used by ITM] (default = 20)

* Connectivity of domains [similar to the random topology parameters]
-domains_method (default = pure-random)
-domains_connection_prob (default = 1.0) [fully connected]
-domains_beta (default = 0.5)
-domains_gamma (default = 0.5)

* Connectivity of transit nodes:
-transit_nodes (default = 4)
-transit_scale (default = 20)
-transit_method (default = pure-random)
-transit_connection_prob (default = 0.6)
-transit_beta (default = 0.5)
-transit_gamma (default = 0.5)

* Connectivity of stub nodes:
-stub_nodes (default = 8)
-stub_method (default = pure-random)
-stub_connection_prob (default = 0.4)
-stub_beta (default = 0.5)
-stub_gamma (default = 0.5)

* Total number of nodes is computed as follows:      
 nodes=transit_domains * transit_nodes * (1 + stubs_per_transit * stub_nodes)

 for example, for the above default settings we get:
        1 * 4 ( 1 + 3 * 8 ) = 100 nodes
  }

}

proc help-on-help { } {
	puts {Help available for random, transit stub, and edge connection method.

Help usage "topology -h <i>" 
where: 
<i> = 1 for random, 2 for transit stub, and 3 for edge connection method.
  }
}

proc help { x } {
	switch $x {
		1 { detailed-usage }
		2 { itm-transit-stub-help }
		3 { itm-random-help }
		default { puts "invalid help option"; help-on-help } 
	}
}

proc topology { args } {
	set len [llength $args]

	if $len {
	    set key [lindex $args 0]
            if {$key == "-?" || $key == "--help" || $key == "-help" \
			|| $key == "-h" } {
				if { [set arg2 [lindex $args 1]] == "" } {
					usage
					help-on-help
				} else {
                        	help $arg2
				}
			return
                }
	}

        if [expr $len % 2] {
                # if number is odd => error !
                puts "fewer number of arguments than needed in \"$args\""
                usage
		return
        }

        # default topology generator
        set generator itm

        if { $args != "" && [lindex $args 0] == "-generator" } {
		set generator [lindex $args 1]
		set args [lreplace $args 0 1]
	}

	# check if the generator type exists
	if [catch {set tg [TG/$generator info instances]}] {
		puts "unknown generator type $generator"
		usage
		return
	}
	if { $tg == "" } {
		set tg [new TG/$generator]
	}
	if ![llength $args] {
		$tg create
	} else {
		$tg create $args
	}
	ScenGen setTG $tg
}

Class TG/itm -superclass TG

TG/itm instproc init { } {
	$self next
}

TG/itm instproc default_options { } {
	# default set may not be complete for now.. !XXX
	$self instvar opt_info

	set opt_info {
		# init file to -1, must be supplied by input
		outfile -1

		# number of graphs and seed
		# flat random
		type random

		# number should not be changed by input... should be left 
		# as 1, and a tcl loop may create multiple graphs... left it as 
		# place holder in case this may change later.. !
		number 1
		# seed is randomized later if not entered as input
		seed -1

		nodes 50
		# if not entered assign to nodes later 
		scale -1 
		
		method pure-random
		connection_prob 0.5

		beta 0.5
		gamma 0.5

		# defaults for transit stub
	# total number of nodes is:
	# transit_domains * transit_nodes * (1 + stubs_per_transit * stub_nodes)
	# 1 * 4 ( 1 + 3 * 8 ) = 100 nodes
		stubs_per_transit 3
		ts_extra_edges 0
		ss_extra_edges 0

		transit_domains 1
		domains_scale 20
		domains_method pure-random
		domains_connection_prob 1.0
		domains_beta 0.5
		domains_gamma 0.5

		transit_nodes 4
		transit_scale 20
		transit_method pure-random
		transit_connection_prob 0.6
		transit_beta 0.5
		transit_gamma 0.5

		stub_nodes 8
		# the stub scale is ignored by ITM, is computed as fraction
		# of the transit scale... see proc comment below !
		stub_scale 10
		stub_method pure-random
		stub_connection_prob 0.4
		stub_beta 0.5
		stub_gamma 0.5

		# for N level hierarchy
		# assume all levels use same vars
		levels 3
		level_nodes 10
		level_scale 10
		level_method waxman1
		level_connection_prob 0.7
		level_beta 0.2
		level_gamma 0.5
	}
	$self parse_opts
}
	
TG instproc parse_opts { } {
	$self instvar opts opt_info

	while { $opt_info != ""} {
		# parse line by line
                if {![regexp "^\[^\n\]*\n" $opt_info line]} {
                        break  
                }
		# remove the parsed line
                regsub "^\[^\n\]*\n" $opt_info {} opt_info
		# remove leading spaces and tabs using trim
                set line [string trim $line]
		# skip comment lines beginning with #
                if {[regexp "^\[ \t\]*#" $line]} {
                        continue
                }
		# skip empty lines
                if {$line == ""} {
                        continue
                } elseif [regexp {^([^ ]+)[ ]+([^ ]+)$} $line dummy key value] {
                        set opts($key) $value
                } 
	}
}

TG instproc parse_input { args } {
	# remove the list brackets from the args list
        set args [lindex $args 0]
        set len [llength $args]

	$self instvar opts

	for { set i 0 } { $i < $len } { incr i } {
		set key [lindex $args $i]
		regsub {^-} $key {} key
                if {![info exists opts($key)]} {
			puts stderr "unrecognized option $key"
			usage
			return -1
		}
		incr i
		# puts "changing $key from $opts($key) to [lindex $args $i]"
		set opts($key) [lindex $args $i]
	}
	# puts "end of parsing... "
	return 0
}

TG instproc create { args } {
        # remove the list brackets from the args list
        set args [lindex $args 0]
        set len [llength $args]
        # puts "calling create with args $args, len $len"

	$self default_options

	if $len {
		if { [$self parse_input $args] == -1 } {
			return 
		}
	}
	# check that the filename is provided
	$self instvar opts
	if { $opts(outfile) == -1 } {
puts {you must provide the outfile name !!.. use "topology -h" for help}
		return
	}
	$self create-topology
}

	

# XXX to be extended to include stubs... and other topo info
TG instproc setNodes { type num } {
	$self instvar nodes
	set nodes($type) $num
	# puts "nodes($type) = $nodes($type)"

	# now we stor nodes(all) x
	# should be able to store nodes(stub1) x1-x2
	# keep track of the num of stubs... etc
}

TG instproc getNodes { type } {
	$self instvar nodes
	if { ![info exists nodes($type)]} {
		puts "error: $type doesnot exist! Check srcstub/deststub arguments"
		exit
	}
	return $nodes($type)
}

TG/itm instproc create-topology { } {

	$self instvar opts

	# initialize the seed if not given
	if { $opts(seed) == -1 } {
		set opts(seed) [ns-random]
	}

	puts "type $opts(type), seed $opts(seed)"

	switch $opts(type) {
	  "random" {
		# compose the filename
		set i 0
		while { 1 } {
			# avoid clashing with prev files, incr i
			set topo_filename rand-$opts(nodes)-$i
			if ![file exists $topo_filename] {
				break
			}
			incr i
		}
		set topo_file [open $topo_filename w]

                # write to a file in GA tech format  
                # for now generate 1 graph,... 
		# check the scale, if not give, assign # of nodes
		if { $opts(scale) == -1 } {
			set opts(scale) $opts(nodes)
		}

		$self setNodes all $opts(nodes)

		puts "nodes $opts(nodes), scale $opts(scale), \
		     method $opts(method)"
		puts "conn prob $opts(connection_prob), beta \
		     $opts(beta), gamma $opts(gamma)"

                puts $topo_file "geo $opts(number) $opts(seed)"
		set str [$self rand-line $opts(nodes) $opts(scale) \
		  $opts(method) $opts(connection_prob) $opts(beta) \
		  $opts(gamma)]
		puts $topo_file $str
	  }
	  "transit_stub" {
		# filename
                set i 0
                while { 1 } {
                        # avoid clashing with prev files, incr i
	set topo_filename ts-$opts(transit_domains)-$opts(transit_nodes)-$i
                        if ![file exists $topo_filename] {
                                break
                        }
                        incr i   
                }
                set topo_file [open $topo_filename w]  
              
		# debugging stuff !!!
		puts "stubs per transit $opts(stubs_per_transit), \
		 ts extra $opts(ts_extra_edges), ss extra $opts(ss_extra_edges)"
		puts "transit domains $opts(transit_domains), \
		 domains_scale $opts(domains_scale), domains_method \
		 $opts(domains_method)"
		puts "domains_conn $opts(domains_connection_prob), \
			beta $opts(domains_beta), gamma $opts(domains_gamma)"
		puts "transit_nodes $opts(transit_nodes), \
		  transit_scale $opts(transit_scale), \
		  transit_method $opts(transit_method)"
		puts "transit prob $opts(transit_connection_prob) \
		  transit_beta $opts(transit_beta), \
		  transit_gamma $opts(transit_gamma)"
		puts "stub_nodes $opts(stub_nodes), \
		  stub_method $opts(stub_method), \
		  stub_conn $opts(stub_connection_prob) \
		  stub_beta $opts(stub_beta) \
		  stub_gamma $opts(stub_gamma)"

		set total_nodes [expr $opts(transit_domains) * \
		  $opts(transit_nodes) * [expr 1 + $opts(stubs_per_transit) \
		  * $opts(stub_nodes)]]
		puts "Total nodes = $total_nodes\n"

		#check if number of nodes specified is diff from
		# the total nodes after computation.
		if {$opts(nodes) != $total_nodes} {
			puts "\n ERROR: Nodes specified = $opts(nodes)                        \nActual number of total nodes = $total_nodes
			\nFor transit_stub type, specify value of \"transit_domains\", \"transit_nodes\", \"stubs_per_transit\" and \"stub_nodes\" to change the number of nodes in your topology\n"
			
			exit 1
			
		}	
		$self setNodes all $total_nodes

		puts $topo_file "ts $opts(number) $opts(seed)"
		puts $topo_file "$opts(stubs_per_transit) \
			$opts(ts_extra_edges) $opts(ss_extra_edges)"
		set str [$self rand-line $opts(transit_domains) \
		  $opts(domains_scale) $opts(domains_method) \
		  $opts(domains_connection_prob) $opts(domains_beta) \
		  $opts(domains_gamma)]
		puts $topo_file $str
		set str [$self rand-line $opts(transit_nodes) \
		  $opts(transit_scale) $opts(transit_method) \
		  $opts(transit_connection_prob) $opts(transit_beta) \
		  $opts(transit_gamma)]
		puts $topo_file $str
		set str [$self rand-line $opts(stub_nodes) \
		  $opts(stub_scale) $opts(stub_method) \
		  $opts(stub_connection_prob) $opts(stub_beta) \
		  $opts(stub_gamma)]
		puts $topo_file $str
	  }
	  default { 
	   puts "invalid type \"$opts(type)\"!! use \"topology -h\" for help"
	   return
	  }
	}
	flush $topo_file
	close $topo_file
        $self generate-topo-gatech $topo_filename
	# cleanup if you want.. uncomment the next line !
	# exec rm $topo_filename
	# call the converter 'number' times
	# no need for this loop if number is always 1 .. XXX
	for { set i 0 } { $i < $opts(number) } { incr i } {
        	# output file is appended by -i.gb 
        	$self convert-to-ns $topo_filename-$i.gb $opts(outfile) $opts(type)

	}
	# clean up... not sure if the file is needed by hierarchical addressing
	# exec rm $topo_filename-0.gb

}

TG/itm instproc rand-line { nodes scale method conn_prob beta gamma } {
	lappend str $nodes $scale
	switch $method {
                "waxman1" {
                  # need alpha and beta
                  lappend str 1 $conn_prob $beta
                }
                "waxman2" {
                  lappend str 2 $conn_prob $beta
                }
                "pure-random" {
                  # needs only alpha
                  lappend str 3 $conn_prob
                }
                "doar-leslie" {
                  # alpha, beta and gamma... X seems to use only alpha !
                  lappend str 4 $conn_prob $beta $gamma
                } 
                "exponential" {
                   # alpha .. XXX doesn't work now !!
                  lappend str 5 $conn_prob
		}
                "locality" {
		   # alpha , beta and gamma
		   lappend str 6 $conn_prob $beta $gamma
		}
                default {
                        puts "unidentified method $method .. aborting !!"
			usage
                        return
                }
	}
	# puts "str $str"
	return $str
}

TG/itm instproc generate-topo-gatech { fn } {
        exec itm $fn
}
                   
TG/itm instproc convert-to-ns { fn outfile type} {
	
	# to avoid generating false errors if sgb2ns is careless
	# about its return/exit value
	#
	# topofile generated by sgb2hierns program; has topology info used by
	# topogen and agentgen
	# So If type permits, read in topofile and cleanup.
	#
	if {$type == "transit_stub"} {
		set topofile $outfile.topoinfo
		catch { exec sgb2hierns $fn $outfile $topofile }
		$self getTopoInfo $topofile
		#exec rm $topofile
		return
	} 
	catch { exec sgb2ns $fn $outfile}
}

#
# Read in topology info from topo.$outfile
#
TG/itm instproc getTopoInfo topofile {
	set input [open $topofile r]
	foreach line [split [read $input] \n] {
		set stream [split $line]
		switch [lindex $stream 0] {
			"transits" {$self getLine $stream "transit"}
			"total-stubs" {$self setNodes "total-stubs" [lindex $stream 1]}
			"stubs" {$self getLine $line "stub"}
			"nodes/stub" {$self getLine $line "nodes/stub"}
		}
	}
	close $input
}


#
# Read each line and store away topoinfo
#

TG/itm instproc getLine {line type} {
	$self instvar nodes
	for {set i 1} {$i < [llength $line]} {incr i} {
		if {$type == "nodes/stub"} {
			set start $nodes(stub$i)
			set range [lindex $line $i]
			# puts "start=$start range=$range"
			$self setNodes stub$i $start:[expr $start + $range - 1]
		} else {
			$self setNodes $type$i [lindex $line $i]
		}
	}
}






proc comment { } {
puts {
 * itm.c -- Driver to create graphs using geo(), geo_hier(), and transtub().
 *
 * Each argument is a file containing ONE set of specs for graph generation.
 * Such a file has the following format:
 *    <method keyword> <number of graphs> [<initial seed>]
 *    <method-dependent parameter lines>
 * Supported method names are "geo", "hier", and "ts".
 * Method-dependent parameter lines are described by the following:
 *    <geo_parms> ::=
 *        <n> <scale> <edgeprobmethod> <alpha> [<beta>] [<gamma>]
 *    <"geo" parms> ::= <geo_parms>
 *    <"hier" parms> ::=
 *          <number of levels> <edgeconnmethod> <threshold>
 *          <geo_parms>+  {one per number of levels}
 *    <"ts" parms> ::=
 *          <# stubs/trans node> <#t-s edges> <#s-s edges>
 *          <geo_parms>       {top-level parameters}
 *          <geo_parms>       {transit domain parameters}
 *          <geo_parms>       {stub domain parameters}
 *
 * Note that the stub domain "scale" parameter is ignored; a fraction
 * of the transit scale range is used.  This fraction is STUB_OFF_FACTOR,
 * defined in ts.c.
 *
 * From the foregoing, it follows that best results will be obtained with
 *   -- a SMALL value for top-level scale parameter
 *   -- a LARGE value for transit-level scale parameter
 * and then the value of stub-level scale parameter won't matter.
 *
 * The indicated number of graphs is produced using the given parameters.
 * If the initial seed is present, it is used; otherwise, DFLTSEED is used.
 *
 * OUTPUT FILE NAMING CONVENTION:
 * The i'th graph created with the parameters from file "arg" is placed
 * in file "arg-i.gb", where the first value of i is zero.
 }
}

###############################################################
### the scenario generator keeps track of topology generator ##
### and can be queried to get this info			     ##
###############################################################

Class ScenGen

ScenGen set TG ""

ScenGen proc setTG { tg } {
	ScenGen set TG $tg
}

ScenGen proc getTG { } {
	return [ScenGen set TG]
}