1 2nd European ns-2 Workshop Day 2 Polly Huang ETH Zurich 18 & 19 April
2 Schedule: Yesterday overview/intro/essential/getting started tcl/otcl/ns-2 fundamentals examples - TCP, RED, multicast, web, wireless Lunch break lab 1 setup/running examples lab 2 tcl/otcl exercises lab 3 simple ns-2 exercise discussion/feedback
3 Schedule: Today recap/wired internal wireless internal/making changes extending ns-2/case studies Lunch break lab 4 intermediate ns-2 exercise lab 5 getting data you want lab 6 advanced topic (TBD) discussion/feedback
4 tcl Interpreter With Extensions tcl8.0 otcl tclcl ns-2 Event Scheduler Network Component
5 Example Script set ns [new Simulator] set n0 [$ns node] set n1 [$ns node] n0n1 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 DropTail set 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 n0n1 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 n0n1 enqT_queue_deqT_ drophead_drpT_ link_ttl_ n1 entry_ head_
13 Routing n0n1 Addr Classifier Port Classifier classifier_ dmux_ entry_ Node entry 0 1 enqT_queue_deqT_ drophead_drpT_ link_ttl_ n1 entry_ head_
14 Routing (cont.) n0n1 Addr Classifier Port Classifier classifier_ dmux_ entry_ 0 1 Addr Classifier Port Classifier classifier_ dmux_ entry_ 1 0 Link n0-n1 Link n1-n0
Transport n0n1 Addr Classifier Port Classifier classifier_ dmux_ entry_ 0 Agent/TCP agents_ Addr Classifier Port Classifier classifier_ dmux_ entry_ 1 0 Link n0-n1 Link n1-n0 0 Agent/TCPSink agents_ dst_addr_=1 dst_port_=0 dst_addr_=0 dst_port_=0
16 Application 0 1 n0n1 Addr Classifier Port Classifier classifier_ dmux_ entry_ 0 Agent/TCP agents_ Addr Classifier Port Classifier classifier_ dmux_ entry_ 1 0 Link n0-n1 Link n1-n0 0 Agent/TCPSink agents_ Application/FTP dst_addr_=1 dst_port_=0 dst_addr_=0 dst_port_=0
17 Packet Flow 0 1 n0n1 Addr Classifier Port Classifier entry_ 0 Agent/TCP Addr Classifier Port Classifier entry_ 1 0 Link n0-n1 Link n1-n0 0 Agent/TCPSink Application/FTP dst_addr_=1 dst_port_=0 dst_addr_=0 dst_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_ ARP wireless headers
21 Portrait of A Mobile Node Node ARP Propagation and antenna models MobileNode LL MAC PHY LL CHANNEL LL MAC PHY Classifier: Forwarding Agent: Protocol Entity Node Entry LL: Link layer object IFQ: Interface queue MAC: Mac object PHY: Net interface protocol agent routing agent addr classifier port classifier 255 IFQ 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 –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/r 2 ) at near distance –Two-ray Ground (1/r 4 ) 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(N 2 ) 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.tcl file source.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 CC cross traffic SR 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 SR pkt: 64 bytes of arbitrary string Receiver-side processing
32 Agent/Message: Step 1 Define sender class Sender –superclass Agent/Message # Message format: “Addr Op SeqNo” Sender instproc send-next {} { $self instvar seq_ agent_addr_ $self send “$agent_addr_ send $seq_” incr seq_ global ns $ns at [expr [$ns now]+0.1] "$self send-next" }
33 Agent/Message: Step 2 Define sender packet processing Sender instproc recv msg { $self instvar agent_addr_ set sdr [lindex $msg 0] set seq [lindex $msg 2] puts "Sender gets ack $seq from $sdr" }
34 Agent/Message: Step 3 Define receiver packet processing Class Receiver –superclass Agent/Message Receiver instproc recv msg { $self instvar agent_addr_ set sdr [lindex $msg 0] set seq [lindex $msg 2] puts “Receiver gets seq $seq from $sdr” $self send “$addr_ ack $seq” }
35 Agent/Message: Step 4 Scheduler and tracing # Create scheduler set ns [new Simulator] # Turn on Tracing set fd [new “message.nam” w] $ns namtrace-all $fd
36 Agent/Message: Step 5 Topology for {set i 0} {$i < 6} {incr i} { set n($i) [$ns node] } $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(5) 10Mb 1ms DropTail $ns duplex-link $n(0) $n(2) 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(1) $n(0) 5
37 Agent/Message: Step 6 Routing # Packet loss produced by queueing # Routing protocol: let’s run distance vector $ns rtproto DV
38 Agent/Message: Step 7 Cross traffic set udp0 [new Agent/UDP] $ns attach-agent $n(2) $udp0 set null0 [new Agent/NULL] $ns attach-agent $n(4) $null0 $ns connect $udp0 $null0 set exp0 [new Application/Traffic/Exponential] $exp0 set rate_ 128k $exp0 attach-agent $udp0 $ns at 1.0 “$exp0 start”
39 Agent/Message: Step 8 Message agents set sdr [new Sender] $sdr set packetSize_ 1000 set rcvr [new Receiver] $rcvr set packetSize_ 40 $ns attach $n(3) $sdr $ns attach $n(5) $rcvr $ns connect $sdr $rcvr $ns connect $rcvr $sdr $ns at 1.1 “$sdr send-next”
40 Agent/Message: Step 9 End-of-simulation wrapper (as usual) $ns at 2.0 finish proc finish {} { global ns fd $ns flush-trace close $fd exit 0 }
41 Agent/Message: Result Example output >./ns msg.tcl Receiver gets seq 0 from 0 Sender gets ack 0 from 1 Receiver gets seq 1 from 0 Sender gets ack 1 from 1 Receiver gets seq 2 from 0 Sender gets ack 2 from 1 Receiver gets seq 3 from 0 Sender gets ack 3 from 1 Receiver gets seq 4 from 0 Sender gets ack 4 from 1 Receiver gets seq 5 from 0
42 Add Your Changes into ns TK8.0OTcltclclTcl8.0ns-2nam-1 tcl extest lib... examples validation tests C++ code OTcl code ns-allinone mcast mysrc msg.tcl
43 Add Your Change into ns tcl/lib/ns-lib.tcl Class Simulator … source../mysrc/msg.tcl Makefile NS_TCL_LIB = \ tcl/mysrc/msg.tcl \ … make distclean./configure --enable-debug –Or: change Makefile.in, make distclean, then./configure --enable-debug
44 Extending ns in C++ Adding code in.{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 Hierarchy TclObject NsObject Connector Classifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCPEnqDeqDrop RenoSACK
48 otcl and C++: The Duality C++ OTcl Pure C++ objects Pure OTcl objects C++/OTcl split objects ns
49 C++/otcl Linkage
50 TclObject Basic hierarchy in ns for split objects Mirrored in both C++ and otcl Example set tcp [new Agent/TCP] $tcp set packetSize_ 1024 $tcp advanceby 5000
51 TclObject: Hierarchy and Shadowing TclObject Agent Agent/TCP Agent/TCP otcl shadow object _o123 Agent/TCP C++ object *tcp TclObject Agent TcpAgent otcl class hierarchy C++ class hierarchy
52 TclObject::bind() Link C++ member variables to otcl object variables C++ TcpAgent::TcpAgent() { bind(“window_”, &wnd_); … } –bind_time(), bind_bool(), bind_bw() otcl set tcp [new Agent/TCP] $tcp set window_ 200
53 Initialization of Bound Variables Initialization through otcl class variables Agent/TCP set window_ 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 Tcl_TraceVar() –Enable trap read/write to otcl variable using 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 send no such procedure 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{} Example set tcp [new Agent/TCP] … delete $tcp
59 C++ OTcl TclObject: Creation and Deletion invoke parent constructor Agent/TCP constructor parent constructor invoke parent constructor TclObject constructor create C++ object AgentTCP constructor invoke parent constructor invoke parent constructor parent (Agent) constructor do nothing, return TclObject (C++) constructor bind variables and return bind variables and return create OTcl shadow object complete initialization complete initialization which C++ object to create? – TclClass
60 TclClass TclObject Agent Agent/TCP TclObject Agent TcpAgent NsObject ?? OTcl C++ mirroring Static 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 statically defined 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 ~ns/tcl/lib/ns-lib.tcl: –Recursively load ~ns/tcl/lib/ns-lib.tcl: source ns-autoconf.tcl source ns-address.tcl source ns-node.tcl –Load everything into a single C++ string –Execute this string at runtime startup ~tclcl/tcl-object.tclTcl::init(): load ~tclcl/tcl-object.tcl ~ns/tcl/lib/ns-lib.tclTcl_AppInit(): load ~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- lib.tcl | tcl2c++ et_ns_lib > gen/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 cwnd_ += 1cwnd_ = MAXWIN_ –From cwnd_ += 1 To cwnd_ = MAXWIN_
70 TCP Jump Start – Step 1 TclObject NsObject Connector Classifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCPEnqDeqDrop RenoSACK JS
71 TCP Jump Start – Step 2 New file: tcp-js.h class JSTCPAgent : public TcpAgent { public: virtual void set_initial_window() { cwnd_ = MAXWIN_; }private: int MAXWIN_; };
72 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_); }
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 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/IP PacketHeader/TCP
76 New Packet Header – Step 1 Create header structure struct hdr_msg { char msg_[64]; static int offset_; inline static int& offset() { return offset_; } inline static hdr_msg* access(Packet* p) { return (hdr_msg*) p->access(offset_); } /* per-field member functions */ char* msg() { return (msg_); } int maxmsg() { return (sizeof(msg_)); } };
77 New Packet Header – Step 2 PacketHeader/Message static class MessageHeaderClass : public PacketHeaderClass { public: MessageHeaderClass() : PacketHeaderClass("PacketHeader/Message", sizeof(hdr_msg)) { sizeof(hdr_msg)) {bind_offset(&hdr_msg::offset_);} } class_msghdr;
78 New Packet Header – Step 3 Enable tracing (packet.h): enum packet_t { PT_TCP,…,PT_MESSAGE, PT_NTYPE // This MUST be the LAST one }; class p_info { …… name_[PT_MESSAGE] = “message”; name_[PT_NTYPE]= "undefined"; ……};
79 New Packet Header – Step 4 Register new header (tcl/lib/ns-packet.tcl) foreach pair { { Common off_cmn_ } … { Message off_msg_ } }
80 Packet Header: Caution Some old code, e.g.: RtpAgent::RtpAgent() { …… bind(“off_rtp_”, &off_rtp); }…… hdr_rtp* rh = (hdr_rtp*)p->access(off_rtp_); Don’t follow this example!
81 Agent/Message – Step 1 TclObject NsObject Connector Classifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCP EnqDeqDrop RenoSACK Message
82 Agent/Message – Step 2 C++ class definition // Standard split object declaration static … class MessageAgent : public Agent { public: MessageAgent() : Agent(PT_MESSAGE) {} virtual int command(int argc, const char*const* argv); virtual void recv(Packet*, Handler*); };
83 Agent/Message – Step 3 Packet processing: send int MessageAgent::command(int, const char*const* argv) { Tcl& tcl = Tcl::instance(); if (strcmp(argv[1], "send") == 0) { Packet* pkt = allocpkt(); hdr_msg* mh = hdr_msg::access(pkt); // We ignore message size check... strcpy(mh->msg(), argv[2]); send(pkt, 0); return (TCL_OK); } return (Agent::command(argc, argv)); }
84 Agent/Message – Step 4 Packet processing: receive void MessageAgent::recv(Packet* pkt, Handler*) { hdr_msg* mh = hdr_msg::access(pkt); // OTcl callback char wrk[128]; sprintf(wrk, "%s recv {%s}", name(), mh->msg()); Tcl& tcl = Tcl::instance(); tcl.eval(wrk);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 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 – –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) call Tcl::instance().eval(“debug 1”) 15: lappend auto_path $dbg_library dbg15.3> w *0: application 15: lappend auto_path $dbg_library 15: lappend auto_path $dbg_library dbg15.4> Simulator info instances _o1 dbg15.5> _o1 now 0 dbg15.6> # and other fun stuff dbg15.7> c (gdb) where #0 0x in write()......
90 Memory Debugging in ns Purify Gray Watson’s dmalloc library – –make distclean –./configure --with-dmalloc= –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} { set a [new RandomVariable/Constant] } –It leaks memory, but can’t be detected! Solution –Explicitly delete EVERY split object that was new-ed
93 Memory Conservation Tips trace-allAvoid trace-all Use arrays for a sequence of variables n$in($i) –Instead of n$i, say n($i) Avoid OTcl temporary variables Use dynamic binding –delay_bind()bind() –delay_bind() instead of 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 n0n1n2 NetworkInterface ANetworkInterface B
100 Class Hierarchy TclObject NsObject ConnectorClassifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCPEnqDnqDrop RenoSACK 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 NetworkInterfacenetworkinterface 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 ConnectorClassifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCPEnqDnqDrop RenoSACK JS
104 TCP Jump Start class JSTcpAgent –openwin() –slowdown() TclClass(“Agent/TCP/JS”)
105 Case 3: Application Layer Message sender (ping) n0n1n2 Message Sender
106 Class Hierarchy TclObject NsObject ConnectorClassifier DelayAddrClassifierAgentMcastClasifierQueueTrace DropTailREDTCPEnqDnqDrop RenoSACK 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