ns2work1 lab 5 adding new components high level scripting in otcl linking otcl and c++ low level in...

50
NS2Work 1 LAB 5 Adding New Components • High level scripting in otcl • Linking otcl and C++ • Low level in C++

Upload: jessica-bell

Post on 13-Dec-2015

224 views

Category:

Documents


2 download

TRANSCRIPT

NS2Work 1

LAB 5

Adding New Components

• High level scripting in otcl

• Linking otcl and C++

• Low level in C++

NS2Work 2

Adding New Component using otcl

• Additional <new_stuff>.tcl file

• source <new_stuff>.tcl

• Adding new files– change Makefile (NS_TCL_LIB), tcl/lib/ns-

lib.tcl– recompile

NS2Work 3

Example: Agent/Message

n0 n1

n4

n5

n2

n3

128Kb, 50ms

10Mb, 1ms 10Mb, 1ms

C Ccrosstraffic

S R

msg agent

http://nslab.ee.ntu.edu.tw/courses/ns-tutorial/ftw-tutorial.html

NS2Work 4

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

string messageReceiver-sideprocessing

NS2Work 5

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"

}}

NS2Work 6

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"

}}

NS2Work 7

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”

}}

NS2Work 8

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

NS2Work 9

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

NS2Work 10

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

NS2Work 11

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”

NS2Work 12

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”

NS2Work 13

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

}}

NS2Work 14

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

NS2Work 15

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

NS2Work 16

Extending ns in C++

• Adding code in <new_stuff>.{cc,h} files– Change Makefile– make depend– recompile

NS2Work 17

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

• Write otcl code (if required)

• Build

NS2Work 18

Class Hierarchy

TclObject

NsObject

Connector Classifier

Delay AddrClassifierAgent McastClasifierQueue Trace

DropTail RED TCP Enq Deq Drop

Reno SACK

NS2Work 19

C++/otcl Linkage

Root 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

NS2Work 20

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

NS2Work 21

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

NS2Work 22

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

NS2Work 23

TclObject::command()

• Implement otcl methods in C++

• Trap point: otcl method cmd{}

• Send all arguments after cmd{} call to TclObject::command()

NS2Work 24

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

NS2Work 25

TclObject::command()

• otclset 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);}

NS2Work 26

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;

NS2Work 27

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

NS2Work 28

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;

}

NS2Work 29

Creating New Components

• new agent, no headers

• new agent, new packet header

NS2Work 30

DtopTail Round Robin (DTRR) – Step 1TclObject

NsObject

Connector Classifier

Delay AddrClassifierAgent McastClasifierQueue Trace

DropTail RED TCP Enq Deq Drop

Reno SACKDTRR

NS2Work 31

Adding New Queue (DropTail Round Robin) using C++

//dtrr-queue.hclass DtRrQueue : public Queue { public: DtRrQueue() {

q1_ = new PacketQueue;q2_ = new PacketQueue;pq_ = q1_;deq_turn_ = 1;

} protected: void enque(Packet*);

Packet* deque();

PacketQueue *q1_; // First FIFO queue PacketQueue *q2_; // Second FIFO queue int deq_turn_; // 1 for First queue 2 for Second

};

NS2Work 32

Creating Object//dtrr-queue.cc#include "dtrr-queue.h"static class DtRrQueueClass : public TclClass {public: DtRrQueueClass() : TclClass("Queue/DTRR") {} TclObject* create(int, const char*const*) {

return (new DtRrQueue);}

} class_dropt_tail_round_robin;

void DtRrQueue::enque(Packet* p) { …}Packet* DtRrQueue::deque(){…}

NS2Work 33

New Agent, New Header for Example MANET Unicast Routing

(EMUR)• Example: Agent/Message

– New packet header for 64-byte message– New transport agent to process this new

header

NS2Work 34

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!

NS2Work 35

How Packet Header Works

Packet

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

NS2Work 36

EMUR Header – Step 1//emur_pkt.hstruct hdr_emur_pkt {struct hdr_emur_pkt {

nsaddr_t pkt_src_; // Node which originated this packet

u_int16_t pkt_len_; // Packet length (in bytes)

u_int8_t pkt_seq_num_; // Packet sequence number

inline nsaddr_t& pkt_src() { return pkt_src_; }

inline u_int16_t& pkt_len() { return pkt_len_; }

inline u_int8_t& pkt_seq_num() { return pkt_seq_num_; }

static int offset_;

inline static int& offset() { return offset_; }

inline static hdr_emur_pkt* access(const Packet* p) {

return (hdr_emur_pkt*)p->access(offset_);

}

};};

#define HDR_EMUR_PKT(p) hdr_emur_pkt::access(p)

NS2Work 37

EMUR Header – Step 2

//emur.cc

#include <emur_pkt.h>

int Emur_pkt::offset_;

static class EmurHeaderClass : public HeaderClass {

public:

EmurHeaderClass() : PacketHeaderClass("PacketHeader/EMUR",

sizeof(hdr_emur_pkt)) {

bind_offset(&hdr_emur_pkt::offset_);

}

} class_rtEMUR_hdr;

NS2Work 38

EMUR Header – Step 3

