traffic.tcl 12.8 KB
Newer Older
1
# -*- tcl -*-
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2
3
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
5
6
7
# All rights reserved.
#

Leigh B. Stoller's avatar
Leigh B. Stoller committed
8
9
10
11
12
13
14
######################################################################
# traffic.tcl
#
#
# This defines the various agents and applications needed to support
# traffic generation.  Specifically it defines Agent/UDP, Agent/Null,
# and Application/Traffic/CBR.
15
16
17
18
19
#
# Added: TCP traffic generation using NSE. Defines
# Agent/TCP/FullTcp, Agent/TCP/FullTcp/Reno, Agent/TCP/FullTcp/Newreno,
# Agent/TCP/FullTcp/Tahoe, Agent/TCP/FullTcp/Sack,
# Application/FTP and Application/Telnet
Leigh B. Stoller's avatar
Leigh B. Stoller committed
20
21
22
23
######################################################################

Class Agent -superclass NSObject
Class Agent/UDP -superclass Agent
24
Class Agent/TCP -superclass Agent
Leigh B. Stoller's avatar
Leigh B. Stoller committed
25
Class Agent/Null -superclass Agent
26
Class Agent/TCPSink -superclass Agent
27
28
29
30
31
Class Agent/TCP/FullTcp -superclass Agent
Class Agent/TCP/FullTcp/Reno -superclass Agent/TCP/FullTcp
Class Agent/TCP/FullTcp/Newreno -superclass Agent/TCP/FullTcp
Class Agent/TCP/FullTcp/Tahoe -superclass Agent/TCP/FullTcp
Class Agent/TCP/FullTcp/Sack -superclass Agent/TCP/FullTcp
Leigh B. Stoller's avatar
Leigh B. Stoller committed
32
33
34

Class Application -superclass NSObject
Class Application/Traffic/CBR -superclass Application
35
36
Class Application/FTP -superclass Application
Class Application/Telnet -superclass Application
37
Class Application/Program -superclass Application
Leigh B. Stoller's avatar
Leigh B. Stoller committed
38
39
40
41

namespace eval GLOBALS {
    set new_classes(Agent/UDP) {}
    set new_classes(Agent/Null) {}
42
    set new_classes(Agent/TCP) {}
43
    set new_classes(Agent/TCPSink) {}
44
45
46
47
48
    set new_classes(Agent/TCP/FullTcp) {}
    set new_classes(Agent/TCP/FullTcp/Reno) {}
    set new_classes(Agent/TCP/FullTcp/Newreno) {}
    set new_classes(Agent/TCP/FullTcp/Tahoe) {}
    set new_classes(Agent/TCP/FullTcp/Sack) {}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
49
    set new_classes(Application/Traffic/CBR) {}
50
51
    set new_classes(Application/FTP) {}
    set new_classes(Application/Telnet) {}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
52
53
54
55
56
}

