| Este Howto foi criado durante a implementação do LAR e contem trechos que não estão na documentação oficial, ou seja foram testados experimentalmente e podem mudar. | |
| Por enquanto todos os nodos estão se comunicando apenas por flooding. O algoritmo em si ainda não foi implementado, mas esta carcaça pode ser usada para implementar outros algoritmos. | |
| Os arquivos referentes ao ns serão referenciados como ns/*, e os arquivos do código do LAR serão referenciados como lar/*. | |
| Sempre que for
necessário indicar a inclusão de
uma linha de código em um arquivo existente, a linha a ser inserida será indicada por setas ( -> ), e o resto do
código será indicada para
contexto.
|
Na enumeração:
enum packet_t {
PT_TCP,
PT_UDP,
PT_CBR,
...
-> PT_LAR, <-
PT_NTYPE // This MUST be the LAST one
};
Inclua linha indicada, para definir um novo tipo de pacote.
E logo abaixo:
class p_info {
public:
p_info() {
name_[PT_TCP]= "tcp";
name_[PT_UDP]= "udp";
name_[PT_CBR]= "cbr";
...
-> name_[PT_LAR]="LAR"; <-
name_[PT_NTYPE]= "undefined";
foreach pair {
{ Common off_cmn_ }
{ Mac off_mac_ }
{ Mac802_11 off_mac802_11_ }
...
{ Ping off_ping_}
-> { LAR off_lar_} <-
} {
...
Estas duas modificações são necessárias para o NS reconhecer
o formato
do pacote do LAR.
Simulator instproc create-wireless-node { args
} {
...
switch -exact $routingAgent_ {
...
-> LAR {
-> set ragent [$self create-lar-agent
$node]
-> }
...
}
-> Simulator instproc create-lar-agent { node
} {
->
-> # Create a dsdv routing agent for this node
->
-> set ragent [new Agent/LAR]
->
-> ## setup address (supports hier-addr) for lar
agent
-> ## and mobilenode
-> set addr [$node node-addr]
->
-> $ragent addr $addr
-> $ragent node $node
->
-> if [Simulator set mobile_ip_] {
-> $ragent port-dmux [$node set dmux_]
-> }
-> $node addr $addr
-> $node set ragent_ $ragent
->
-> #delay till after add interface
->
-> $self at 0.0 "$ragent start-lar" ;# start updates
->
-> return $ragent
-> }
Para isto, inclua no arquivo ns/Makefile:
OBJ_CC = \
random.o rng.o ranvar.o misc.o timer-handler.o
\
scheduler.o object.o \
packet.o ip.o route.o connector.o ttl.o
\
...
-> /home/ns/lar/lar.o /home/ns/lar/lar_routing_table.o
<-
Onde está ultima linha contem os arquivos objetos do código.
Obs: O Makefile do ns ira automaticamente compilar os
arquivos
fontes indicados acima. Digamos que no Makefile esteja:
OBJ_CC = teste1.o ...
O Makefile ira' tentar compilar o arquivo teste1.cc para
gerar o arquivo objeto teste1.o.
lar_routing_table.cc implementa uma tabela de roteamento
com procura por funcao HASH, e com os campos de endereco, rota e distancia.
Ja' em lar.cc e lar.h o bicho pega. E' aqui que esta'
quase todo o código do algoritmo de roteamento. Vamos descrever então estes arquivos.
static class LarHeaderClass : public PacketHeaderClass
{
public:
LarHeaderClass() : PacketHeaderClass("PacketHeader/LAR",
MAX3(sizeof(hdr_lar_route_request),
sizeof(hdr_lar_route_response),
sizeof(hdr_lar_data)) ) {}
} class_larhdr;
static class LarClass : public TclClass {
public:
LarClass() : TclClass("Agent/LAR") {}
TclObject* create(int, const char*const*)
{
return (new LarAgent());
}
} class_lar;
LarAgent::LarAgent() : Agent(PT_LAR), ll_queue (0),
seqno_ (0),
myaddr_ (0), subnet_ (0), node_ (0), port_dmux_(0),
periodic_callback_ (0), be_random_ (1),
use_mac_ (0), verbose_ (1), trace_wst_ (0),
lasttup_ (-10)
{
bind("off_lar_", &off_lar_);
}
A função bind associa a propriedade da classe
off_lar_, com a variavel em OTcl off_lar_.
e' necessário para que a nova classe possa aceitar comandas
do OTcl.
e' talvez um dos mais importantes.
Ele recebe, tanto da camada superior, quanto da camada
inferior, os pacotes destinados ao novo e originados do nodo.
O roteamento em si' e' realizado aqui. Baseado nas informações
do cabeçalho, este método deve decidir
se vai retransmitir ou nao o pacote.
A função
static void mac_callback (Packet * p, void *arg);
e' chamada quando ha' um erro de transmissão detectada
pela camada de enlace.
Para ativar a função callback devemos definir no cabeçalho padrão
de cada pacote que iremos enviar:
cmh->xmit_failure_ = mac_callback;
cmh->xmit_failure_data_ = this;
A primeira linha define a função mac_callback como a função
a ser chamada na ocorrência de erro.
A segunda linha passa como argumento a instancia da classe
LarAgent, ou seja, o nodo que originou o pacote.
Desta forma, quando a função mac_callback e' chamada
e' possível saber que nodo originou o pacote.
// update old_rte in routing table to to new_rte
Trace *tracetarget;
// Trace Target
PriQueue *ll_queue;
// link level output queue
int seqno_;
// Sequence number to advertise with...
int myaddr_;
// My address...
// Extensions for mixed type simulations using wired and
wireless
// nodes
char *subnet_;
// My subnet
MobileNode *node_;
// My node
// for debugging
char *address;
NsObject *port_dmux_; // my port dmux
Event *periodic_callback_; // notify for periodic update
// Randomness/MAC/logging parameters
int be_random_;
int use_mac_;
int verbose_;
int trace_wst_;
// last time a periodic update was sent...
double lasttup_; // time of last triggered update
double next_tup; // time of next triggered update
// Event *trigupd_scheduled; // event marking a scheduled
triggered update
...
void startUp(void);
};
Observe que vários métodos e propriedades são obrigatórios para
que o agente funcione corretamente como um protocolo de roteamento adhoc.
ou
cmh->next_hop_ = IP_BROADCAST;
...
cmh->addr_type_ = NS_AF_INET;
cmh->xmit_failure_ = mac_callback;
cmh->xmit_failure_data_ = this;
cmh->direction() = hdr_cmn::DOWN;
assert (!cmh->xmit_failure_ || cmh->xmit_failure_ == mac_callback);
s.schedule(target_, pkt, 0.0 /*Random::uniform(0.01)*/);
Lembre-se que nem o cabeçalho IP nem o cabeçalho do LAR foram
preenchidos. Este código apenas ressalta alguns pontos importantes.
A ultima linha realiza a transmissão do pacote. O ultimo argumento
especifica em daqui a quanto tempo o pacote devera' ser transmitido.
0.0 indica imediatamente. Em alguns casos, como flooding, isto poderá
causar colisões sistemáticas. Então, a função Random::uniform(faixa),
ou alguma outra, devera ser usada para definir um tempo aleatório de espera.
cmh->next_hop_ define qual nodo será o destinatário imediato
(não final) do pacote. IP_BROADCAST indica, obviamente, que
todos dentro do alcance receberão o pacote.
Outro ponto importante e' a definição: cmh->direction()
= hdr_cmn::DOWN;
Para assegurar a transmissão correta. Isto não consta na documentação
oficial
drop(pkt,
_xulambs); // Onde _xulambs é a constante indicando a razão porque o pacote
foi descartado
Com isso concluímos que o porquinho foi pro mar!