• Enable tracing (packet.h):enum packet_t {enum packet_t {

PT_TCP,PT_TCP,……,,PT_EMUR,PT_EMUR,PT_NTYPE // This MUST be the LAST onePT_NTYPE // This MUST be the LAST one

};};class p_info {class p_info {

…………name_[PT_EMUR] = “EMUR”;name_[PT_EMUR] = “EMUR”;name_[PT_NTYPE]= "undefined";name_[PT_NTYPE]= "undefined";

…………};};

NS2Work 39

EMUR Timer – Step 1//emur.hclass Emur; // forward declaration/* Timers */class Emur_PktTimer : public TimerHandler {public:Emur_PktTimer(Emur* agent) : TimerHandler() {

agent_ = agent;}protected:Emur* agent_;virtual void expire(Event* e); };

NS2Work 40

EMUR Class – Step 2//emur.hclass Emur : public Agent {/* Friends */friend class Emur_PktTimer;

/* Private members */…Emur_PktTimer pkt_timer_; // Timer for sending packets.

public:Emur(nsaddr_t);int command(int, const char*const*);void recv(Packet*, Handler*);

};

NS2Work 41

EMUR Binding – Step 3

//Emur/Emur.ccstatic class EmurClass : public TclClass {public:EmurClass() : TclClass("Agent/EMUR") {}TclObject* create(int argc, const char*const* argv) {assert(argc == 5);return (new Emur((nsaddr_t)Address::instance().str2addr(argv[4])));}

} class_rtEmur;

NS2Work 42

EMUR Constructor – Step 4

//Emur/Emur.cc

Emur::Emur(nsaddr_t id) : Agent(PT_EMUR), pkt_timer_(this) {

bind(“tcl_var_", &cc_var_);

ra_addr_ = id;

}

In Simulation script

Agent/Emur set tcl_var_ 100

NS2Work 43

EMUR Command – Step 5Int Emur::command(int argc, const char*const* argv) {

if (argc == 2) {if (strcasecmp(argv[1], "start") == 0) {Start(); //pkt_timer_.resched(0.0);return TCL_OK;}else if (strcasecmp(argv[1], “some_other_func") == 0) {…}}else if (argc == 3) {// Obtains corresponding dmux to carry packets to upper layersif (strcmp(argv[1], “some_var") == 0) {loc_var_ = atoi (strcmp(argv[2])return TCL_OK;}…

// Pass the command to the base class return Agent::command(argc, argv);}

NS2Work 44

Emur Packet Receive – Step 6Void Emur::recv(Packet* p, Handler* h) {struct hdr_cmn* ch = HDR_CMN(p);struct hdr_ip* ih = HDR_IP(p);if (ih->saddr() == ra_addr()) { // If there exists a loop, must drop the packet if (ch->num_forwards() > 0) { drop(p, DROP_RTR_ROUTE_LOOP);return;}// else if this is a packet I am originating, must add IP headerelse if (ch->num_forwards() == 0)ch->size() += IP_HDR_LEN;}// If it is a Emur packet, must process itif (ch->ptype() == PT_EMUR)recv_emur_pkt(p);// Otherwise, must forward the packet (unless TTL has reached zero)else {

ih->ttl_--;if (ih->ttl_ == 0) {drop(p, DROP_RTR_TTL);return;

}forward_data(p);}

NS2Work 45

Emur Send Packet – Step - 7Void Emur::send_emur_pkt() {

Packet* p = allocpkt();struct hdr_cmn* ch = HDR_CMN(p);struct hdr_ip* ih = HDR_IP(p);struct hdr_Emur_pkt* ph = HDR_Emur_PKT(p);ph->pkt_src() = ra_addr();ph->pkt_len() = 7;ph->pkt_seq_num() = seq_num_++;ch->ptype() = PT_Emur;ch->direction() = hdr_cmn::DOWN;ch->size() = IP_HDR_LEN + ph->pkt_len();ch->error() = 0;ch->next_hop() = IP_BROADCAST;ch->addr_type() = NS_AF_INET;ih->saddr() = ra_addr();ih->daddr() = IP_BROADCAST;ih->sport() = RT_PORT;ih->dport() = RT_PORT;ih->ttl() = IP_DEF_TTL;Scheduler::instance().schedule(target_, p, JITTER);

}

NS2Work 46

Emur Scheduling Packets – Step 8

void Emur_PktTimer::expire(Event* e) {

agent_->send_emur_pkt();

resched((double)5.0);

}

NS2Work 47

Emur Tracing – Step 9//trace/cmu-trace.htrace/cmu-trace.hclass CMUTrace : public Trace {/* ... definitions ... */private:/* ... */void format_aodv(Packet *p, int offset);void format_emur(Packet *p, int offset);};//trace/cmu-trace.cc

Void CMUTrace::format_emur(Packet *p, int offset){struct hdr_emur_pkt* ph = HDR_EMUR_PKT(p);…}

NS2Work 48

Add Method to TCL library – Step 10

//tcl/lib/ns-lib.tclSimulator instproc create-Emur-agent { node } {

# Create Emur routing agentset ragent [new Agent/Emur [$node node-addr]]

$self at 0.0 "$ragent start"$node set ragent_ $ragentreturn $ragent}

NS2Work 49

EMUR Final Step

• Change Makefile.in to add your source files

• Run Configure

• Run make

NS2Work 50

Summary

• Internals of NS2

• How to add new component in ns2– Queue– Routing