Extending ns Extending ns In OTcl In C++ Debugging Padma Haldar - - PDF document

extending ns
SMART_READER_LITE
LIVE PREVIEW

Extending ns Extending ns In OTcl In C++ Debugging Padma Haldar - - PDF document

Outline Extending ns Extending ns In OTcl In C++ Debugging Padma Haldar USC/ISI 1 2 ns Directory Structure Extending ns in OTcl ns-allinone If you dont want to compile source your changes in your sim Tcl8.3 TK8.3


slide-1
SLIDE 1

1

1

Extending ns

Padma Haldar USC/ISI

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 R pkt: 64 bytes

  • f arbitrary

string Receiver-side processing

slide-2
SLIDE 2

2

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

slide-3
SLIDE 3

3

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

slide-4
SLIDE 4

4

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

slide-5
SLIDE 5

5

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

slide-6
SLIDE 6

6

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

slide-7
SLIDE 7

7

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

slide-8
SLIDE 8

8

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 (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

slide-9
SLIDE 9

9

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 simin 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

pointed by the error message