1
Extending ns Padma Haldar USC/ISI 1 Outline Extending ns In - - PowerPoint PPT Presentation
Extending ns Padma Haldar USC/ISI 1 Outline Extending ns In - - PowerPoint PPT Presentation
Extending ns Padma Haldar USC/ISI 1 Outline Extending ns In OTcl In C++ Debugging 2 ns Directory Structure ns-allinone Tcl8.3 TK8.3 OTcl tclcl ns-2 nam-1 ... tcl C+ + code ex test mcast ... lib examples
2
Outline
Extending ns In OTcl In C++ Debugging
3
ns Directory Structure
TK8.3 OTcl tclcl Tcl8.3 ns-2 nam-1 tcl ex test lib
... ...
examples validation tests C+ + code OTcl code
ns-allinone mcast
4
Extending ns in OTcl
If you don’t want to compile source your changes in your sim
scripts
Otherwise Modifying code; recompile Adding new files
- Change Makefile (NS_TCL_LIB),
tcl/lib/ns-lib.tcl
- Recompile
5
Example: Agent/Message
n0 n1 n4 n5 n2 n3
128Kb, 50ms 10Mb, 1ms 10Mb, 1ms
C C
cross traffic
S R
msg agent
6
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
S S R R
pkt: 64 bytes
- f arbitrary
string Receiver-side processing
7
Agent/Message: Step 1
Define sender
class Sender class Sender – –superclass superclass Agent/Message Agent/Message
# Message format: “ # Message format: “Addr Addr Op Op SeqNo SeqNo” Sender Sender instproc instproc send send-next {} { next {} { $self $self instvar instvar seq seq_ _ agent_addr agent_addr_ $self send “$ $self send “$agent_addr agent_addr_ send $ _ send $seq seq_” _” incr incr seq seq_ global ns global ns $ns at [ $ns at [expr expr [$ns now]+0.1] "$self send [$ns now]+0.1] "$self send-next" next" }
8
Agent/Message: Step 2
Define sender packet processing
Sender Sender instproc instproc recv recv msg msg { { $self $self instvar instvar agent_addr agent_addr_ _ set set sdr sdr [ [lindex lindex $ $msg msg 0] 0] set set seq seq [ [lindex lindex $ $msg msg 2] 2] puts "Sender gets puts "Sender gets ack ack $ $seq seq from $ from $sdr sdr" " } }
9
Agent/Message: Step 3
Define receiver packet processing
Class Receiver Class Receiver – –superclass superclass Agent/Message Agent/Message Receiver Receiver instproc instproc recv recv msg msg { { $self $self instvar instvar agent_addr agent_addr_ _ set set sdr sdr [ [lindex lindex $ $msg msg 0] 0] set set seq seq [ [lindex lindex $ $msg msg 2] 2] puts “Receiver gets puts “Receiver gets seq seq $ $seq seq from $ from $sdr sdr” ” $self send “$ $self send “$addr addr_ _ ack ack $ $seq seq” ” } }
10
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 set fd fd [new “ [new “message.tr message.tr” w] ” w] $ns trace $ns trace-
- all $
all $fd fd
11
Agent/Message: Step 5
Topology
for {set i 0} {$i < 6} { for {set i 0} {$i < 6} {incr incr i} { i} { set set n($i n($i) [$ns node] ) [$ns node] } $ns duplex $ns duplex-link $n(0) $n(1) 128kb 50ms link $n(0) $n(1) 128kb 50ms DropTail DropTail $ns duplex $ns duplex-link $n(1) $n(4) 10Mb 1ms link $n(1) $n(4) 10Mb 1ms DropTail DropTail $ns duplex $ns duplex-link $n(1) $n(5) 10Mb 1ms link $n(1) $n(5) 10Mb 1ms DropTail DropTail $ns duplex $ns duplex-link $n(0) $n(2) 10Mb 1ms link $n(0) $n(2) 10Mb 1ms DropTail DropTail $ns duplex $ns duplex-link $n(0) $n(3) 10Mb 1ms link $n(0) $n(3) 10Mb 1ms DropTail DropTail $ns queue $ns queue-limit $n(0) $n(1) 5 limit $n(0) $n(1) 5 $ns queue $ns queue-limit $n(1) $n(0) 5 limit $n(1) $n(0) 5
12
Agent/Message: Step 6
Routing
# Packet loss produced by # Packet loss produced by queueing queueing # Routing protocol: let’s run distance # Routing protocol: let’s run distance vector vector $ns $ns rtproto rtproto DV DV
13
Agent/Message: Step 7
Cross traffic
set udp0 [new Agent/UDP] set udp0 [new Agent/UDP] $ns attach $ns attach-
- agent $n(2) $udp0
agent $n(2) $udp0 set null0 [new Agent/NULL] set null0 [new Agent/NULL] $ns attach $ns attach-
- agent $n(4) $null0
agent $n(4) $null0 $ns connect $udp0 $null0 $ns connect $udp0 $null0 set exp0 [new set exp0 [new Application/Traffic/Exponential] Application/Traffic/Exponential] $exp0 set rate_ 128k $exp0 set rate_ 128k $exp0 attach $exp0 attach-
- agent $udp0
agent $udp0 $ns at 1.0 “$exp0 start” $ns at 1.0 “$exp0 start”
14
Agent/Message: Step 8
Message agents set set sdr sdr [new Sender] [new Sender] $ $sdr sdr set set seq seq_ 0 _ 0 $ $sdr sdr set set packetSize packetSize_ 1000 _ 1000 set set rcvr rcvr [new Receiver] [new Receiver] $ $rcvr rcvr set set packetSize packetSize_ 40 _ 40 $ns attach $ns attach-
- agent $n(3) $
agent $n(3) $sdr sdr $ns attach $ns attach-
- agent $n(5) $
agent $n(5) $rcvr rcvr $ns connect $ $ns connect $sdr sdr $ $rcvr rcvr $ns at 1.1 “$ $ns at 1.1 “$sdr sdr send send-
- next”
next”
15
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 global ns fd fd $ns flush $ns flush-
- trace
trace close $ close $fd fd exit 0 exit 0 } } $ns run $ns run
16
Agent/Message: Result
Example output
> ./ns > ./ns msg.tcl msg.tcl Receiver gets Receiver gets seq seq 0 from 3 0 from 3 Sender gets Sender gets ack ack 0 from 5 0 from 5 Receiver gets Receiver gets seq seq 1 from 3 1 from 3 Sender gets Sender gets ack ack 1 from 5 1 from 5 Receiver gets Receiver gets seq seq 2 from 3 2 from 3 Sender gets Sender gets ack ack 2 from 5 2 from 5 Receiver gets Receiver gets seq seq 3 from 3 3 from 3 Sender gets Sender gets ack ack 3 from 5 3 from 5 Receiver gets Receiver gets seq seq 4 from 3 4 from 3 Sender gets Sender gets ack ack 4 from 5 4 from 5 Receiver gets Receiver gets seq seq 5 from 3 5 from 3
17
Add Your Changes into ns
TK8.3 OTcl tclcl Tcl8.3 ns-2 nam-1 tcl ex test lib
... ...
examples validation tests C+ + code OTcl code
ns-allinone mcast mysrc msg.tcl
18
Add Your Change into ns
tcl/lib/ns-lib.tcl
Class Simulator Class Simulator … … source ../ source ../mysrc/msg.tcl mysrc/msg.tcl
Makefile
NS_TCL_LIB = NS_TCL_LIB = \ \ tcl/mysrc/msg.tcl tcl/mysrc/msg.tcl \ \ … …
Or: change Makefile.in, make
make distclean distclean,
then ./configure
./configure --
- -enable
enable-
- debug ,
debug , make depend make depend and
and make
make
19
Outline
Extending ns In OTcl In C++
- New components
20
Extending ns in C++
Modifying code make depend Recompile Adding code in new files Change Makefile make depend recompile
21
Creating New Components
Guidelines Two styles New agent based on existing packet
headers
Add new packet header
22
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)
23
New Agent, Old Header
TCP jump start Wide-open transmission window at
the beginning
From cwnd
cwnd_ += 1 _ += 1 To cwnd cwnd_ = _ = MAXWIN_ MAXWIN_
24
TCP Jump Start – Step 1
TclObject NsObject Connector Classifier Delay AddrClassifier Agent McastClasifier Queue Trace DropTail RED TCP Enq Deq Drop Reno SACK
JS
Handler
25
TCP Jump Start – Step 2
New file: tcp-js.h class class JSTCPAgent JSTCPAgent : public : public TcpAgent TcpAgent { { public: public: virtual void virtual void set_initial_window set_initial_window() { () { cwnd cwnd_ = MAXWIN_; _ = MAXWIN_; } } private: private: int int MAXWIN_; MAXWIN_; }; };
26
TCP Jump Start – Step 3
New file: tcp-js.cc
static JSTcpClass : public TclClass { public: JSTcpClass() : TclClass("Agent/TCP/JS") {} TclObject* create(int, const char*const*) { return (new JSTcpAgent()); } }; JSTcpAgent::JSTcpAgent() { bind(“MAXWIN_”, MAXWIN_); }
27
Packet Format
header data ip header tcp header rtp header trace header cmn header ... ts_ ptype_ uid_ size_ iface_
28
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!
29
How Packet Header Works
Packet next_ hdrlen_ bits_
size determined at compile time size determined at compile time size determined at compile time …… hdr_cmn hdr_ip hdr_tcp size determined at simulator startup time
(PacketHeaderManager) PacketHeader/ Common PacketHeader/ I P PacketHeader/ TCP
30
Example: Agent/Message
New packet header for 64-byte
message
New transport agent to process this
new header
31
New Packet Header – Step 1
Create header structure
struct struct hdr_msg hdr_msg { { char msg_[64]; char msg_[64]; static static int int offset_;
- ffset_;
inline static inline static int int& offset() { return & offset() { return
- ffset_; }
- ffset_; }
inline static inline static hdr_msg hdr_msg* * access(Packet access(Packet* p) { * p) { return ( return (hdr_msg hdr_msg*) p *) p-
- >
>access(offset access(offset_); _); } } /* per /* per-
- field member functions */
field member functions */ char* char* msg msg() { return ( () { return (msg msg_); } _); } int int maxmsg maxmsg() { return ( () { return (sizeof(msg sizeof(msg_)); } _)); } }; };
32
New Packet Header – Step 2
PacketHeader/Message static class static class MessageHeaderClass MessageHeaderClass : : public public PacketHeaderClass PacketHeaderClass { { public: public: MessageHeaderClass MessageHeaderClass() : () : PacketHeaderClass("PacketHeader PacketHeaderClass("PacketHeader/Message /Message ", ", sizeof(hdr_msg sizeof(hdr_msg)) { )) { bind_offset(&hdr_msg::offset bind_offset(&hdr_msg::offset_); _); } } } } class_msghdr class_msghdr; ;
33
New Packet Header – Step 3
Enable tracing (packet.h): enum enum packet_t packet_t { { PT_TCP, PT_TCP, …, …, PT_MESSAGE, PT_MESSAGE, PT_NTYPE // This MUST be the LAST one PT_NTYPE // This MUST be the LAST one }; }; class class p_info p_info { { …… …… name_[PT_MESSAGE name_[PT_MESSAGE] = “message”; ] = “message”; name_[PT_NTYPE name_[PT_NTYPE]= "undefined"; ]= "undefined"; …… …… }; };
34
New Packet Header – Step 4
Register new header (tcl/lib/ns-
packet.tcl)
foreach foreach pair { pair { { Common { Common off_cmn
- ff_cmn_ }
_ } … … { Message { Message off_msg
- ff_msg_ }
_ } } }
35
Packet Header: Caution
Some old code, e.g.:
RtpAgent::RtpAgent RtpAgent::RtpAgent() { () { …… …… bind(“off_rtp bind(“off_rtp_”, & _”, &off_rtp
- ff_rtp);
); } } …… …… hdr_rtp hdr_rtp* * rh rh = ( = (hdr_rtp hdr_rtp*)p *)p-
- >
>access(off_rtp access(off_rtp_); _);
Don’t follow this example!
36
Agent/Message – Step 1
TclObject NsObject Connector Classifier Delay AddrClassifier Agent McastClasifier Queue Trace DropTail RED TCP Enq Deq Drop Reno SACK
Message
37
Agent/Message – Step 2
C++ class definition
// Standard split object declaration // Standard split object declaration static … static … class class MessageAgent MessageAgent : public Agent { : public Agent { public: public: MessageAgent MessageAgent() : () : Agent( Agent(PT_MESSAGE PT_MESSAGE) {} ) {} virtual virtual int int command(int command(int argc argc, const char*const* , const char*const* argv argv); ); virtual void virtual void recv(Packet recv(Packet*, Handler*); *, Handler*); }; };
38
Agent/Message – Step 3
Packet processing: send
int int MessageAgent::command(int MessageAgent::command(int, const char*const* , const char*const* argv argv) { Tcl Tcl& & tcl tcl = = Tcl::instance Tcl::instance(); (); if (strcmp(argv[1], "send") == 0) { if (strcmp(argv[1], "send") == 0) { Packet* Packet* pkt pkt = = allocpkt allocpkt(); (); hdr_msg hdr_msg* * mh mh = = hdr_msg::access(pkt hdr_msg::access(pkt); ); // We ignore message size check... // We ignore message size check... strcpy(mh strcpy(mh->msg msg(), argv[2]); (), argv[2]); send(pkt send(pkt, 0); , 0); return (TCL_OK); return (TCL_OK); } return ( return (Agent::command(argc Agent::command(argc, , argv argv)); )); }
39
Agent/Message – Step 4
Packet processing: receive void void MessageAgent::recv(Packet MessageAgent::recv(Packet* * pkt pkt, Handler*) , Handler*) { { hdr_msg hdr_msg* * mh mh = = hdr_msg::access(pkt hdr_msg::access(pkt); ); // // OTcl OTcl callback callback char wrk[128]; char wrk[128]; sprintf(wrk sprintf(wrk, "%s , "%s recv recv {%s}", name(), {%s}", name(), mh mh-
- >
>msg msg()); ()); Tcl Tcl& & tcl tcl = = Tcl::instance Tcl::instance(); (); tcl.eval(wrk tcl.eval(wrk); ); Packet::free(pkt Packet::free(pkt); ); } }
40
Outline
Extending ns In OTcl In C++ Debugging: OTcl/C++, memory Pitfalls
41
Debugging C++ in ns
C++/OTcl debugging Memory debugging purify dmalloc
42
C++/OTcl Debugging
Usual technique Break inside command() Cannot examine states inside OTcl! Solution Execute tcl-debug inside gdb
43
C++/OTcl Debugging
( (gdb gdb) ) call call Tcl::instance().eval(“debug Tcl::instance().eval(“debug 1”) 1”) 15: 15: lappend lappend auto_path auto_path $ $dbg_library dbg_library dbg15.3> w dbg15.3> w *0: application *0: application 15: 15: lappend lappend auto_path auto_path $ $dbg_library dbg_library dbg15.4> Simulator info instances dbg15.4> Simulator info instances _o1 _o1 dbg15.5> _o1 now dbg15.5> _o1 now dbg15.6> # and other fun stuff dbg15.6> # and other fun stuff dbg15.7> dbg15.7> c c ( (gdb gdb) where ) where #0 0x102218 in write() #0 0x102218 in write() ...... ......
44
Memory Debugging in ns
Purify Set PURIFY macro in ns Makefile Usually, put -colloctor=<ld_path> Gray Watson’s dmalloc library http://www.dmalloc.com make distclean ./configure --with-dmalloc=<dmalloc_path> Analyze results: dmalloc_summarize
45
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
46
Pitfalls
Scalability vs flexibility Or, how to write scalable simulation? Memory conservation tips Memory leaks
47
Scalability vs Flexibility
It’s tempting to write all-OTcl
simulation
Benefit: quick prototyping Cost: memory + runtime Solution Control the granularity of your split
- bject by migrating methods from
OTcl to C++
48
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
49
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
50
Memory Conservation Tips
Remove unused packet headers Avoid trace
trace-
- all
all
Use arrays for a sequence of variables Instead of n$i
n$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} See tips for running large sim in ns at
www.isi.edu/ns/nsnam/ns-largesim.html
51
Memory Leaks
Purify or dmalloc, but be careful about split
- bjects:
for {set i 0} {$i < 500} { for {set i 0} {$i < 500} {incr incr i} { i} { set a [new set a [new RandomVariable RandomVariable/Constant] /Constant] } }
It leaks memory, but can’t be detected! Solution Explicitly delete EVERY split object that was
new-ed
52
Final Word
My extended ns dumps OTcl scripts! Find the last 10-20 lines of the dump Is the error related to “_o*** cmd …” ?
- Check your command()
Otherwise, check the otcl script