# Agent
Agent instproc init {} {
    $self set node {}
57
58
59
    # Which link (interface) on the node this agent is attached to.
    # If not set, default to the only one we currently allow.
    $self set link {}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
60
61
    $self set application {}
    $self set destination {}
62
63
64
    $self set proto {}
    $self set role {}
    $self set port {}
65
    $self set generator "TG"
66
67
    global ::GLOBALS::last_class
    set ::GLOBALS::last_class $self
68
69
70
71
72
73
    var_import ::GLOBALS::simulated
    if { $simulated == 1 } {
	$self set simulated 1
    } else {
	$self set simulated 0
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
74
75
76
}
Agent instproc set_node {node} {
    $self set node $node
77
    $self set port [$node next_portnumber]
Leigh B. Stoller's avatar
Leigh B. Stoller committed
78
}
79
80
81
82
Agent instproc get_node {} {
    $self instvar node
    return $node
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
83
84
Agent instproc set_application {application} { 
    $self set application $application
85
86
    $self set role [$application set role]
    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
87
88
89
90
}
Agent instproc connect {dst} {
    $self instvar destination
    if {$destination != {}} {
91
	puts stderr "*** WARNING: \[connect] $self is already connected to $destination"
Leigh B. Stoller's avatar
Leigh B. Stoller committed
92
93
94
    }
    set destination $dst
}
95
96
97
98
99
100
101
Agent instproc rename {old new} {
    $self instvar application
    # In normal conditions this will never occur.
    if {$application != {}} {
	$application set agent $new
    }
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
102

103
104
105
106
107
# updatedb DB
# This adds rows to the virt_trafgens table corresponding to this agent.
Agent instproc updatedb {DB} {
    var_import ::GLOBALS::pid
    var_import ::GLOBALS::eid
108
    var_import ::TBCOMPAT::objtypes
109
110
111
112
113
    $self instvar application
    $self instvar destination
    $self instvar node
    $self instvar proto
    $self instvar role
114
    $self instvar generator
115
    $self instvar port
116
    $self instvar link
117
    $self instvar simulated
118

119
120
121
122
    if {$node == {}} {
	perror "\[updatedb] $self is not attached to a node."
	return
    }
123
124
125
126
127
128
129
130
    if {$role == {}} {
	perror "\[updatedb] $self has no role."
	return
    }
    if {$destination == {}} {
	perror "\[updatedb] $self has no destination."
	return
    }
131
132
133
134
    if { ($role == "source") && ($application == {}) } {
        perror "\[updatedb] $self does not have an attached application."
        return
    }
135
136
137
    set target_vnode [$destination set node]
    set target_port [$destination set port]

138
    # At some point allow users to set link. For now, first link (0).
139
140
    set ip [$node ip 0]
    set target_ip [$target_vnode ip 0]
141

142
    if {$role == "sink"} {
143
	set application $self
144
	set proto [$destination set proto]
145
146
147
	set target_vname [$destination set application]
    } else {
	set target_vname $destination
148
149
    }

150
151
152
    if { $simulated == 0 } {
	# Update the DB
	spitxml_data "virt_trafgens" [list "vnode" "vname" "role" "proto" "port" "ip" "target_vnode" "target_vname" "target_port" "target_ip" "generator" ] [list $node $application $role $proto $port $ip $target_vnode $target_vname $target_port $target_ip $generator ]
153

154
155
	spitxml_data "virt_agents" [list "vnode" "vname" "objecttype" ] [list $node $application $objtypes(TRAFGEN)]
    }
156
157
158
159
160
161
}

# get_nseconfig is only defined for subclasses that will be simulated by NSE
# Will be called from Node updatedb
Agent instproc get_nseconfig {} {
   return ""
162
163
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
164
165
166
# Agent/UDP 
Agent/UDP instproc connect {dst} {
    $self next $dst
167
    $self set proto "udp"
168
    $self set role "source"
Leigh B. Stoller's avatar
Leigh B. Stoller committed
169
170
}

171
172
173
174
# Agent/TCP
Agent/TCP instproc connect {dst} {
    $self next $dst
    $self set proto "tcp"
175
    $self set role "source"
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
# Agent/TCP/FullTcp
Agent/TCP/FullTcp instproc init args {

    eval $self next $args
    $self set simulated 1
    $self set tcptype ""
    $self set segsize_ 1460
    $self set role "source" 
    $self set generator "NSE"
}

# Agent/TCP/FullTcp/Newreno
Agent/TCP/FullTcp/Newreno instproc init args {
    eval $self next $args
    $self set tcptype "Newreno"
}

# Agent/TCP/FullTcp/Tahoe
Agent/TCP/FullTcp/Tahoe instproc init args {
    eval $self next $args
    $self set tcptype "Tahoe"
}

# Agent/TCP/FullTcp/Sack
Agent/TCP/FullTcp/Sack instproc init args {
    eval $self next $args
    $self set tcptype "Sack"
}

# Agent/TCP/FullTcp
Agent/TCP/FullTcp instproc listen {} {

   $self set role "sink"

}

# updatedb DB
# This adds rows to the virt_trafgens table corresponding to this agent.
# We do things differently from the base class version. For NSE, the
# vname in the table is the FullTcp agent object and not the application
# object connected to it. The important thing is using "$ns at", we can
# send events and control any of these objects
Agent/TCP/FullTcp instproc updatedb {DB} {
    var_import ::GLOBALS::pid
    var_import ::GLOBALS::eid
223
    var_import ::TBCOMPAT::objtypes
224
225
226
227
228
229
230
    $self instvar application
    $self instvar destination
    $self instvar node
    $self instvar proto
    $self instvar role
    $self instvar generator
    $self instvar port
231
    $self instvar link
232
    $self instvar simulated
233

234
235
236
237
    if {$node == {}} {
	perror "\[updatedb] $self is not attached to a node."
	return
    }
238
239
240
241
242
243
244
245
    if {$role == {}} {
	perror "\[updatedb] $self has no role."
	return
    }
    if {$destination == {}} {
	perror "\[updatedb] $self has no destination."
	return
    }
246
247
248
249
    if { ($role == "source") && ($application == {}) } {
        perror "\[updatedb] $self does not have an attached application."
        return
    }
250
251
252
    set target_vnode [$destination set node]
    set target_port [$destination set port]

253
254
255
256
    # At some point allow users to set link. For now, first link (0).
    set ip [$node ip 0]
    set target_ip [$target_vnode ip 0]

257
    set vname $self
258
    set target_vname $destination
259

260
261
262
    if { $simulated == 0 } {
	# Update the DB
	spitxml_data "virt_trafgens" [list "vnode" "vname" "role" "proto" "port" "ip" "target_vnode" "target_vname" "target_port" "target_ip" "generator" ] [list  $node $vname $role $proto $port $ip $target_vnode $target_vname $target_port $target_ip $generator]
263

264
265
266
267
268
	spitxml_data "virt_agents" [list "vnode" "vname" "objecttype"] [list $node $vname $objtypes(NSE) ]

	if {$application != {}} {
	    spitxml_data "virt_agents" [list "vnode" "vname" "objecttype" ] [list $node $application $objtypes(NSE) ]
	}
269
    }
270
271
272
273
274
275
276
277
278
}

# Agent/TCP/FullTcp
Agent/TCP/FullTcp instproc get_nseconfig {} {

    $self instvar tcptype
    $self instvar role
    $self instvar simulated
    $self instvar application
279
    $self set objname $self
280
281
282
283
284
285
286
287
288
    
    set nseconfig ""

    # This agent could possibly be a real one in which case
    # we don't do NSE traffic generation
    if { $simulated != 1 } {
         return $nseconfig
    }

289
290
291
    # we set a global variable to indicate that NSE trafgen
    # is present so that nseinput.tcl can take appropriate
    # action
292
    append nseconfig "set nsetrafgen_present 1\n\n"
293
    if { ($tcptype == "") || ($tcptype == "Reno") } {
294
          append nseconfig "set $self \[new Agent/TCP/FullTcp]\n"
295
    } else {
296
          append nseconfig "set $self \[new Agent/TCP/FullTcp/$tcptype]\n"
297
    }
298

299
300
301
302
303
304
305
306
307
308
309
310
    if { $role == "sink" } {
         append nseconfig "\$$self listen\n\n"
    }

    # We end up including variables present only in TB parser. However
    # that does not matter coz all NS variables end with _ character
    # Pruning can be done later
    foreach var [$self info vars] {
           if { [$self set $var] != {} } {
             append nseconfig "\$$self set $var [$self set $var]\n"
           }
    }
311
    append nseconfig "\n"
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

    if { $application != {} } {
         append nseconfig [$application get_nseconfig]
    } 

    return $nseconfig
}


# Agent/TCP/FullTcp
Agent/TCP/FullTcp instproc connect {dst} {
    $self next $dst
    $self instvar node
    $self instvar application
    $self instvar destination
    $self instvar role

    $self set proto "tcp"
    $dst set proto "tcp"
    $node set osid "FBSD-STD"
Shashi Guruprasad's avatar
Shashi Guruprasad committed
332
    $node set realtime 1
333
334
    $dst set osid "FBSD-STD"
    $dst set realtime 1
335
336
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
337
338
339
# Agent/Null
Agent/Null instproc connect {dst} {
    $self next $dst
340
    $self set role "sink"
Leigh B. Stoller's avatar
Leigh B. Stoller committed
341
342
}

343
# Agent/Null
344
Agent/TCPSink instproc connect {dst} {
345
346
347
348
349
    $self next $dst
    $self set role "sink"
    $self set proto "tcp"
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
350
351
352
# Application
Application instproc init {} {
    $self set agent {}
353
    $self set role {}
354
355
    global ::GLOBALS::last_class
    set ::GLOBALS::last_class $self
356
357
358
359
360
361
    var_import ::GLOBALS::simulated
    if { $simulated == 1 } {
	$self set simulated 1
    } else {
	$self set simulated 0
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
362
363
364
365
366
}
Application instproc attach-agent {agent} {
    $self set agent $agent
    $agent set_application $self
}
367
368
Application instproc get_node {} {
    $self instvar agent
369
370
371
372
    if {$agent == {} } {
	perror "\[Application get_node] $self is not attached to an agent."
	return ""
    }
373
374
    return [$agent get_node]
}
375
376
Application instproc rename {old new} {
    $self instvar agent
377
    # In normal condition this will never occur.
378
379
380
381
    if {$agent != {}} {
	$agent set_application $self
    }
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
382
383
384
385
386
387

# Application/Traffic/CBR
Application/Traffic/CBR instproc init {} {
    $self set packetSize_ 210
    $self set rate_ "100Mbps"
    $self set interval_ {}
388
    $self set iptos_ {}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
389
    $self next
390
391
392
393
394
395
396
397
    
    $self set role "source"
}

Application/Traffic/CBR instproc get_params {} {
    $self instvar packetSize_
    $self instvar rate_
    $self instvar interval_
398
    $self instvar iptos_
399
400
401
402
403
404
405
406
407
408
409
410
411

    if {$rate_ != {} && $rate_ != 0} {
	set rate [parse_bw $rate_]
    } else {
	set rate -1
    }
    set param "PACKETSIZE=$packetSize_ RATE=$rate"

    if {$interval_ != {} && $interval_ != 0} {
	set param "$param INTERVAL=$interval_"
    } else {
	set param "$param INTERVAL=-1"
    }
412
413

    if {$iptos_ != {} && $iptos_ != 0} {
414
	set param "$param IPTOS=$iptos_"
415
    } else {
416
	set param "$param IPTOS=-1"
417
418
    }

419
    return $param
Leigh B. Stoller's avatar
Leigh B. Stoller committed
420
}
421
422
423
424
425
426
427
428
429
430
431
432
433

# Application/FTP
Application/FTP instproc init {} {
    $self next
   
    $self set role "source"
}

# Application/FTP
Application/FTP instproc get_nseconfig {} {

    $self instvar agent
    set nseconfig "set $self \[new Application/FTP]\n"
434
435
    
    append nseconfig "\$$self set objname $self\n"
436
437

    if { $agent != {} } {
438
         append nseconfig "\$$self attach-agent \$$agent\n"
439
    }
440
    append nseconfig "\n"
441
442

    # XXX temporary untill event system changes get in
443
    # append nseconfig "\[Simulator instance] at 30.0 \"\$$self start\"\n\n"
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

   return $nseconfig
}

# Application/Telnet
Application/Telnet instproc init {} {
    $self next
    $self instvar role
    $self instvar interval_

    $self set role "source"

# NS's default is 1.0 and therefore would result in inter-packet times
# to be chosen from the exponential distribution. If it is 0, it would
# be chosen based on the tcplib distribution. I differ from NS in my
# default because of the realism of tcplib distribution
    $self set interval_ 0.0
}

# Application/Telnet
Application/Telnet instproc get_nseconfig {} {
   
    $self instvar agent
    $self instvar interval_

    set nseconfig "set $self \[new Application/Telnet]\n"
470
471

    append nseconfig "\$$self set objname $self\n"
472
473
474
               
    append nseconfig "\$$self set interval_ $interval_\n"
    if { $agent != {} } {
475
         append nseconfig "\$$self attach-agent \$$agent\n"
476
    }
477
    append nseconfig "\n"
478
479
        
    # XXX temporary untill event system changes get in
480
    # append nseconfig "\[Simulator instance] at 30.0 \"\$$self start\"\n\n"
481
482
483

    return $nseconfig
}
484