1 2nd european ns-2 workshop day 2 polly huang eth zurich huang 18 & 19 april
Post on 21-Dec-2015
215 views
TRANSCRIPT
1
2nd European ns-2 WorkshopDay 2
Polly Huang
ETH Zurich
http://www.tik.ee.ethz.ch/~huang
18 & 19 April
2
Schedule: Yesterday
9-9.50 overview/intro/essential/getting started
10-10.50 tcl/otcl/ns-2 fundamentals
11-11.50 examples - TCP, RED, multicast, web, wireless
Lunch break
1.30-2.20 lab 1 setup/running examples
2.30-3.20 lab 2 tcl/otcl exercises
3.30-4.20 lab 3 simple ns-2 exercise
4.30-5.00 discussion/feedback
3
Schedule: Today
9-9.50 recap/wired internal
10-10.50 wireless internal/making changes
11-11.50 extending ns-2/case studies
Lunch break
1.30-2.20 lab 4 intermediate ns-2 exercise
2.30-3.20 lab 5 getting data you want
3.30-4.20 lab 6 advanced topic (TBD)
4.30-5.00 discussion/feedback
4
tcl Interpreter With Extensions
tcl8.0
otcl
tclcl
ns-2EventScheduler
Netw
orkC
omponent
5
Example Script
set ns [new Simulator]
set n0 [$ns node]
set n1 [$ns node]
n0 n1
set ftp [new Application/FTP]
$ftp attach-agent $tcp
$ns at 0.2 "$ftp start"
$ns at 1.2 ”exit"
$ns run$ns duplex-link $n0 $n1 1.5Mb
10ms DropTailset tcp [$ns create-connection
TCP $n0 TCPSink $n1 0]
6
Basic ns-2: Covered
• wired & wireless
• unicast & multicast
• TCP & UDP
• errors & network dynamics
• ns & nam tracing
• application-level support
7
Basic ns-2: Also But...
• mobile IP
• satellite
• DiffServ
• emulation
8
Outline for This Morning
• ns-2 Internal
• Making changes
• New components– in otcl– otcl and C++ Linkage– in C++
• Debugging
9
ns-2 Internals
• Discrete Event Scheduler
• Network Topology
• Routing
• Transport
• Application
• Packet Flow
• Packet Format
10
Discrete Event Scheduler
time_, uid_, next_, handler_
head_ ->
handler_ -> handle()
time_, uid_, next_, handler_insert
head_ ->
11
Network Topology - Node
n0 n1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
Node entry
Unicast Node
Multicast Classifier
classifier_
dmux_
entry_
Node entry
Multicast Node
multiclassifier_
12
Network Topology - Link
n0 n1
enqT_ queue_ deqT_
drophead_ drpT_
link_ ttl_
n1 entry_head_
13
Routing
n0 n1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
Node entry 0
1enqT_ queue_ deqT_
drophead_ drpT_
link_ ttl_
n1 entry_head_
14
Routing (cont.)
n0 n1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
0
1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
1
0Link n0-n1
Link n1-n0
15
0
1
Transport
n0 n1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
0 Agent/TCP
agents_
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
1
0Link n0-n1
Link n1-n0
0 Agent/TCPSink
agents_
dst_addr_=1dst_port_=0
dst_addr_=0dst_port_=0
16
Application
0
1
n0 n1
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
0 Agent/TCP
agents_
Addr Classifier
Port Classifier
classifier_
dmux_
entry_
1
0Link n0-n1
Link n1-n0
0 Agent/TCPSink
agents_
Application/FTP
dst_addr_=1dst_port_=0
dst_addr_=0dst_port_=0
17
Packet Flow
0
1
n0 n1
Addr Classifier
Port Classifier
entry_
0 Agent/TCP Addr Classifier
Port Classifier
entry_
1
0Link n0-n1
Link n1-n0
0 Agent/TCPSink
Application/FTP
dst_addr_=1dst_port_=0
dst_addr_=0dst_port_=0
18
Packet Format
header
data
ip header
tcp header
rtp header
trace header
cmn header
...
ts_
ptype_
uid_
size_
iface_
19
ns-2 Wireless Internal
• Packet headers
• Mobile node
• Wireless channel
20
Wireless Packet Format
header
data
ts_
ptype_
uid_
size_
iface_
IP header
......
cmn header
LL
MAC 802_11
......
ARP
wireless headers
21
Portrait of A Mobile NodeNode
ARP
Propagation and antenna models MobileNode
LL
MAC
PHY
LL
CHANNEL
LL
MAC
PHY
Classifier: Forwarding
Agent: Protocol EntityNode Entry
LL: Link layer object
IFQ: Interface queue
MAC: Mac object
PHY: Net interface
protocolagent
routingagent
addrclassifier
portclassifier
255
IFQIFQ
defaulttarget_
22
Mobile Node: Layer 2
• Link Layer– Same as LAN, but with a separate ARP module
• Interface queue– Give priority to routing protocol packets
• Mac Layer– IEEE 802.11
– RTS/CTS/DATA/ACK for all unicast packets
– DATA for all broadcast packets
23
Mobile Node: Layer 1
• Network interface (PHY)– Parameters based on Direct Sequence Spread Spectrum
(WaveLan)– Interface with: antenna and propagation models– Update energy: transmission and reception
• Radio Propagation Model– Friss-space attenuation(1/r2) at near distance– Two-ray Ground (1/r4) at far distance
• Antenna– Omni-directional, unity-gain
24
Wireless Channel
• Duplicate packets to all mobile nodes attached to the channel except the sender
• It is the receiver’s responsibility to decide if it will accept the packet– Collision is handled at individual receiver– O(N2) messages grid keeper
25
Grid-keeper: An Optimization
26
Outline for This Morning
• ns-2 Internal
• Making changes
• New components– in otcl– otcl and C++ Linkage– in C++
• debugging
27
Making Changes
• In otcl space– source– recompile
• in C++ space– recompile
28
Adding New Components
• in otcl
• otcl and C++ linkage
• in C++
29
New Component Purely in otcl
• Additional <new_stuff>.tcl file
• source <new_stuff>.tcl
• Adding new files– change Makefile (NS_TCL_LIB), tcl/lib/ns-
lib.tcl– recompile
30
Example: Agent/Message
n0 n1
n4
n5
n2
n3
128Kb, 50ms
10Mb, 1ms 10Mb, 1ms
C Ccrosstraffic
S R
msg agent
31
Agent/Message
• A UDP agent (without UDP header)• Up to 64 bytes user message• Good for fast prototyping a simple idea• Usage requires extending ns functionality
SS RR
pkt: 64 bytesof arbitrary string
Receiver-sideprocessing
32
Agent/Message: Step 1
• Define senderclass Sender –superclass Agent/Messageclass Sender –superclass Agent/Message
# Message format: “Addr Op SeqNo”# Message format: “Addr Op SeqNo”
Sender instproc send-next {} {Sender instproc send-next {} {
$self instvar seq_ agent_addr_$self instvar seq_ agent_addr_
$self send “$agent_addr_ send $seq_”$self send “$agent_addr_ send $seq_”
incr seq_incr seq_
global nsglobal ns
$ns at [expr [$ns now]+0.1] "$self send-next"$ns at [expr [$ns now]+0.1] "$self send-next"
}}
33
Agent/Message: Step 2
• Define sender packet processing
Sender instproc Sender instproc recvrecv msg { msg {
$self instvar agent_addr_$self instvar agent_addr_
set sdr [lindex $msg 0]set sdr [lindex $msg 0]
set seq [lindex $msg 2]set seq [lindex $msg 2]
puts "Sender gets ack $seq from $sdr"puts "Sender gets ack $seq from $sdr"
}}
34
Agent/Message: Step 3
• Define receiver packet processing
Class Receiver –superclass Agent/MessageClass Receiver –superclass Agent/Message
Receiver instproc Receiver instproc recvrecv msg { msg {
$self instvar agent_addr_$self instvar agent_addr_
set sdr [lindex $msg 0]set sdr [lindex $msg 0]
set seq [lindex $msg 2]set seq [lindex $msg 2]
puts “Receiver gets seq $seq from $sdr”puts “Receiver gets seq $seq from $sdr”
$self send “$addr_ ack $seq”$self send “$addr_ ack $seq”
}}
35
Agent/Message: Step 4
• Scheduler and tracing
# Create scheduler# Create scheduler
set ns [new Simulator]set ns [new Simulator]
# Turn on Tracing# Turn on Tracing
set fd [new “message.nam” w]set fd [new “message.nam” w]
$ns namtrace-all $fd$ns namtrace-all $fd
36
Agent/Message: Step 5
• Topologyfor {set i 0} {$i < 6} {incr i} {for {set i 0} {$i < 6} {incr i} {
set n($i) [$ns node]set n($i) [$ns node]}}$ns duplex-link $n(0) $n(1) 128kb 50ms DropTail$ns duplex-link $n(0) $n(1) 128kb 50ms DropTail$ns duplex-link $n(1) $n(4) 10Mb 1ms DropTail$ns duplex-link $n(1) $n(4) 10Mb 1ms DropTail$ns duplex-link $n(1) $n(5) 10Mb 1ms DropTail$ns duplex-link $n(1) $n(5) 10Mb 1ms DropTail$ns duplex-link $n(0) $n(2) 10Mb 1ms DropTail$ns duplex-link $n(0) $n(2) 10Mb 1ms DropTail$ns duplex-link $n(0) $n(3) 10Mb 1ms DropTail$ns duplex-link $n(0) $n(3) 10Mb 1ms DropTail
$ns queue-limit $n(0) $n(1) 5$ns queue-limit $n(0) $n(1) 5$ns queue-limit $n(1) $n(0) 5$ns queue-limit $n(1) $n(0) 5
37
Agent/Message: Step 6
• Routing
# Packet loss produced by queueing# Packet loss produced by queueing
# Routing protocol: let’s run distance vector# Routing protocol: let’s run distance vector
$ns rtproto DV$ns rtproto DV
38
Agent/Message: Step 7
• Cross trafficset udp0 [new Agent/UDP]set udp0 [new Agent/UDP]$ns attach-agent $n(2) $udp0$ns attach-agent $n(2) $udp0set null0 [new Agent/NULL]set null0 [new Agent/NULL]$ns attach-agent $n(4) $null0$ns attach-agent $n(4) $null0$ns connect $udp0 $null0$ns connect $udp0 $null0
set exp0 [new Application/Traffic/Exponential]set exp0 [new Application/Traffic/Exponential]$exp0 set rate_ 128k$exp0 set rate_ 128k$exp0 attach-agent $udp0$exp0 attach-agent $udp0$ns at 1.0 “$exp0 start”$ns at 1.0 “$exp0 start”
39
Agent/Message: Step 8
• Message agentsset sdr [new Sender]set sdr [new Sender]$sdr set packetSize_ 1000$sdr set packetSize_ 1000
set rcvr [new Receiver]set rcvr [new Receiver]$rcvr set packetSize_ 40$rcvr set packetSize_ 40
$ns attach $n(3) $sdr$ns attach $n(3) $sdr$ns attach $n(5) $rcvr$ns attach $n(5) $rcvr$ns connect $sdr $rcvr$ns connect $sdr $rcvr$ns connect $rcvr $sdr$ns connect $rcvr $sdr$ns at 1.1 “$sdr send-next”$ns at 1.1 “$sdr send-next”
40
Agent/Message: Step 9
• End-of-simulation wrapper (as usual)
$ns at 2.0 finish$ns at 2.0 finish
proc finish {} {proc finish {} {
global ns fdglobal ns fd
$ns flush-trace$ns flush-trace
close $fdclose $fd
exit 0exit 0
}}
41
Agent/Message: Result
• Example output> ./ns msg.tcl> ./ns msg.tclReceiver gets seq 0 from 0Receiver gets seq 0 from 0Sender gets ack 0 from 1Sender gets ack 0 from 1Receiver gets seq 1 from 0Receiver gets seq 1 from 0Sender gets ack 1 from 1Sender gets ack 1 from 1Receiver gets seq 2 from 0Receiver gets seq 2 from 0Sender gets ack 2 from 1Sender gets ack 2 from 1Receiver gets seq 3 from 0Receiver gets seq 3 from 0Sender gets ack 3 from 1Sender gets ack 3 from 1Receiver gets seq 4 from 0Receiver gets seq 4 from 0Sender gets ack 4 from 1Sender gets ack 4 from 1Receiver gets seq 5 from 0Receiver gets seq 5 from 0
42
Add Your Changes into ns
TK8.0 OTcl tclclTcl8.0 ns-2 nam-1
tcl
ex test lib
...
...
examples validation tests
C++ code
OTcl code
ns-allinone
mcastmysrc
msg.tcl
43
Add Your Change into ns
• tcl/lib/ns-lib.tclClass SimulatorClass Simulator……source ../mysrc/msg.tclsource ../mysrc/msg.tcl
• MakefileNS_TCL_LIB = \NS_TCL_LIB = \tcl/mysrc/msg.tcl \tcl/mysrc/msg.tcl \……
– Or: change Makefile.in, make distcleanmake distclean, then ./configure --enable-debug./configure --enable-debug
44
Extending ns in C++
• Adding code in <new_stuff>.{cc,h} files– Change Makefile– make depend– recompile
45
Guidelines
• Decide position in class hierarchy– I.e., which class to derive from?
• Create new packet header (if necessary)
• Create C++ class, fill in methods
• Define otcl linkage (if any)
• Write otcl code (if any)
• Build (and debug)
46
Important Basics
• class hierarchy
• otcl and C++ linkage
47
Class HierarchyTclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Deq Drop
Reno SACK
48
otcl and C++: The Duality
C++ OTcl
Pure C++objects
Pure OTclobjects
C++/OTcl split objects
ns
49
C++/otcl LinkageRoot of ns-2 object hierarchy
bind(): link variable values between C++ and OTcl TclObject
command(): link OTcl methods to C++ implementations
TclClass Create and initialize TclObject’s
Tcl C++ methods to access Tcl interpreter
TclCommand Standalone global commands
EmbeddedTcl ns script initialization
50
TclObject
• Basic hierarchy in ns for split objects
• Mirrored in both C++ and otcl
• Exampleset tcp [new Agent/TCP]set tcp [new Agent/TCP]
$tcp set packetSize_ 1024$tcp set packetSize_ 1024
$tcp advanceby 5000$tcp advanceby 5000
51
TclObject: Hierarchy and Shadowing
TclObject
Agent
Agent/TCP
Agent/TCP otcl shadow object
_o123Agent/TCP C++
object
*tcp
TclObject
Agent
TcpAgent
otcl classhierarchy
C++ classhierarchy
52
TclObject::bind()
• Link C++ member variables to otcl object variables
• C++TcpAgent::TcpAgent() {
bind(“window_”, &wnd_);… …
}
– bind_time(), bind_bool(), bind_bw()
• otclset tcp [new Agent/TCP]set tcp [new Agent/TCP]$tcp set window_ 200$tcp set window_ 200
53
Initialization of Bound Variables
• Initialization through otcl class variablesAgent/TCP set Agent/TCP set window_window_ 50 50
• Do all initialization of bound variables in ~ns/lib/ns-default.tcl– Otherwise a warning will be issued when the
shadow object is created
54
Implementation of Bound Variables
• Class InstVar– One object per bound variable – expensive!– InstVarInt, InstVarReal, …
• Created by TclObject::bind()– Create instance variable in otcl stack– Enable trap read/write to otcl variable using Tcl_TraceVar()Tcl_TraceVar()
– Connect to C++ variable in the trap
55
TclObject::command()
• Implement otcl methods in C++
• Trap point: otcl method cmd{}
• Send all arguments after cmd{} call to TclObject::command()
56
TclObject::command()• otcl
set tcp [new Agent/TCP]
$tcp advance 10
• C++int TcpAgent::command(int argc, const char*const* argv) {
if (argc == 3) { if (strcmp(argv[1], “advance”) == 0) { int newseq = atoi(argv[2]);
…… return(TCL_OK);
} }
return (Agent::command(argc, argv);}
57
TclObject::command()
$tcp send TclObject::unknown{} $tcp cmd sendno suchprocedure
TcpAgent::command()
match “send”?
Invoke parent: return Agent::command()
process and return
Yes No
OTcl space
C++ space
58
TclObject: Creation and Deletion
• Global procedures: new{}, delete{}
• Exampleset tcp [new Agent/TCP]set tcp [new Agent/TCP]
……
delete $tcpdelete $tcp
59
C++
OTcl
TclObject: Creation and Deletion
invoke parentconstructor
Agent/TCPconstructor
parentconstructor
invoke parentconstructor
TclObjectconstructor
create C++object
AgentTCPconstructor
invoke parentconstructor
invoke parentconstructor
parent (Agent)constructor
do nothing,return
TclObject (C++)constructor
bind variablesand return
bind variablesand return
create OTclshadow object
complete initialization
complete initialization
which C++ object to create? – TclClass
60
TclClass
TclObject
Agent
Agent/TCP
TclObject
Agent
TcpAgent
NsObject ??
OTclC++ mirroringStatic class TcpClass : public TclClass {public:
TcpClass() : TclClass(“Agent/TCP”) {}TclObject* create(int, const char*const*) {
return (new TcpAgent());}
} class_tcp;
Static class TcpClass : public TclClass {public:
TcpClass() : TclClass(“Agent/TCP”) {}TclObject* create(int, const char*const*) {
return (new TcpAgent());}
} class_tcp;
61
TclClass: Mechanism
• Initialization at runtime startup
SplitObject::register{} Create and register otcl class Agent/TCP
TclClass::init()
for each staticallydefined TclClass
TcpClass::bind()
e.g.
Agent/TCP::create-shadow{} TclClass::create_shadow()
62
Class Tcl
• Singleton class with a handle to Tcl interpreter
• Usage– Invoke otcl procedure– Obtain otcl evaluation results– Pass a result string to otcl– Return success/failure code to otcl
63
Class Tcl
Tcl& tcl = Tcl::instance();if (argc == 2) {
if (strcmp(argv[1], “now”) == 0) {tcl.resultf(“%g”, clock());return TCL_OK;
}tcl.error(“command not found”);return TCL_ERROR;
} else if (argc == 3) {tcl.eval(argv[2]);clock_ = atof(tcl.result());return TCL_OK;
}
64
Class TclCommand
• C++ implementation of global otcl commands
class RandomCommand : public TclCommand {public: RandomCommand() : TclCommand("ns-random") {} virtual int command(int argc, const char*const* argv);};
int RandomCommand::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 1) { sprintf(tcl.buffer(), "%u", Random::random()); tcl.result(tcl.buffer()); }
65
EmbeddedTcl
• Pre-load otcl scripts at ns runtime startup– Recursively load ~ns/tcl/lib/ns-lib.tcl:~ns/tcl/lib/ns-lib.tcl:
source ns-autoconf.tclsource ns-autoconf.tclsource ns-address.tclsource ns-address.tclsource ns-node.tclsource ns-node.tcl....... .......
– Load everything into a single C++ string– Execute this string at runtime startup
• Tcl::init(): load ~tclcl/tcl-object.tcl~tclcl/tcl-object.tcl
• Tcl_AppInit(): load ~ns/tcl/lib/ns-lib.tcl~ns/tcl/lib/ns-lib.tcl
66
EmbeddedTcl
• How it works– tcl2c++tcl2c++: provided by TclCL, converts tcl
scripts into a C++ static character array– Makefile.in:tclsh8.0 bin/tcl-expand.tcl tcl/lib/ns-tclsh8.0 bin/tcl-expand.tcl tcl/lib/ns-lib.tcl | tcl2c++ et_ns_lib > lib.tcl | tcl2c++ et_ns_lib > gen/ns_tcl.ccgen/ns_tcl.cc
67
Summary
• TclObject– Unified interpreted (otcl) and compiled (C++)
class hierarchies– Seamless access (procedure call and variable
access) between otcl and C++
• TclClass– The mechanism that makes TclObject work
• Tcl: primitives to access Tcl interpreter
68
Creating New Components
• new agent, old packet headers
• new agent, new packet header
69
New Agent, Old Header
• TCP jump start– Wide-open transmission window at the
beginning– From cwnd_ += 1cwnd_ += 1 To cwnd_ = MAXWIN_cwnd_ = MAXWIN_
70
TCP Jump Start – Step 1TclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Deq Drop
Reno SACK JS
71
TCP Jump Start – Step 2
• New file: tcp-js.h
class JSTCPAgent : public TcpAgent {class JSTCPAgent : public TcpAgent {
public:public:
virtual void set_initial_window() {virtual void set_initial_window() {
cwnd_ = MAXWIN_;cwnd_ = MAXWIN_;
}}
private:private:
int MAXWIN_;int MAXWIN_;
};};
72
TCP Jump Start – Step 3
• New file: tcp-js.ccstatic JSTcpClass : public TclClass {public:
JSTcpClass() : TclClass("Agent/TCP/JS") {}TclObject* create(int, const char*const*) {
return (new JSTcpAgent());}
};JSTcpAgent::JSTcpAgent() {
bind(“MAXWIN_”, MAXWIN_);}
73
New Agent, New Header
• Example: Agent/Message– New packet header for 64-byte message– New transport agent to process this new header
74
New Packet Header
• Create new header structure• Enable tracing support of new header• Create static class for otcl linkage
(packet.h)• Enable new header in otcl (tcl/lib/ns-
packet.tcl)• This does not apply when you add a new
field into an existing header!
75
How Packet Header WorksPacket
next_
hdrlen_
bits_ size determinedat compile time
size determinedat compile time
size determinedat compile time
……
hdr_cmn
hdr_ip
hdr_tcp
size determinedat simulatorstartup time
(PacketHeaderManager)
PacketHeader/Common
PacketHeader/IP
PacketHeader/TCP
76
New Packet Header – Step 1
• Create header structurestruct hdr_msg {struct hdr_msg {
char msg_[64];char msg_[64];static int offset_;static int offset_;inline static int& offset() { return offset_; }inline static int& offset() { return offset_; }inline static hdr_msg* access(Packet* p) {inline static hdr_msg* access(Packet* p) {
return (hdr_msg*) p->access(offset_);return (hdr_msg*) p->access(offset_);}}/* per-field member functions *//* per-field member functions */char* msg() { return (msg_); }char* msg() { return (msg_); }int maxmsg() { return (sizeof(msg_)); }int maxmsg() { return (sizeof(msg_)); }
};};
77
New Packet Header – Step 2
• PacketHeader/Messagestatic class MessageHeaderClass : static class MessageHeaderClass :
public PacketHeaderClass {public PacketHeaderClass {
public:public:
MessageHeaderClass() : MessageHeaderClass() : PacketHeaderClass("PacketHeader/Message",PacketHeaderClass("PacketHeader/Message",
sizeof(hdr_msg)) {sizeof(hdr_msg)) {
bind_offset(&hdr_msg::offset_);bind_offset(&hdr_msg::offset_);
}}
} class_msghdr;} class_msghdr;
78
New Packet Header – Step 3
• Enable tracing (packet.h):enum packet_t {enum packet_t {
PT_TCP,PT_TCP,……,,PT_MESSAGE,PT_MESSAGE,PT_NTYPE // This MUST be the LAST onePT_NTYPE // This MUST be the LAST one
};};class p_info {class p_info {
…………name_[PT_MESSAGE] = “message”;name_[PT_MESSAGE] = “message”;name_[PT_NTYPE]= "undefined";name_[PT_NTYPE]= "undefined";
…………};};
79
New Packet Header – Step 4
• Register new header (tcl/lib/ns-packet.tcl)
foreach pair {foreach pair {
{ Common off_cmn_ }{ Common off_cmn_ }
……
{ Message off_msg_ }{ Message off_msg_ }
}}
80
Packet Header: Caution
• Some old code, e.g.:RtpAgent::RtpAgent() {RtpAgent::RtpAgent() {
…… ……
bind(“off_rtp_”, &off_rtp);bind(“off_rtp_”, &off_rtp);
}}
…………
hdr_rtp* rh = (hdr_rtp*)p->access(off_rtp_);hdr_rtp* rh = (hdr_rtp*)p->access(off_rtp_);
• Don’t follow this example!
81
Agent/Message – Step 1TclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Deq Drop
Reno SACK
Message
82
Agent/Message – Step 2
• C++ class definition// Standard split object declaration// Standard split object declaration
static …static …
class MessageAgent : public Agent {class MessageAgent : public Agent {
public:public:
MessageAgent() : Agent(MessageAgent() : Agent(PT_MESSAGEPT_MESSAGE) {}) {}
virtual int command(int argc, const char*const* virtual int command(int argc, const char*const* argv);argv);
virtual void recv(Packet*, Handler*);virtual void recv(Packet*, Handler*);
};};
83
Agent/Message – Step 3
• Packet processing: sendint MessageAgent::command(int, const char*const* argv)int MessageAgent::command(int, const char*const* argv){{
Tcl& tcl = Tcl::instance();Tcl& tcl = Tcl::instance();if (strcmp(argv[1], "send") == 0) {if (strcmp(argv[1], "send") == 0) {
Packet* pkt = allocpkt();Packet* pkt = allocpkt();hdr_msg* mh = hdr_msg::access(pkt);hdr_msg* mh = hdr_msg::access(pkt);// We ignore message size check...// We ignore message size check...strcpy(mh->msg(), argv[2]);strcpy(mh->msg(), argv[2]);send(pkt, 0);send(pkt, 0);return (TCL_OK);return (TCL_OK);
}}return (Agent::command(argc, argv));return (Agent::command(argc, argv));
}}
84
Agent/Message – Step 4
• Packet processing: receivevoid MessageAgent::recv(Packet* pkt, Handler*)void MessageAgent::recv(Packet* pkt, Handler*){{
hdr_msg* mh = hdr_msg::access(pkt);hdr_msg* mh = hdr_msg::access(pkt);
// OTcl callback// OTcl callbackchar wrk[128];char wrk[128];sprintf(wrk, "%s recv {%s}", name(), mh->msg());sprintf(wrk, "%s recv {%s}", name(), mh->msg());Tcl& tcl = Tcl::instance();Tcl& tcl = Tcl::instance();tcl.eval(wrk);tcl.eval(wrk);
Packet::free(pkt);Packet::free(pkt);}}
85
Outline for This Morning
• ns-2 Internal
• Making changes
• New components– in otcl– otcl and C++ Linkage– in C++
• debugging
86
My ns dumps otcl scripts!
– Find the last 10-20 lines of the dump– Is the error related to “_o4 cmd …” ?
• Check your command()
– Otherwise, check the otcl script pointed by the error message
87
Debugging
• printf() and puts “”
• gdb
• tcl debugger– http://expect.nist.gov/tcl-debug/– place debug 1 at the appropriate location– trap to debugger from the script– single stepping through lines of codes– examine data and code using Tcl-ish commands
88
C++/otcl Debugging
• Usual technique– Break inside command()– Cannot examine states inside otcl!
• Solution– Execute tcl-debug inside gdb
89
C++/otcl Debugging(gdb) (gdb) call Tcl::instance().eval(“debug 1”)call Tcl::instance().eval(“debug 1”)15: lappend auto_path $dbg_library15: lappend auto_path $dbg_librarydbg15.3> wdbg15.3> w*0: application*0: application 15: lappend auto_path $dbg_library15: lappend auto_path $dbg_librarydbg15.4> Simulator info instancesdbg15.4> Simulator info instances_o1_o1dbg15.5> _o1 nowdbg15.5> _o1 now00dbg15.6> # and other fun stuffdbg15.6> # and other fun stuffdbg15.7> dbg15.7> cc(gdb) where(gdb) where#0 0x102218 in write()#0 0x102218 in write()............
90
Memory Debugging in ns
• Purify• Gray Watson’s dmalloc library
– http://www.dmalloc.com – make distclean– ./configure --with-dmalloc=<dmalloc_path>– Analyze results: dmalloc_summarize
91
dmalloc: Usage
• Turn on dmalloc– alias dmalloc ’eval ‘\dmalloc –C \!*`’– dmalloc -l log low
• dmalloc_summarize ns < logfile– ns must be in current directory– itemize how much memory is allocated in each
function
92
Memory Leaks
• Purify or dmalloc, but be careful about split objects:for {set i 0} {$i < 500} {incr i} {for {set i 0} {$i < 500} {incr i} {
set a [new set a [new RandomVariable/Constant]RandomVariable/Constant]
}}
– It leaks memory, but can’t be detected!
• Solution– Explicitly delete EVERY split object that was
new-ed
93
Memory Conservation Tips
• Avoid trace-alltrace-all
• Use arrays for a sequence of variables– Instead of n$in$i, say n($i)n($i)
• Avoid OTcl temporary variables
• Use dynamic binding– delay_bind()delay_bind() instead of bind()bind()– See object.{h,cc}
94
Scalability vs Flexibility
• It’s tempting to write all-otcl simulation– Benefit: quick prototyping– Cost: memory + runtime
• Solution– Control the granularity of your split object by
migrating methods from otcl to C++
95
The Merit of OTcl
Program size, complexity
C/C++ OTcl
• Smoothly adjust the granularity of scripting to balance extensibility and performance
• With complete compatibility with existing simulation scripts
high low
split objects
96
Object Granularity Tips
• Functionality– Per-packet processing C++– Hooks, frequently changing code otcl
• Data management– Complex/large data structure C++– One-time configuration variables otcl
97
98
Case Studies
• Network Layer: Network Interface (packet labeler)
• Transport Layer: TCP Jump Start
• Application Layer: Message agent (ping)
99
Case 1: Network Layer
• Network Interface - Packet Labeler
n0 n1 n2
NetworkInterface A NetworkInterface B
100
Class Hierarchy
TclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Dnq Drop
Reno SACK
Network Interface
101
Network Interface Labeler
• class NetworkInterface– NetworkInterface()– recv(pkt)
• pkt->iface() = label_
– send(pkt)• target->recv(pkt)
– command()• label argv {label_ = argv}
• TclClass(“networkinterface”)
C++ otcl
NetworkInterface networkinterface
set iface [new networkinteface]$iface label A
command(): label
102
Case 2: Transport Layer
• TCP Jump Start– from cwnd += 1– to cwnd = maxwin
103
Class Hierarchy
TclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Dnq Drop
Reno SACK JS
104
TCP Jump Start
• class JSTcpAgent– openwin()– slowdown()
• TclClass(“Agent/TCP/JS”)
105
Case 3: Application Layer
• Message sender (ping)
n0 n1 n2
Message Sender Message Sender
106
Class Hierarchy
TclObject
NsObject
Connector Classifier
Delay AddrClassifierAgent McastClasifierQueue Trace
DropTail RED TCP Enq Dnq Drop
Reno SACK MessageAgent
107
Message Sender
• class MessageAgent– MessageAgent()– recv()– send()– command()
• send {send()}
• TclClass(“Agent/Message”)
C++ otcl
MessageAgent Agent/Message
set msg [new Agent/Message]$msg send
command(): send