Agent/TCP - UET Taxila

Download Report

Transcript Agent/TCP - UET Taxila

LAB 5
Adding New Components
• High level scripting in otcl
• Linking otcl and C++
• Low level in C++
NS2Work
1
Adding New Component using
otcl
• Additional <new_stuff>.tcl file
• source <new_stuff>.tcl
• Adding new files
– change Makefile (NS_TCL_LIB), tcl/lib/nslib.tcl
– recompile
NS2Work
2
Example: Agent/Message
C
n2
cross
traffic
n0
128Kb, 50ms
10Mb, 1ms
S
n4
C
n5
R
n1
10Mb, 1ms
n3
msg agent
http://nslab.ee.ntu.edu.tw/courses/ns-tutorial/ftw-tutorial.html
NS2Work
3
Agent/Message
Receiver-side
processing
string message
S
•
•
•
•
R
A UDP agent (without UDP header)
Up to 64 bytes user message
Good for fast prototyping a simple idea
Usage requires extending ns functionality
NS2Work
4
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"
}
NS2Work
5
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"
}
NS2Work
6
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”
}
NS2Work
7
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
NS2Work
8
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
NS2Work
9
Agent/Message: Step 6
• Routing
# Packet loss produced by queueing
# Routing protocol: let’s run distance vector
$ns rtproto DV
NS2Work
10
Agent/Message: Step 7
• Cross traffic
set
$ns
set
$ns
$ns
udp0 [new Agent/UDP]
attach-agent $n(2) $udp0
null0 [new Agent/NULL]
attach-agent $n(4) $null0
connect $udp0 $null0
set exp0 [new Application/Traffic/Exponential]
$exp0 set rate_ 128k
$exp0 attach-agent $udp0
$ns at 1.0 “$exp0 start”
NS2Work
11
Agent/Message: Step 8
• Message agents
set sdr [new Sender]
$sdr set packetSize_ 1000
set rcvr [new Receiver]
$rcvr set packetSize_ 40
$ns
$ns
$ns
$ns
$ns
attach $n(3) $sdr
attach $n(5) $rcvr
connect $sdr $rcvr
connect $rcvr $sdr
at 1.1 “$sdr send-next”
NS2Work
12
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
}
NS2Work
13
Agent/Message: Result
• Example output
> ./ns msg.tcl
Receiver gets seq
Sender gets ack 0
Receiver gets seq
Sender gets ack 1
Receiver gets seq
Sender gets ack 2
Receiver gets seq
Sender gets ack 3
Receiver gets seq
Sender gets ack 4
Receiver gets seq
0 from
from 1
1 from
from 1
2 from
from 1
3 from
from 1
4 from
from 1
5 from
0
0
0
0
0
0
NS2Work
14
Add Your Change into ns
• tcl/lib/ns-lib.tcl
Class Simulator
…
source ../mysrc/msg.tcl
• Makefile
NS_TCL_LIB = \
tcl/mysrc/msg.tcl \
…
– Or: change Makefile.in, make distclean, then
./configure --enable-debug
NS2Work
15
Extending ns in C++
• Adding code in <new_stuff>.{cc,h} files
– Change Makefile
– make depend
– recompile
NS2Work
16
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
17
Class Hierarchy
TclObject
NsObject
Connector
Queue
Delay Agent
DropTail RED
TCP
Reno
Classifier
Trace
AddrClassifier McastClasifier
Enq Deq
Drop
SACK
NS2Work
18
C++/otcl Linkage
Root of ns-2 object hierarchy
TclObject
bind(): link variable values between
C++ and OTcl
command(): link OTcl methods to C++
implementations
TclClass
Tcl
Create and initialize TclObject’s
C++ methods to access Tcl interpreter
TclCommand Standalone global commands
EmbeddedTcl ns script initialization
NS2Work
19
TclObject: Hierarchy and Shadowing
C++ class
hierarchy
TclObject otcl class
hierarchy
TclObject
Agent
Agent
Agent/TCP
TcpAgent
_o123
*tcp
Agent/TCP otcl
shadow object
Agent/TCP C++
object
NS2Work
20
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
NS2Work
21
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
NS2Work
22
TclObject::command()
• Implement otcl methods in C++
• Trap point: otcl method cmd{}
• Send all arguments after cmd{} call to
TclObject::command()
NS2Work
23
TclObject::command()
$tcp send
OTcl space
no such
procedure
TclObject::unknown{}
$tcp cmd send
C++ space
TcpAgent::command()
Yes
match
“send”?
No
Invoke parent:
return Agent::command()
process and return
NS2Work
24
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);
}
NS2Work
25
TclClass
C++
TclObject
NsObject
Agent
TcpAgent
mirroring
OTcl
Static
class TcpClass
: public TclClass {
public:
TclObject
TcpClass()
: TclClass(“Agent/TCP”) {}
TclObject* create(int, const char*const*) {
return (new TcpAgent());
??
}
} class_tcp;
Agent
Agent/TCP
NS2Work
26
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
27
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
28
Creating New Components
• new agent, no headers
• new agent, new packet header
NS2Work
29
DtopTail Round Robin (DTRR) –
Step 1
TclObject
NsObject
Connector
Queue
Delay Agent
DropTail RED
DTRR
TCP
Reno
Classifier
Trace
AddrClassifier McastClasifier
Enq Deq
Drop
SACK
NS2Work
30
Adding New Queue (DropTail
Round Robin) using C++
//dtrr-queue.h
class DtRrQueue : public Queue {
public:
DtRrQueue() {
q1_ = new PacketQueue;
q2_ = new PacketQueue;
pq_ = q1_;
deq_turn_ = 1;
}
protected:
void enque(Packet*);
Packet* deque();
PacketQueue *q1_;
PacketQueue *q2_;
int deq_turn_;
// First FIFO queue
// Second FIFO queue
// 1 for First queue 2 for Second
};
NS2Work
31
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
32
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
33
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/nspacket.tcl)
• This does not apply when you add a new
field into an existing header!
NS2Work
34
How Packet Header Works
Packet
PacketHeader/Common
next_
hdrlen_
bits_
size determined
at simulator
startup time
(PacketHeaderManager)
size determined
hdr_cmn
at compile time PacketHeader/IP
size determined
at compile time
size determined
at compile time
……
NS2Work
hdr_ip
PacketHeader/TCP
hdr_tcp
35
EMUR Header – Step 1
//emur_pkt.h
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
36
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_);
}
NS2Work
} class_rtEMUR_hdr;
37
EMUR Header – Step 3
• Enable tracing (packet.h):
enum packet_t {
PT_TCP,
…,
PT_EMUR,
PT_NTYPE // This MUST be the LAST one
};
class p_info {
……
name_[PT_EMUR] = “EMUR”;
name_[PT_NTYPE]= "undefined";
……
};
NS2Work
38
EMUR Timer – Step 1
//emur.h
class 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
39
EMUR Class – Step 2
//emur.h
class 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
40
};
EMUR Binding – Step 3
//Emur/Emur.cc
static 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().str2add
r(argv[4])));
}
} class_rtEmur;
NS2Work
41
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
42
EMUR
Command
–
Step
5
Int 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 layers
if (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
43
Emur Packet Receive – Step 6
Void 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 header
else if (ch->num_forwards() == 0)
ch->size() += IP_HDR_LEN;
}
// If it is a Emur packet, must process it
if (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;
NS2Work
44
}
Emur Send Packet – Step - 7
Void 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
45
Emur Scheduling Packets –
Step 8
void Emur_PktTimer::expire(Event* e) {
agent_->send_emur_pkt();
resched((double)5.0);
}
NS2Work
46
Emur Tracing – Step 9
//trace/cmu-trace.h
trace/cmu-trace.h
class 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
}
47
Add Method to TCL library –
Step 10
//tcl/lib/ns-lib.tcl
Simulator instproc create-Emur-agent {
node } {
# Create Emur routing agent
set ragent [new Agent/Emur [$node nodeaddr]]
$self at 0.0 "$ragent start"
$node set ragent_ $ragent
return $ragent
}
NS2Work
48
EMUR Final Step
• Change Makefile.in to add your source
files
• Run Configure
• Run make
NS2Work
49
Summary
• Internals of NS2
• How to add new component in ns2
– Queue
– Routing
NS2Work
50