Escolar Documentos
Profissional Documentos
Cultura Documentos
Verso ns-3.21
ns-3 project
05/12/2014
Sumrio
Introduo
1.1 Para os usurios do ns-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Contribuindo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Organizao do Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
4
4
Recursos
2.1 A Internet . . . . . . . . . . . . . . .
2.2 Mercurial . . . . . . . . . . . . . . .
2.3 Waf . . . . . . . . . . . . . . . . . .
2.4 Ambiente de Desenvolvimento . . . .
2.5 Programando com Soquetes (Sockets)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
5
6
6
6
Iniciando
3.1 Baixando o ns-3 . . . . . . . .
3.2 Construindo o ns-3 . . . . . . .
3.3 Testando o ns-3 . . . . . . . . .
3.4 Executando um cdigo (Script)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
12
14
15
Viso Conceitual
4.1 Principais Abstraes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 O primeiro cdigo no ns-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 Cdigo fonte do Ns-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
17
19
27
Aprofundando Conhecimentos
5.1 Usando o Mdulo de Registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Usando Argumentos na Linha de Comando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Usando o Sistema de Rastreamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
29
34
38
Construindo topologias
6.1 Construindo uma rede em barramento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 Modelos, atributos e a sua realidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3 Construindo uma rede sem fio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
43
51
52
Rastreamento
61
.
.
.
.
.
.
.
.
.
.
.
.
7.1
7.2
7.3
7.4
7.5
8
ii
Introduo . . . . . . . . . . . . . . . . . . .
Viso Geral . . . . . . . . . . . . . . . . . . .
Um Exemplo Real . . . . . . . . . . . . . . .
Usando Classes Assistentes para Rastreamento
Consideraes Finais . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. 61
. 63
. 75
. 90
. 102
Concluso
103
8.1 Para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.2 Finalizando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Este o Tutorial do ns-3 baseado no ns-3 Tutorial (ingls), verso 3.14. A documentao para o projeto ns-3 esta
disponvel da seguinte forma:
ns-3 Doxygen: Documentao das APIs pblicas do simulador;
Tutorial (este documento), manual, modelos de bibliotecas para a ltima release e rvore de desenvolvimento;
ns-3 wiki.
Este documento escrito em reStructuredText para Sphinx e mantido no diretrio doc/tutorial-pt-br do
cdigo fonte do ns-3.
Sumrio
Sumrio
CAPTULO 1
Introduo
O ns-3 um simulador de redes baseado em eventos discretos desenvolvido especialmente para pesquisa e uso educacional. O projeto ns-3 iniciou em 2006 e tem seu cdigo aberto.
O objetivo deste tutorial apresentar o ns-3 de forma estruturada aos usurios iniciantes. Algumas vezes torna-se
difcil obter informaes bsicas de manuais detalhados e converter em informaes teis para as simulaes. Neste
tutorial so ilustrados vrios exemplos de simulaes, introduzindo e explicando os principais conceitos necessrios
ao longo do texto.
A documentao completa do ns-3 e trechos do cdigo fonte so apresentados para os interessados em aprofundar-se
no funcionamento do sistema.
Alguns pontos importantes para se observar:
O ns-3 no uma extenso do ns-2; O ns-3 um simulador novo. Ambos so escritos em C++, mas o ns-3
totalmente novo e no suporta as APIs da verso anterior. Algumas funcionalidades do ns-2 j foram portadas
para o ns-3. O projeto continuar mantendo o ns-2 enquanto o ns-3 estiver em fase de desenvolvimento e formas
de integrao e transio esto em estudo.
O ns-3 cdigo aberto e existe um grande esforo para manter um ambiente aberto para pesquisadores que
queiram contribuir e compartilhar software com o projeto.
Uma questo que frequentemente aparece : Eu devo continuar usando o ns-2 ou devo migrar para o ns-3?. A
resposta : depende. O ns-3 no tem todos os modelos do ns-2, contudo, possui novas funcionalidades (tais como:
trabalha corretamente com ns de rede com mltiplas interfaces de rede (por exemplo, computadores com vrias placas
de rede), usa endereamento IP, mais consistente com arquiteturas e protocolos da Internet, detalha mais o modelo
802.11, etc.). Em todo o caso, os modelos do ns-2 podem ser portados para o ns-3 (um guia est em desenvolvimento).
Atualmente existem vrias frentes de trabalho para o desenvolvimento do simulador. Os desenvolvedores acreditam
(e os primeiros usurios concordam) que o ns-3 est pronto para o uso e uma tima alternativa para usurios que
querem iniciar novos projetos de simulao.
1.2 Contribuindo
O ns-3 um simulador para pesquisas e de uso educacional, feito por e para pesquisadores. Este conta com contribuies da comunidade para desenvolver novos modelos, corrigir erros ou manter cdigos e compartilhar os resultados.
Existem polticas de incentivo para que as pessoas contribuam com o projeto, assim como foi feito no ns-2, tais como:
Licena de cdigo aberto compatvel com GNU GPLv2;
Wiki;
Pgina para contribuio com o cdigo, similar a pgina de contribuio do ns-2;
Registro de erros (bugs) aberto.
Se voc est lendo este documento, provavelmente contribuir diretamente no seja o foco neste momento, mas esteja
ciente que contribuir est no esprito do projeto, mesmo que seja deixando uma mensagem descrevendo suas experincias com o ns-3 (por exemplo, voc pode relatar qual seo deste tutorial no esta clara), reportar a desatualizao
da documentao, etc. Toda ajuda ser muita bem vinda.
Captulo 1. Introduo
CAPTULO 2
Recursos
2.1 A Internet
H vrios recursos importantes que um usurio do ns-3 deve conhecer. O principal est em http://www.nsnam.org e
fornece acesso a informaes bsicas sobre o ns-3. A documentao detalhada esta disponvel no stio principal atravs do endereo http://www.nsnam.org/documentation/. Nesta pgina, tambm podem ser encontrados documentos
relacionados a arquitetura do sistema.
Tambm existe um Wiki que completa o stio do ns-3 e pode ser encontrado em http://www.nsnam.org/wiki/. Nesta
pgina so encontradas perguntas freqentes - FAQs (do ingls, Frequently Asked Questions) para usurios e desenvolvedores, guias para resoluo de problemas, cdigo de terceiros, artigos, etc.
O cdigo fonte tambm pode ser encontrado e explorado em http://code.nsnam.org/. Neste encontra-se a rvore de
cdigo em desenvolvimento em um repositrio chamado ns-3-dev. Repositrios antigos e experimentais do ncleo
de desenvolvimento podem ser encontrados neste stio tambm.
2.2 Mercurial
Sistemas complexos precisam gerenciar a organizao e alteraes do cdigo, bem como a documentao. Existem
vrias maneiras de fazer isto e o leitor provavelmente j ouviu falar de algumas. O Concurrent Version System (CVS)
em portugus, Sistema de Verses Concorrentes provavelmente o mais conhecido.
O ns-3 utiliza o Mercurial para isto. Embora no seja necessrio conhecer muito sobre o Mercurial para
entender este tutorial, recomenda-se a familiarizao com o uso da ferramenta para acessar o cdigo fonte
do sistema. O Mercurial tem um stio em http://www.selenic.com/mercurial/, no qual pode-se baixar diretamente os executveis ou o cdigo fonte deste sistema de Software Configuration Management (SCM)
em portugus, Software de Gerenciamento de Configurao. Selenic (o desenvolvedor do Mercurial),
tambm fornece tutoriais em http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial/, e um guia rpido em
http://www.selenic.com/mercurial/wiki/index.cgi/QuickStart/.
Informaes vitais de como usar o Mercurial e o ns-3 so encontradas no stio principal do projeto.
2.3 Waf
Uma vez baixado o cdigo fonte para o seu sistema de arquivos local, ser necessrio compilar estes fontes para
criar os executveis. Para esta tarefa existem vrias ferramentas disponveis. Provavelmente a mais conhecida o
Make. Alm de mais conhecido, tambm deve ser o mais difcil de usar em grandes sistemas e com muitas opes
de configurao. Por este motivo, muitas alternativas foram desenvolvidas, utilizando principalmente a linguagem
Python.
O Waf utilizado para gerar os binrios no projeto ns-3. Ele faz parte da nova gerao de sistemas de compilao e
contruo baseados em Python. O leitor no precisa entender nada de Python para compilar o ns-3, e ter que entender
um pequeno e intuitivo subconjunto da linguagem se quiser estender o sistema.
Para os interessados em mais detalhes sobre o Waf, basta acessar o stio http://code.google.com/p/waf/.
Captulo 2. Recursos
Uma API do Ingls, Application Programming Interface um um conjunto de rotinas e padres estabelecidos
por um software para a utilizao das suas funcionalidades. Para uma boa viso geral sobre a programao de soquetes
TCP/IP sugerimos TCP/IP Sockets in C, Donahoo and Calvert.
O stio http://cs.baylor.edu/~donahoo/practical/CSockets/ contm os cdigos fontes dos exemplos do livro.
Se o leitor entender os primeiros quatro captulos do livro (ou para aqueles que no tm acesso ao livro, os exemplos de
cliente e servidor de eco mostrado no stio anterior) estar apto para compreender o tutorial. Existe tambm um livro
sobre soquetes multidifuso, Multicast Sockets, Makofske and Almeroth. que um material que cobre o necessrio
sobre multidifuso caso o leitor se interesse.
Captulo 2. Recursos
CAPTULO 3
Iniciando
Depois que o comando clone for executado com sucesso, teremos um diretrio chamado ns-3-allinone dentro
do diretrio ~/repos. O contedo deste diretrio deve ser algo como:
build.py*
constants.py
dist.py*
download.py*
README
util.py
At agora foram baixados alguns scripts em Python. O prximo passo ser usar estes scripts para baixar e construir a
distribuio ns-3 de sua escolha.
Acessando o endereo: http://code.nsnam.org/, observa-se vrios repositrios. Alguns so privados equipe de desenvolvimento do ns-3. Os repositrios de interesse ao leitor estaro prefixados com ns-3. As releases oficiais do ns-3
estaro enumeradas da seguinte forma: ns-3.<release>.<hotfix>. Por exemplo, uma segunda atualizao de
pequeno porte (hotfix) de uma hipottica release 42, seria enumerada da seguinte maneira: ns-3.42.2.
A verso em desenvolvimento (que ainda no uma release oficial) pode ser encontrada em http://code.nsnam.org/ns3-dev/. Os desenvolvedores tentam manter este repositrio em um estado consistente, mas podem existir cdigos
instveis. Recomenda-se o uso de uma release oficial, a no ser que se necessite das novas funcionalidades introduzidas.
Uma vez que o nmero das verses fica mudando constantemente, neste tutorial ser utilizada a verso ns-3-dev, mas
o leitor pode escolher outra (por exemplo, ns-3.10). A ltima verso pode ser encontrada inspecionando a lista de
repositrios ou acessando a pgina ns-3 Releases e clicando em latest release.
Entre no diretrio ns-3-allinone criado anteriormente. O arquivo download.py ser usado para baixar as
vrias partes do ns-3 que sero utilizadas.
Execute os seguintes comandos no shell (lembre-se de substituir o nmero da verso no lugar de ns-3-dev pela que
escolheu, por exemplo, se voc optou por usar a dcima release estvel, ento deve usar o nome "ns-3.10").
./download.py -n ns-3-dev
O ns-3-dev o padro quando usamos a opo -n, assim o comando poderia ser ./download.py -n. O
exemplo redundante apenas para ilustra como especificar repositrios alternativos. Um comando mais simples para
obter o ns-3-dev seria:
./download.py
10
Captulo 3. Iniciando
Este o script de download obtendo um gerador de bindings Python um binding literalmente a ligao ou ponte
entre dois sistemas, chamaremos aqui de extenses Python. Tambm ser necessrio o Bazaar (brz) para baixar o
PyBindGen. O Bazaar um sistema de controle de verses. Em seguida, o leitor deve ver (com algumas variaes
devido as plataformas) algo parecido com as seguintes linhas:
#
# Get NSC
#
Required NSC version: nsc-0.5.0
Retrieving nsc from https://secure.wand.net.nz/mercurial/nsc
=> hg clone https://secure.wand.net.nz/mercurial/nsc nsc
requesting all changes
adding changesets
adding manifests
adding file changes
added 273 changesets with 17565 changes to 15175 files
10622 files updated, 0 files merged, 0 files removed, 0 files unresolved
Neste momento, o script de download baixa o Network Simulation Cradle - NSC. Note que o NSC no suportado no
OSX ou Cygwin e trabalha melhor com o gcc-3.4, gcc-4.2 ou superiores.
Depois que o script download.py tiver completado sua tarefa, veremos vrios diretrios novos dentro de
~/repos/ns-3-allinone:
build.py*
constants.py
constants.pyc
dist.py*
download.py*
ns-3-dev/
nsc/
pybindgen/
README
util.py
util.pyc
Por fim, no diretrio ns-3-dev que est dentro do diretrio ~/repos/ns-3-allinone deve existir, depois dos
passos anteriores, o seguinte contedo:
AUTHORS
bindings
CHANGES.html
doc
examples
LICENSE
ns3
README
RELEASE_NOTES
scratch
src
test.py*
testpy.supp
utils
utils.py
VERSION
waf*
waf.bat*
waf-tools
wscript
wutils.py
11
tarballs para manter as verses obtidas via arquivo compactado. Dica: o tutorial ir assumir que o download foi
feito dentro do diretrio repos. Se a opo for pelo mtodo do arquivo compactado, pode-se obter a cpia de uma
verso digitando os seguintes comandos no shell Linux (obviamente, substitua os nmeros de verses do comando
para o valor apropriado):
cd
mkdir tarballs
cd tarballs
wget http://www.nsnam.org/releases/ns-allinone-3.10.tar.bz2
tar xjf ns-allinone-3.10.tar.bz2
ns-3.10/
nsc-0.5.2/
pybindgen-0.15.0/
README
util.py
Foram utilizadas as opes --enable-examples e --enable-tests pois o tutorial ir trabalhar com exemplos
e testes, e, por padro, eles no so construdos. Futuramente, o leitor poder construir sem estas opes.
Sero exibidas muitas sadas tpicas de um compilador conforme o cdigo construdo. Finalmente, no final do
processo, dever aparecer uma sada como esta:
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (2m30.586s)
Modules built:
aodv
click
csma
emu
internet
mobility
network
ns3wifi
point-to-point
spectrum
template
topology-read
visualizer
12
applications
config-store
csma-layout
energy
lte
mpi
nix-vector-routing
olsr
point-to-point-layout
stats
test
uan
wifi
bridge
core
dsdv
flow-monitor
mesh
netanim
ns3tcp
openflow
propagation
tap-bridge
tools
virtual-net-device
wimax
Captulo 3. Iniciando
Uma vez que o projeto foi construdo, pode-se deixar de lado os scripts ns-3-allinone. O leitor j obteve o que
precisava e agora ir interagir diretamente com o Waf no diretrio ns-3-dev. Mude para o diretrio ns-3-dev (ou
para o diretrio apropriado de sua verso).
cd ns-3-dev
Isto executa o Waf fora do diretrio local (o que bem conveniente). Como o sistema em construo verifica vrias
dependncias, dever aparecer uma sada similar com a que segue:
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
Checking
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
for
program g++
: ok /usr/bin/g++
program cpp
: ok /usr/bin/cpp
program ar
: ok /usr/bin/ar
program ranlib
: ok /usr/bin/ranlib
g++
: ok
program pkg-config
: ok /usr/bin/pkg-config
-Wno-error=deprecated-declarations support : yes
-Wl,--soname=foo support
: yes
header stdlib.h
: ok
header signal.h
: ok
header pthread.h
: ok
high precision time implementation
: 128-bit integer
header stdint.h
: ok
header inttypes.h
: ok
header sys/inttypes.h
: not found
library rt
: ok
header netpacket/packet.h
: ok
pkg-config flags for GSL
: ok
header linux/if_tun.h
: ok
pkg-config flags for GTK_CONFIG_STORE
: ok
pkg-config flags for LIBXML2
: ok
library sqlite3
: ok
NSC location
: ok ../nsc (guessed)
library dl
: ok
NSC supported architecture x86_64
: ok
program python
: ok /usr/bin/python
Python version >= 2.3
: ok 2.5.2
library python2.5
: ok
program python2.5-config
: ok /usr/bin/python2.5-config
header Python.h
: ok
-fvisibility=hidden support
: yes
pybindgen location
: ok ../pybindgen (guessed)
Python module pybindgen
: ok
pybindgen version
: ok 0.10.0.640
Python module pygccxml
: ok
pygccxml version
: ok 0.9.5
program gccxml
: ok /usr/local/bin/gccxml
gccxml version
: ok 0.9.0
13
Repare a ltima parte da sada. Algumas opes do ns-3 no esto habilitadas por padro ou necessitam de algum
suporte do sistema para funcionar corretamente. Por exemplo, para habilitar XmlTo, a biblioteca libxml-2.0 deve
estar presente no sistema. Se a biblioteca no estiver instalada esta funcionalidade no habilitada no ns-3 e uma
mensagem apresentada. Note tambm que existe uma funcionalidade que utiliza o Sudo para configurar o suid de
certos programas. Isto no est habilitado por padro, ento esta funcionalidade reportada como no habilitada (not
enabled).
Vamos configurar uma construo do ns-3 com suporte a depurao, bem como, vamos incluir exemplos e testes. Para
isto devemos executar:
./waf -d debug --enable-examples --enable-tests configure
Pronto o sistema est configurado, agora podemos construir nossa verso digitando:
./waf
Alguns comandos do Waf so vlidos apenas na fase de construo e outros so vlidos na fase de configurao do
sistema. Por exemplo, se o leitor espera usar caractersticas de emulao do ns-3, deve habilitar o suid usando o Sudo
como descrito anteriormente, isto na fase de configurao. O comando utilizado, incluindo exemplos e testes, ser:
./waf -d debug --enable-sudo --enable-examples --enable-tests configure
Com esta configurao, o Waf executar o Sudo para alterar programas que criam soquetes para executar o cdigo de
emulao como root. Existem vrias outras opes de configurao e construo disponveis no Waf. Para explorar
estas opes, digite:
./waf --help
14
Captulo 3. Iniciando
./test.py -c core
Estes testes so executados em paralelo pelo Waf. No final, uma mensagem como a que segue deve aparecer.
47 of 47 tests passed (47 passed, 0 failed, 0 crashed, 0 valgrind errors)
TestSuite
TestSuite
TestSuite
TestSuite
TestSuite
TestSuite
applications
config-store
csma-layout
energy
lte
mpi
nix-vector-routing
olsr
point-to-point-layout
stats
test
uan
wifi
bridge
core
dsdv
flow-monitor
mesh
netanim
ns3tcp
openflow
propagation
tap-bridge
tools
virtual-net-device
wimax
ns3-wifi-interference
histogram
sample
ipv4-address-helper
devices-wifi
propagation-loss-model
...
PASS:
PASS:
PASS:
PASS:
PASS:
PASS:
PASS:
95 of
TestSuite attributes
TestSuite config
TestSuite global-value
TestSuite command-line
TestSuite basic-random-number
TestSuite object
TestSuite random-number-generators
95 tests passed (95 passed, 0 failed, 0 crashed, 0 valgrind errors)
Este comando normalmente executado pelos usurios para verificar se o ns-3 foi construdo corretamente.
15
O Waf primeiro verifica se o programa foi construdo corretamente e se necessrio, o constri. Ento executa o
programa, que fornece a seguinte sada:
Hello Simulator
para dizer ao Waf para construir o ns-3 com a verso de depurao e incluir exemplos e testes. Ainda necessrio
digitar o seguinte comando para a construo:
./waf
16
Captulo 3. Iniciando
CAPTULO 4
Viso Conceitual
Antes de escrever cdigos no ns-3 extremamente importante entender um pouco dos conceitos e abstraes do
sistema. Muitos conceitos podero parecer bvios, mas a recomendao geral que esta seo seja lida por completo
para assegurar que o leitor inicie com uma base slida.
4.1.1 N (Node)
No jargo da Internet, um dispositivo computacional que conecta-se a uma rede chamado de host ou em alguns
casos de terminal. Devido ao fato do ns-3 ser um simulador de rede, e no um simulador da Internet, o termo host
intencionalmente no utilizado, pois est intimamente associado com a Internet e seus protocolos. Ao invs disso,
utilizado o termo node em portugus, n que um termo mais genrico e tambm usado por outros simuladores
que tem suas origens na Teoria dos Grafos.
A abstrao de um dispositivo computacional bsico chamado ento de n. Essa abstrao representada em C++
pela classe Node. Esta classe fornece mtodos para gerenciar as representaes de dispositivos computacionais nas
simulaes.
O n deve ser pensado como um computador no qual se adicionam funcionalidades, tal como aplicativos, pilhas de
protocolos e perifricos com seus drivers associados que permitem ao computador executar tarefas teis. No ns-3
utilizado este mesmo conceito bsico.
17
operacional real, no h o conceito de nveis de privilgios nem chamadas de sistema. H apenas aplicaes que so
executadas nos ns para uma determinada simulao.
No ns-3, a abstrao bsica para um programa de usurio que gera alguma atividade a ser simulada a aplicao. Esta
abstrao representada em C++ pela classe Application, que fornece mtodos para gerenciar a representao
de suas verses de aplicaes a serem simuladas. Os desenvolvedores devem especializar a classe Application
para criar novas aplicaes. Neste tutorial sero utilizadas duas especializaes da classe Application, chamadas
UdpEchoClientApplication e UdpEchoServerApplication. Estas aplicaes compem um modelo
cliente/servidor usado para gerar pacotes simulados de eco na rede.
18
examples
LICENSE
ns3
README
RELEASE_NOTES
scratch
src
test.py*
testpy-output
testpy.supp
utils
utils.py
utils.pyc
VERSION
waf*
waf.bat*
waf-tools
wscript
wutils.py
wutils.pyc
Entrando no diretrio examples/tutorial, vai haver um arquivo chamado first.cc. Este um cdigo que
criar uma conexo ponto-a-ponto entre dois ns e enviar um pacote de eco entre eles. O arquivo ser analisado linha
a linha, para isto, o leitor pode abri-lo em seu editor de textos favorito.
4.2.1 Padronizao
A primeira linha do arquivo uma linha de modo emacs, que informa sobre a conveno de formatao (estilo de
codificao) que ser usada no cdigo fonte.
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Este sempre um assunto um tanto quanto controverso. O projeto ns-3, tal como a maioria dos projetos de grande
porte, adotou um estilo de codificao, para o qual todo o cdigo deve conformar. Se o leitor quiser contribuir com o
projeto, dever estar em conformidade com a codificao que est descrita no arquivo doc/codingstd.txt ou no
stio.
A equipe do ns-3 recomenda aos novos usurios que adotem o padro quando estiverem tralhando com o cdigo. Tanto
eles, quanto todos os que contribuem, tiveram que fazer isto em algum momento. Para aqueles que utilizam o editor
Emacs, a linha de modo torna mais facil seguir o padro corretamente.
O ns-3 licenciado usando a GNU General Public License - GPL. No cabealho de todo aquivo da distribuio h as
questes legais associadas licena. Frequentemente, haver tambm informaes sobre os direitos de cpia de uma
das instituies envolvidas no projeto e o autor do arquivo.
/*
*
*
*
*
*
19
"ns3/core-module.h"
"ns3/network-module.h"
"ns3/internet-module.h"
"ns3/point-to-point-module.h"
"ns3/applications-module.h"
Os arquivos a serem includos so agrupados em mdulos relativamente grandes, de forma a ajudar os usurios.
Tambm possvel fazer referncia a um nico arquivo que ir recursivamente carregar todas as bibliotecas de cada
mdulo. Ao invs de procurar pelo arquivo exato, e provavelmente, ter que resolver dependncias, possvel carregar
um grupo de arquivos de uma vez. Esta com certeza no a abordagem mais eficiente, mas permite escrever cdigos
de forma bem mais fcil.
Durante a construo, cada um dos arquivos includos copiado para o diretrio chamado ns3 (dentro do diretrio
build), o que ajuda a evitar conflito entre os nomes dos arquivos de bibliotecas. O arquivo ns3/core-module.h,
por exemplo, corresponde ao mdulo que est no diretrio src/core. H um grande nmero de arquivos neste diretrio. No momento em que o Waf est construindo o projeto, copia os arquivos para o diretrio ns3, no subdiretrio
apropriado build/debug ou build/optimized dependendo da configurao utilizada.
Considerando que o leitor esteja seguindo este tutorial, j ter feito:
./waf -d debug --enable-examples --enable-tests configure
para construir o projeto. Ento, no diretrio ../../build/debug/ns3 dever haver os quatro mdulos includos
anteriormente. Olhando para o contedo destes arquivos, possvel observar que eles incluem todos os arquivos
pblicos dos seus respectivos mdulos.
O projeto ns-3 implementado em um namespace chamado ns3. Isto agrupa todas as declaraes relacionadas ao
projeto em um escopo fora do global, que ajuda na integrao com outros cdigos. A declarao using do C++
insere o namespace ns-3 no escopo global, evitando que se tenha que ficar digitando ns3:: antes dos cdigos ns-3.
Se o leitor no esta familiarizado com namesapaces, consulte algum tutorial de C++ e compare o namespace ns3 e o
namespace std, usado com frequncia em C++, principalmente com cout e streams.
20
Ns iremos utilizar esta declarao em um lugar conveniente para conversar com o sistema de documentao Doxygen.
Se voc procurar no web site do projeto ns-3, voc encontrar um link para a documentao (Documentation) na barra
de navegao. Se selecionarmos este link, veremos a pgina de documentao. L tem um link para as ltimas releases
(Latest Release) que iro apresentar a documentao da ltima release do ns-3. Se voc tambm pode selecionar o
link para a documentao das APIs (API Documentation).
Do lado esquerdo, voc achar uma representao grfica da estrutura da documentao. Um bom lugar para comear
com o livro de mdulos do NS-3 (NS-3 Modules) na rvore de navegao, voc pode expandir para ver a lista de
documentao de mdulos do ns-3. O conceito de mdulo aqui est diretamente ligado com a incluso de bibliotecas
apresentadas anteriormente. O sistema de registro (logging) discutido na seo C++ Constructs Used by
All Modules, v em frente e expanda a documentao. Agora expanda o livro da depurao (Debugging) e
selecione a pgina de Logging.
Agora voc deve procurar na documentao Doxygen pelo mdulo de Logging. Na lista de #define bem no topo
da pgina voc ver uma entrada para NS_LOG_COMPONENT_DEFINE. Antes de ir para l, d uma boa olhada na
descrio detalhada (Detailed Description) do mdulo de logging.
Uma vez que voc tem uma ideia geral, prossiga e olhe a documentao de NS_LOG_COMPONENT_DEFINE.
No esperamos duplicar a documentao, mas para resumir esta linha declara o componente de logging chamado
FirstScriptExample que permite habilitar e desabilitar mensagens de logging referenciando pelo nome.
Esta a declarao da funo principal (main) do programa. Assim como em qualquer programa em C++, voc
precisa definir uma funo principal que a primeira funo que ser executada no programa. No h nada de especial
e seu cdigo ns-3 apenas um programa C++.
As prximas duas linhas do cdigo so usadas para habilitar dois componentes de registro que so construdos com as
aplicaes de Echo Client e Echo Server:
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
Se voc leu a documentao do componente de logging voc viu que existem vrios nveis de detalhamento de logging
e que voc pode habilit-los para cada componente. Essas duas linhas de cdigo habilitam a depurao de logging
com o nvel INFO para o cliente e servidor. Isto ira fazer com que as aplicaes mostrem as mensagens dos pacotes
sendo enviados e recebidos durante a simulao.
Agora ns iremos direto ao ponto, criando uma topologia e executando uma simulao. Ns usaremos o Assistente de
Topologia para fazer isto da forma mais simples possvel.
21
Antes de continuar vamos pesquisar a documentao da classe NodeContainer. Outra forma de obter a documentao atravs aba Classes na pgina do Doxygen. No Doxygen, v at o topo da pgina e selecione Classes.
Ento, voc ver um novo conjunto de opes aparecendo, uma delas ser a sub-aba Class List. Dentro desta
opo voc ver uma lista com todas as classes do ns-3. Agora procure por ns3::NodeContainer. Quando voc
achar a classe, selecione e veja a documentao da classe.
Lembre-se que uma de nossas abstraes o n. Este representa um computador, ao qual iremos adicionar coisas, como protocolos, aplicaes e perifricos. O assistente NodeContainer fornece uma forma conveniente de
criar, gerenciar e acessar qualquer objeto Node que criamos para executar a simulao. A primeira linha declara um
NodeContainer que chamamos de nodes. A segunda linha chama o mtodo Create sobre o objeto nodes e
pede para criar dois ns.
Os ns, como esto no cdigo, no fazem nada. O prximo passo montar uma topologia para conect-los em uma
rede. Uma forma simples de conectar dois computadores em uma rede com um enlace ponto-a-ponto.
PointToPointHelper
Construiremos um enlace ponto-a-ponto e para isto usaremos um assistente para configurar o nvel mais baixo da
rede. Lembre-se que duas abstraes bsicas so NetDevice e Channel. No mundo real, estes termos correspondem, a grosso modo, placa de rede e ao cabo. Normalmente, estes dois esto intimamente ligados e no
normal ficar trocando. Por exemplo, no comum placas Ethernet conectadas em canais sem fio. O assistente de
topologia acopla estes dois conceitos em um simples PointToPointHelper para configurar e conectar objetos
PointToPointNetDevice e PointToPointChannel em nosso cdigo.
As prximas trs linhas no cdigo so,
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
A primeira linha,
PointToPointHelper pointToPoint;
diz ao objeto PointToPointHelper para usar o valor de 5Mbps (cinco megabits por segundo) como DataRate
(taxa de transferncia) quando criarmos um objeto PointToPointNetDevice.
De uma perspectiva mais detalhada, a palavra DataRate corresponde ao que ns chamamos de
atributo (Attribute) do PointToPointNetDevice.
Se voc olhar no Doxygen na classe
ns3::PointToPointNetDevice e procurar a documentao para o mtodo GetTypeId, voc achar
uma lista de atributos definidos por dispositivos. Dentro desses est o atributo DataRate. A maioria dos objetos do
ns-3 tem uma lista similar de atributos. Ns usamos este mecanismo para facilitar a configurao das simulaes sem
precisar recompilar, veremos isto na seo seguinte.
22
Parecido com o DataRate no PointToPointNetDevice voc achar o atributo Delay (atraso) associado com
o PointToPointChannel. O final da linha,
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
diz ao PointToPointHelper para usar o valor de 2ms (dois milissegundos) como valor de atraso de transmisso
para o canal ponto-a-ponto criado.
NetDeviceContainer
At agora no cdigo, temos um NodeContainer que contm dois ns. Tambm temos PointToPointHelper
que carrega e prepara os objetos PointToPointNetDevices e PointToPointChannel. Depois, usamos o
assistente NodeContainer para criar os ns para a simulao. Iremos pedir ao PointToPointHelper para
criar, configurar e instalar nossos dispositivos. Iremos necessitar de uma lista de todos os objetos NetDevice que so
criados, ento ns usamos um NetDeviceContainer para agrupar os objetos criados, tal como usamos o NodeContainer
para agrupar os ns que criamos. Nas duas linhas de cdigo seguintes,
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
vamos terminar configurando os dispositivos e o canal. A primeira linha declara o continer de dispositivos mencionado anteriormente e o segundo faz o trabalho pesado. O mtodo Install do PointToPointHelper utiliza
um NodeContainer como parmetro. Internamente, um NetDeviceContainer criado. Para cada n no
NodeContainer (devem existir dois para um enlace ponto-a-ponto) um PointToPointNetDevice criado e
salvo no continer do dispositivo. Um PointToPointChannel criado e dois PointToPointNetDevices
so conectados. Quando os objetos so criados pelo PointToPointHelper, os atributos, passados anteriormente,
so configurados pelo assistente (Helper).
Depois de executar a chamada pointToPoint.Install (nodes) iremos ter dois ns, cada qual instalado na
rede ponto-a-ponto e um nico canal ponto-a-ponto ligando os dois. Ambos os dispositivos sero configurados para
ter uma taxa de transferncia de dados de cinco megabits por segundo, que por sua vez tem um atraso de transmisso
de dois milissegundos.
InternetStackHelper
Agora temos os ns e dispositivos configurados, mas no temos qualquer pilha de protocolos instalada em nossos ns.
As prximas duas linhas de cdigo iro cuidar disso.
InternetStackHelper stack;
stack.Install (nodes);
23
declara um assistente de endereamento e diz para ele iniciar a alocao de IPs na rede 10.1.1.0 usando a mscara
255.255.255.0. Por padro, os endereos alocados iro iniciar do primeiro endereo IP disponvel e sero incrementados um a um. Ento, o primeiro endereo IP alocado ser o 10.1.1.1, seguido pelo 10.1.1.2, etc. Em um nvel mais
baixo, o ns-3 mantm todos os endereos IPs alocados e gera um erro fatal se voc acidentalmente usar o mesmo
endereo duas vezes (esse um erro muito difcil de depurar).
A prxima linha de cdigo,
Ipv4InterfaceContainer interfaces = address.Assign (devices);
realiza efetivamente o endereamento. No ns-3 ns fazemos a associao entre endereos IP e dispositivos usando
um objeto Ipv4Interface. As vezes precisamos de uma lista dos dispositivos de rede criados pelo assistente de
topologia para consultas futuras. O Ipv4InterfaceContainer fornece esta funcionalidade.
Agora que ns temos uma rede ponto-a-ponto funcionando, com pilhas de protocolos instaladas e endereos IPs
configurados. O que ns precisamos so aplicaes para gerar o trfego de rede.
4.2.7 Aplicaes
Outra abstrao do ncleo do ns-3 so as aplicaes (Application). Neste cdigo so utilizadas duas especializaes da classe Application chamadas UdpEchoServerApplication e UdpEchoClientApplication.
Assim como nas explicaes anteriores que ns utilizamos assistentes para configurar e gerenciar outros objetos, ns
usaremos os objetos UdpEchoServerHelper e UdpEchoClientHelper para deixar a nossa vida mais fcil.
UdpEchoServerHelper
As linhas seguintes do cdigo do exemplo first.cc, so usadas para configurar uma aplicao de eco (echo) UDP
em um dos ns criados anteriormente.
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
iro iniciar (Start) a aplicao de servidor de eco um segundo aps o incio da simulao e depois desligar (Stop)
em dez segundos. Em virtude de termos declarado que um evento de simulao (o evento de desligamento da aplicao) deve ser executado por dez segundos, a simulao vai durar pelo menos dez segundos.
UdpEchoClientHelper
A aplicao cliente de eco configurada de forma muito similar ao servidor. H o UdpEchoClientApplication
que gerenciado por um UdpEchoClientHelper.
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Para o cliente de eco, precisamos configurar cinco diferentes atributos. Os dois primeiros so configurados durante a
construo do UdpEchoClientHelper. Passamos os parmetros que so usados (internamente pelo Assistente)
para configurar os atributos RemoteAddress (endereo remoto) e RemotePort (porta remota).
Lembre-se que usamos um Ipv4InterfaceContainer para configurar o endereo IP em nossos dispositivos. A
interface zero (primeira) no continer corresponde ao endereo IP do n zero no continer de ns. A primeira interface
corresponde ao endereo IP do primeiro n. Ento, na primeira linha do cdigo anterior, ns criamos um assistente
e dizemos ao n para configurar o endereo remoto do cliente conforme o IP do servidor. Ns dizemos tambm para
enviar pacotes para a porta nove.
O atributo MaxPackets diz ao cliente o nmero mximo de pacotes que so permitidos para envio durante a simulao. O atributo Interval diz ao cliente quanto tempo esperar entre os pacotes e o PacketSize informa ao cliente
qual o tamanho da rea de dados do pacote. Com esta combinao de atributos que ns fizemos teremos clientes
enviando pacotes de 1024 bytes.
Assim como no caso do servidor de eco, ns dizemos para o cliente de eco iniciar e parar, mas aqui ns iniciamos o
cliente um segundo depois que o servidor estiver funcionando (com dois segundos de simulao).
agendamos os eventos no simulador em 1 segundo, 2 segundos e dois eventos em 10 segundos. Quando chamamos
Simulator::Run, o sistema verificar a lista de eventos agendados e os executar no momento apropriado. Primeiramente, ele vai executar o evento de 1 segundo que inicia a aplicao de servidor de eco. Depois executa o evento
agendado com dois segundos (t=2,0) que iniciar a aplicao do cliente de eco. Estes eventos podem agendar muitos
4.2. O primeiro cdigo no ns-3
25
outros eventos. O evento start do cliente ir iniciar a fase de transferncia de dados na simulao enviando pacotes ao
servidor.
O ato de enviar pacotes para o servidor vai disparar uma cadeia de eventos que sero automaticamente escalonados e
executaro a mecnica do envio de pacotes de eco de acordo com os vrios parmetros de tempo que configuramos no
cdigo.
Considerando que enviamos somente um pacote (lembre-se que o atributo MaxPackets foi definido com um), uma
cadeia de eventos ser disparada por este nico pedido de eco do cliente at cessar e o simulador ficar ocioso. Uma vez
que isto ocorra, os eventos restantes sero o Stop do servidor e do cliente. Quando estes eventos forem executados,
no havendo mais eventos para processar, o Simulator::Run retorna. A simulao est completa.
Tudo que resta limpar. Isto feito chamando uma funo global chamada Simulator::Destroy. Uma das
funes dos assistentes (ou do cdigo de baixo nvel do ns-3) agrupar todos os objetos que foram criados e destrulos. Voc no precisa tratar estes objetos tudo que precisa fazer chamar Simulator::Destroy e sair. O ns-3
cuidar desta difcil tarefa para voc. As linhas restantes do cdigo fazem isto:
Simulator::Destroy ();
return 0;
}
Voc deve ver mensagens reportando que o seu exemplo myfirst foi construdo com sucesso.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
[614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o
[706/708] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (2.357s)
Voc agora pode executar o exemplo (note que se voc construiu seu programa no diretrio scratch, ento deve
executar o comando fora deste diretrio):
./waf --run scratch/myfirst
O sistema verifica se os arquivos foram construdos e ento executa-os. Atravs do componente de registro vemos
que o cliente enviou 1024 bytes para o servidor atravs do IP 10.1.1.2. Tambm podemos ver que o servidor diz ter
recebido 1024 bytes do IP 10.1.1.1 e ecoa o pacote para o cliente, que registra o seu recebimento.
26
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
2009-07-01
12:47
12:47
12:47
12:47
12:47
12:47
12:47
12:47
12:47
12:47
12:47
12:47
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+0200
560
1886
1276
30961
17987
3742
16171
6
88110
28
35395
7673
[up]
bindings python
doc
examples
ns3
scratch
src
utils
.hgignore
.hgtags
AUTHORS
CHANGES.html
LICENSE
README
RELEASE_NOTES
VERSION
waf
waf.bat
wscript
wutils.py
files
files
files
files
files
files
files
file |
file |
file |
file |
file |
file |
file |
file |
file |
file |
file |
file |
revisions
revisions
revisions
revisions
revisions
revisions
revisions
revisions
revisions
revisions
revisions
revisions
|
|
|
|
|
|
|
|
|
|
|
|
annotate
annotate
annotate
annotate
annotate
annotate
annotate
annotate
annotate
annotate
annotate
annotate
Os cdigos exemplo esto no diretrio examples. Se voc clicar ver uma lista de subdiretrios. Um dos arquivos
no subdiretrio tutorial o first.cc. Clicando nele voc encontrar o cdigo que acabamos de analisar.
O cdigo fonte mantido no diretrio src. Voc pode v-lo clicando sobre o nome do diretrio ou clicando no
item files a direita do nome. Clicando no diretrio src, obter uma lista de subdiretrios. Clicando no subdiretrio core, encontrar um lista de arquivos. O primeiro arquivo o abort.h, que contm macros caso condies
anormais sejam encontradas.
O cdigo fonte para os assistentes utilizados neste captulo podem ser encontrados no diretrio
src/applications/helper. Sinta-se vontade para explorar a rvore de diretrios e ver o estilo de
cdigo do ns-3.
27
28
CAPTULO 5
Aprofundando Conhecimentos
Tambm fornecido um nvel de registro incondicional, que sempre exibido independente do nvel de registro ou do
componente selecionado.
NS_LOG_UNCOND Registra mensagens incondicionalmente.
Cada nvel pode ser requerido individualmente ou de forma cumulativa. O registro pode ser configurado usando
uma varivel de ambiente (NS_LOG) ou atravs de uma chamada ao sistema de registro. J havamos abordado
anteriormente o sistema de registro, atravs da documentao Doxygen, agora uma boa hora para ler com ateno
esta documentao no Doxygen.
Depois de ler a documentao, vamos usar nosso conhecimento para obter algumas informaes importante do cdigo
de exemplo scratch/myfirst.cc.
Veremos a sada do nosso primeiro programa ns-3 de exemplo, tal como visto anteriormente.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.413s)
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
Essa linha de cdigo habilita o nvel LOG_LEVEL_INFO de registro. Quando habilitamos um dado nvel de registro, estamos habilitando este nvel e todos os nveis inferiores a este. Neste caso, habilitamos NS_LOG_INFO,
NS_LOG_DEBUG, NS_LOG_WARN e NS_LOG_ERROR. Podemos aumentar o nvel de registro e obter mais informaes sem alterar o script, ou seja, sem ter que recompilar. Conseguimos isto atravs da configurao da varivel de
ambiente NS_LOG, tal como:
export NS_LOG=UdpEchoClientApplication=level_all
Do lado esquerdo do comando temos o nome do componente de registro que ns queremos configurar, no lado direito
fica o valor que estamos passando. Neste caso, estamos ligando todos os nveis de depurao para a aplicao. Se
executarmos o cdigo com o NS_LOG configurado desta forma, o sistema de registro do ns-3 observar a mudana e
mostrar a seguinte sada:
30
As informaes de depurao extras, apresentadas aqui, so fornecidas pela aplicao no nvel de registros
NS_LOG_FUNCTION. Isto apresentado toda vez que a aplicao chamar a funo. No obrigatrio que o modelo fornea suporte a registro, no ns-3, esta deciso cabe ao desenvolvedor do modelo. No caso da aplicao de eco
uma grande quantidade de sadas de log esto disponveis.
Podemos ver agora registros de vrias funes executadas pela aplicao. Se olharmos mais de perto veremos que
as informaes so dadas em colunas separadas por (::), do lado esquerdo est o nome da aplicao (no exemplo,
UdpEchoClientApplication) e do outro lado o nome do mtodo esperado pelo escopo C++. Isto incremental.
O nome que est aparece no registro no necessariamente o nome da classe, mas sim o nome do componente de
registro. Quando existe uma correspondncia um-para-um, entre cdigo fonte e classe, este geralmente ser o nome
da classe, mas isto nem sempre verdade. A maneira sutil de diferenciar esta situao usar : quando for o nome do
componente de registro e :: quando for o nome da classe.
Em alguns casos pode ser complicado determinar qual mtodo gerou a mensagem. Se olharmos o texto anterior, veremos a mensagem Received 1024 bytes from 10.1.1.2, nesta no existe certeza de onde a mensagem
veio. Podemos resolver isto usando um OU (OR) entre o nvel de registro e o prefix_func, dentro do NS_LOG.
export NS_LOG=UdpEchoClientApplication=level_all|prefix_func
As aspas so requeridas quando usamos o | (pipe) para indicar uma operao de OU.
Agora, se executarmos o script devemos ver que o sistema de registro informa de qual componente de registro vem a
mensagem.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.417s)
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
Podemos ver, depois da configurao, que todas as mensagens do cliente de eco UDP esto identificadas. Agora a
mensagem Received 1024 bytes from 10.1.1.2 claramente identificada como sendo do cliente de eco. O restante
31
das mensagens devem estar vindo do servidor de eco UDP. Podemos habilitar mais do que um componente usando :,
para separ-los na varivel NS_LOG.
export NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
UdpEchoServerApplication=level_all|prefix_func
Ateno: no podemos quebrar a entrada da varivel em vrias linhas como foi feito no exemplo, tudo deve estar em
uma nica linha. O exemplo ficou assim por uma questo de formatao do documento.
Agora, se executarmos o script veremos todas as mensagens de registro tanto do cliente quando do servidor. Isto
muito til na depurao de problemas.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.406s)
UdpEchoServerApplication:UdpEchoServer()
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoServerApplication:StartApplication()
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
UdpEchoServerApplication:HandleRead(): Echoing packet
UdpEchoClientApplication:HandleRead(0x624920, 0x625160)
UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
UdpEchoServerApplication:StopApplication()
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()
As vezes tambm til registrar o tempo em que uma mensagem gerada. Podemos fazer isto atravs de um OU com
o prefix_time, exemplo:
export NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:
UdpEchoServerApplication=level_all|prefix_func|prefix_time
Novamente, teremos que deixar tudo em uma nica linha e no em duas como no exemplo anterior. Executando o
script, veremos a seguinte sada:
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.418s)
0s UdpEchoServerApplication:UdpEchoServer()
0s UdpEchoClientApplication:UdpEchoClient()
0s UdpEchoClientApplication:SetDataSize(1024)
1s UdpEchoServerApplication:StartApplication()
2s UdpEchoClientApplication:StartApplication()
2s UdpEchoClientApplication:ScheduleTransmit()
2s UdpEchoClientApplication:Send()
2s UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
2.00369s UdpEchoServerApplication:HandleRead(): Echoing packet
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
2.00737s UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
32
10s UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()
Podemos ver que o construtor para o UdpEchoServer foi chamado pelo simulador no segundo 0 (zero). Isto
acontece antes do simulador ser iniciado, mas o tempo mostrado como zero, o mesmo acontece para o construtor do
UdpEchoClient.
Lembre-se que o script scratch/first.cc inicia a aplicao servidor de eco no primeiro segundo da simulao.
Repare que o mtodo StartApplication do servidor , de fato, chamado com um segundo. Tambm podemos
notar que a aplicao cliente de eco iniciada com dois segundos de simulao, como ns pedimos no script.
Agora podemos acompanhar o andamento da simulao: ScheduleTransmit chamado no cliente, que invoca
o Send e o HandleRead, que usado na aplicao servidor de eco. Repare que o tempo decorrido entre o envio
de cada pacote de 3.69 milissegundos. Veja que a mensagem de registro do servidor diz que o pacote foi ecoado e
depois houve um atraso no canal. Podemos ver que o cliente recebeu o pacote ecoado pelo mtodo HandleRead.
Existe muita coisa acontecendo por baixo dos panos e que no estamos vendo. Podemos facilmente seguir as entradas
de processo configurando todos os componentes de registro do sistema. Configure a varivel de NS_LOG da seguinte
forma,
export NS_LOG=*=level_all|prefix_func|prefix_time
O asterisco um componente coringa, que ira ligar todos os componentes de registro usados na simulao. No vamos
reproduzir a sada aqui (cada pacote de eco produz 1265 linhas de sada), mas podemos redirecionar esta informao
para um arquivo e visualiz-lo depois em um editor de textos,
./waf --run scratch/myfirst > log.out 2>&1
utilizamos uma verso extremamente detalhada de registro quando surge um problema e no temos ideia do que est
errado. Assim, podemos seguir o andamento do cdigo e depurar o erro. Podemos assim visualizar a sada em um
editor de texto e procurar por coisas que ns esperamos e principalmente por coisa que no espervamos. Quando
temos uma ideia geral sobre o que est acontecendo de errado, usamos um depurador de erros para examinarmos
de forma mais detalhada o problema. Este tipo de sada pode ser especialmente til quando nosso script faz algo
completamente inesperado. Se estivermos depurando o problema passo a passo, podemos nos perder completamente.
O registro pode tornar as coisas mais visveis.
Agora que sabemos habilitar todos os registros em vrios nveis configurando a varivel NS_LOG. Vamos adicionar
alguns registros ao cdigo. O macro usado para adicionar uma mensagem ao nvel de informao NS_LOG_INFO,
ento vamos adicionar uma mensagem dessas (pouco antes de criar os ns de rede) que diz que a Topologia foi
Criada. Isto feito como neste trecho do cdigo,
Abra o arquivo scratch/myfirst.cc e adicione a linha,
NS_LOG_INFO ("Creating Topology");
33
NodeContainer nodes;
nodes.Create (2);
Agora construa o cdigo usando o Waf e limpe a varivel NS_LOG desabilite o registro que ns havamos habilitado
anteriormente:
./waf
export NS_LOG=
veremos novas mensagens, pois o componente de registro no est habilitado. Agora para ver a mensagem devemos
habilitar o componente de registro do FirstScriptExample com um nvel maior ou igual a NS_LOG_INFO. Se
s esperamos ver um nvel particular de registro, devemos habilita-lo,
export NS_LOG=FirstScriptExample=info
Estas duas linhas de programao so muito uteis. Isto abre uma porta para as variveis globais e atributos do ns-3.
Adicione estas duas linhas no cdigo em nosso exemplo scratch/myfirst.cc, bem no inicio da funo principal
(main). Na sequencia construa o cdigo e execute-o, mas pea para o cdigo ajudar da seguinte forma,
34
Isto pede ao Waf para executar o scratch/myfirst e passa via linha de comando o argumento --PrintHelp.
As aspas so necessrias para ordenar os argumentos. O analisador de linhas de comandos agora tem como argumento
o --PrintHelp e responde com,
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.413s)
TcpL4Protocol:TcpStateMachine()
CommandLine:HandleArgument(): Handle arg name=PrintHelp value=
--PrintHelp: Print this help message.
--PrintGroups: Print the list of groups.
--PrintTypeIds: Print all TypeIds.
--PrintGroup=[group]: Print all TypeIds of group.
--PrintAttributes=[typeid]: Print all attributes of typeid.
--PrintGlobals: Print the list of globals.
Vamos focar na opo --PrintAttributes. J demos a dica sobre atributos no ns-3 enquanto explorvamos o
cdigo do first.cc. Ns olhamos as seguintes linhas de cdigo,
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
O sistema ir mostrar todos os atributos dos tipos de dispositivos de rede (net device). Entre os atributos veremos,
--ns3::PointToPointNetDevice::DataRate=[32768bps]:
The default data rate for point to point links
32768 bits por segundos o valor padro que ser usado quando criarmos um PointToPointNetDevice no
sistema. Vamos alterar este valor padro do PointToPointHelper. Para isto iremos usar os valores dos dispositivos ponto-a-ponto e dos canais, deletando a chamada SetDeviceAttribute e SetChannelAttribute do
myfirst.cc, que ns temos no diretrio scratch.
Nosso cdigo agora deve apenas declarar o PointToPointHelper sem configurar qualquer operao, como no
exemplo a seguir,
...
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
...
Agora construa o novo cdigo com o Waf (./waf) e depois vamos habilitar alguns registros para o servidor de eco
UDP e ligar o prefixo de informaes sobre tempo de execuo.
35
export NS_LOG=UdpEchoServerApplication=level_all|prefix_time
Lembre-se que o ltimo tempo que vimos na simulao quando recebemos um pacote de eco no servidor, foi de
2.00369 segundos.
2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
Isto ira configurar o valor do atributo DataRate para cinco megabits por segundos. Ficou surpreso com o resultado?
Acontece que para obtermos o resultado do cdigo original, teremos que configurar tambm o atraso do canal de
comunicao. Podemos fazer isto via linha de comandos, tal como fizemos com o dispositivo de rede:
./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"
Ento descobrimos que o atributo Delay do canal esta configurado com o seguinte valor padro:
--ns3::PointToPointChannel::Delay=[0ns]:
Transmission delay through the channel
neste caso voltamos com os tempos de DataRate e Delay que tnhamos inicialmente no cdigo original:
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.417s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Sent 1024 bytes to 10.1.1.2
2.00369s Received 1024 bytes from 10.1.1.1
2.00369s Echoing packet
Received 1024 bytes from 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
36
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()
Repare que o pacote recebido novamente pelo servidor com 2.00369 segundos. Ento desta forma, podemos
configurar qualquer atributo usado no cdigo. Em particular ns podemos configurar o atributo MaxPackets do
UdpEchoClient para qualquer outro valor.
importante lembrar que devemos retirar todas as configuraes com valores explcitos do cdigo. Depois disto
devemos re-construir o cdigo (fazer novamente os binrios). Tambm teremos que achar a sintaxe do atributo usando
o help da linha de comando. Uma vez que tenhamos este cenrio estaremos aptos para controlar o nmeros de pacotes
ecoados via linha de comando. No final a linha de comando deve parecer com algo como:
./waf --run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"
D uma olhada um pouco mais para baixo, no cdigo e veja onde configuramos o atributo MaxPackets, retire o 1 e
coloque em seu lugar a varivel nPackets, como mostrado a seguir:
echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
Agora se executarmos o cdigo e fornecermos o argumento --PrintHelp, deveremos ver nosso argumento de
usurio (User Arguments), listado no help.
Execute,
./waf --run "scratch/myfirst --PrintHelp"
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.403s)
--PrintHelp: Print this help message.
--PrintGroups: Print the list of groups.
--PrintTypeIds: Print all TypeIds.
--PrintGroup=[group]: Print all TypeIds of group.
37
Agora para especificar o nmero de pacotes de eco podemos utilizar o argumento --nPackets na linha de comando,
./waf --run "scratch/myfirst --nPackets=2"
Podemos usar o mdulo de registro (visto anteriormente) para verificar pequenas estruturas de nossas solues. Porm,
os problemas gerados por esta abordagem j so bem conhecidos e portanto fornecemos um subsistema para rastrear
eventos genricos para localizar problemas importantes.
Os objetivos bsicos do sistema de rastreamento ns-3 so:
Para as tarefas bsicas, o sistemas de rastreamento fornece ao usurio um rastreamento padro atravs de rastreamentos conhecidos e customizao dos objetos que geram o rastreamento;
38
Os usurios podem estender o sistema de rastreamento para modificar os formatos das sadas geradas ou inserir
novas fontes de rastreamento, sem modificar o ncleo do simulador;
Usurios avanados podem modificar o ncleo do simulador para adicionar novas origens de rastreamentos e
destino do rastreamento.
O sistema de rastreamento do ns-3 feito atravs de conceitos independentes de rasteamento na origem e no destino,
e um mecanismo uniforme para conectar a origem ao destino. O rastreador na origem so entidades que podem
demonstrar eventos que ocorrem na simulao e fornece acesso aos dados importantes. Por exemplo, um rastreador
de origem podem indicar quando um pacote recebido por um dispositivo de rede e prove acesso aos comentrios de
pacote para os interessados no rastreador do destino.
Os rastreadores de origem no so usados sozinhos, eles devem ser conectados a outros pedaos de cdigo que fazem
alguma coisa til com a informao fornecida pelo destino. Rastreador de destino so consumidores dos eventos e
dados fornecidos pelos rastreadores de origem. Por exemplo, pode-se criar um rastreador de destino que (quando
conectado ao rastreador de origem do exemplo anterior) mostrar sadas de partes importantes de pacotes recebidos.
A lgica desta diviso explicita permitir que os usurios apliquem novos tipos de rastreadores de destinos em rastreadores de origem existentes, sem precisar editar ou recompilar o ncleo do simulador. Assim, no exemplo anterior, o
usurio pode definir um novo rastreador de destino em seu cdigo e aplicar isto a um rastreador de origem definido no
ncleo da simulao editando, para isto, somente o cdigo do usurio.
Neste tutorial, abordamos alguns rastreadores de origem e de destino j predefinidos e demonstramos como esses
podem ser customizados, com um pouco de esforo. Veja o manual do ns-3 ou a seo de how-to para informaes
avanadas sobre configurao de rastreamento incluindo extenso do namespace de rastreamento e criao de novos
rastreadores de origem.
Tal como j vimos no ns-3, este cdigo usa o objeto Assistente para criar o rastreador ASCII. A segunda linha aninhada
duas chamadas para mtodos. Dentro do mtodo CreateFileStream() utilizado um objeto para criar um outro
objeto, que trata um arquivo, que passado para o mtodo. Iremos detalhar isto depois, agora tudo que precisamos
saber que estamos criando um objeto que representa um arquivo chamado myfirst.tr. Estamos dizendo para o
ns-3 tratar problemas de criao de objetos e tambm para tratar problemas causados por limitaes do C++ com
objetos relacionados com cpias de construtores.
Fora da chamada, para EnableAsciiAll(), dizemos para o Assistente que esperamos habilitar o rastreamento
ASCII para todo dispositivo ponto-a-ponto da simulao; e esperamos rastrear destinos e escrever as informaes de
sada sobre o movimento de pacotes no formato ASCII.
Para queles familiarizados com ns-2, os eventos rastreados so equivalentes aos populares pontos de rastreadores
(trace points) que registram eventos +, -, d, e r
Agora podemos construir o cdigo e executa-lo:
./waf --run scratch/myfirst
39
Veremos algumas mensagens do Waf, seguida da mensagem build finished successfully, bem como algumas mensagens do programa.
Quando isto for executado, o programa criar um arquivo chamado myfirst.tr. Devido a forma que o Waf trabalha,
o arquivo no criado no diretrio local, mas sim no diretrio raiz do repositrio. Se voc espera controlar o que
salvo, ento use a opo -cwd do Waf. Agora mude para o diretrio raiz do repositrio e veja o arquivo myfirst.tr
com um editor de texto.
Anlise de Rastros ASCII
Uma grande quantidade de informao gerada pelo sistema de rastreamento e pode ser difcil analis-las de forma
clara e consistente.
Cada linha do arquivo corresponde a um evento de rastreamento (trace event). Neste caso so eventos rastreados da
fila de transmisso (transmit queue). A fila de transmisso um lugar atravs do qual todo pacote destinado para
o canal ponto-a-ponto deve passar. Note que cada linha no arquivo inicia com um nico caractere (com um espao
depois). Este caractere tem o seguinte significado:
+: Uma operao de enfileiramento (bloqueio) ocorreu no dispositivo de fila;
-: Uma operao de desenfileiramento (desbloqueio) ocorre no dispositivo de fila;
d: Um pacote foi descartado, normalmente por que a fila est cheia;
r: Um pacote foi recebido por um dispositivo de rede.
Vamos detalhar mais a primeira linha do arquivo de rastreamento. Vamos dividi-la em sees com nmeros de dois
dgitos para referncia:
00
01
02
03
04
05
06
07
08
09
10
+
2
/NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
ns3::PppHeader (
Point-to-Point Protocol: IP (0x0021))
ns3::Ipv4Header (
tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
length: 1052 10.1.1.1 > 10.1.1.2)
ns3::UdpHeader (
length: 1032 49153 > 9)
Payload (size=1024)
A primeira linha do evento expandido (referncia nmero 00) a operao. Temos um caractere +, que corresponde
a uma operao de enfileiramento na fila de transmisso. A segunda linha (referncia 01) o tempo da simulao em
segundos. Lembre-se que pedimos ao UdpEchoClientApplication para iniciar o envio de pacotes depois de
dois segundos (aqui podemos confirmar que isto est acontecendo).
A prxima linha do exemplo (referncia 02) diz qual rastreador de origem iniciou este evento (expressado pelo namespace de rastreamento). Podemos pensar no namespace do rastreamento como algo parecido com um sistema de
arquivos. A raiz do namespace o NodeList. Este corresponde a um gerenciador de container no ncleo ns-3 que
contm todos os ns de rede que foram criados no cdigo. Assim, como um sistema de arquivos pode ter diretrios
dentro da raiz, podemos ter ns de rede no NodeList. O texto /NodeList/0 desta forma refere-se ao n de rede
0 (zero) no NodeList, ou seja o node 0. Em cada ns existe uma lista de dispositivos que esto instalados
nestes ns de rede. Esta lista aparece depois do namespace. Podemos ver que este evento de rastreamento vem do
DeviceList/0 que o dispositivo 0 instalado neste n.
O prximo texto, $ns3::PointToPointNetDevice informa qual o tipo de dispositivo na posio zero da lista
de dispositivos para o n 0 (node 0). Lembre-se que a operao + significa que uma operao de enfileiramento est
acontecendo na fila de transmisso do dispositivo. Isto reflete no segmento final do caminho de rastreamento, que so
TxQueue/Enqueue.
40
As linhas restantes no rastreamento devem ser intuitivas. As referncias 03-04 indicam que o pacote encapsulado
pelo protocolo ponto-a-ponto. Referencias 05-07 mostram que foi usado o cabealho do IP na verso 4, o endereo IP
de origem o 10.1.1.1 e o destino o 10.1.1.2. As referncias 08-09 mostram que o pacote tem um cabealho UDP e
finalmente na referncia 10 apresentado que a rea de dados possui 1024 bytes.
A prxima linha do arquivo de rastreamento mostra que o mesmo pacote inicia o desenfileiramento da fila de transmisso do mesmo n de rede.
A terceira linha no arquivo mostra o pacote sendo recebido pelo dispositivo de rede no n que representa o servidor
de eco. Reproduzimos o evento a seguir.
00 r
01 2.25732
02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
03
ns3::Ipv4Header (
04
tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
05
length: 1052 10.1.1.1 > 10.1.1.2)
06
ns3::UdpHeader (
07
length: 1032 49153 > 9)
08
Payload (size=1024)
A operao agora o r e o tempo de simulao foi incrementado para 2.25732 segundos. Se voc seguiu os passos do
tutorial isto significa que temos o tempo padro tanto para DataRate quanto para o Delay. J vimos este tempo na
seo anterior.
Na referncia 02, a entrada para o namespace foi alterada para refletir o evento vindo do n 1 (/NodeList/1) e o
recebimento do pacote no rastreador de origem (/MacRx). Isto deve facilitar o acompanhamento dos pacotes atravs
da topologia, pois basta olhar os rastros no arquivo.
Insira esta linha depois do cdigo do rastreamento ASCII, no arquivo scratch/myfirst.cc. Repare que passamos apenas o texto myfirst e no myfirst.pcap, isto ocorre por que um prefixo e no um nome de arquivo
completo. O assistente ir criar um arquivo contendo um prefixo e o nmero do n de rede, o nmero de dispositivo e
o sufixo .pcap.
Em nosso cdigo, ns iremos ver arquivos chamados myfirst-0-0.pcap e myfirst-1-0.pcap que so rastreamentos
pcap do dispositivo 0 do n 0 e do dispositivo 0 do n de rede 1, respectivamente.
Uma vez que adicionamos a linha de cdigo que habilita o rastreamento pcap, podemos executar o cdigo da forma
habitual:
./waf --run scratch/myfirst
Se olharmos no diretrio da distribuio, veremos agora trs novos arquivos de registro: myfirst.tr que o arquivo
ASCII, que ns examinamos na seo anterior. myfirst-0-0.pcap e myfirst-1-0.pcap, que so os novos
arquivos pcap gerados.
41
Podemos ver no primeiro dump do arquivo myfirst-0-0.pcap (dispositivo cliente), que o pacote de eco enviado
com dois segundos de simulao. Olhando o segundo dump veremos que o pacote recebido com 2.257324 segundos.
O pacote ecoado de volta com 2.257324 segundos e finalmente recebido de volta pelo cliente com 2.514648
segundos.
Lendo sadas com o Wireshark
Podemos obter o Wireshark em http://www.wireshark.org/, bem como sua documentao.
O Wireshark um programa que usa interface grfica e pode ser usado para mostrar os arquivos de rastreamento. Com
o Wireshark, podemos abrir cada arquivo de rastreamento e visualizar contedo como se tivssemos capturando os
pacotes usando um analisador de trfego de redes (packet sniffer).
42
CAPTULO 6
Construindo topologias
"ns3/core-module.h"
"ns3/network-module.h"
"ns3/csma-module.h"
"ns3/internet-module.h"
"ns3/point-to-point-module.h"
"ns3/applications-module.h"
"ns3/ipv4-global-routing-helper.h"
Algo que pode ser surpreendentemente til uma pequena arte ASCII que mostra um desenho da topologia da rede
construda. Um desenho similar encontrado na maioria dos exemplos no projeto.
Neste caso, possvel perceber que o exemplo ponto-a-ponto (a ligao entre os ns n0 e n1 abaixo) est sendo
estendido, agregando uma rede em barramento ao lado direito. Observe que esta a topologia de rede padro, visto
que o nmero de ns criados na LAN pode ser mudado. Se o atributo nCsma for configurado para um, haver um
total de dois ns na LAN (canal CSMA) um n obrigatrio e um n extra. Por padro, existem trs ns extra,
como pode ser observado:
43
Em seguida, o namespace do ns-3 usado e um componente de registro (log) definido. At aqui, tudo exatamente
como em first.cc, no h nada novo ainda.
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
O programa principal comea com um toque ligeiramente diferente. A varivel verbose usada para determinar
se os componentes de registro de UdpEchoClientApplication e UdpEchoServerApplication estaro
habilitados. O valor padro verdadeiro (os componentes de registro esto ativados), mas possvel desligar durante
os testes de regresso deste exemplo.
Voc ver cdigos familiares que lhe permitiro mudar o nmero de dispositivos na rede CSMA via linha de comando.
Fizemos algo semelhante, quando permitimos que o nmero de pacotes enviados em uma sesso fosse alterado. A
ltima linha garante que voc tenha pelo menos um n extra.
O cdigo consiste em variaes de APIs abordadas anteriormente neste tutorial.
bool verbose = true;
uint32_t nCsma = 3;
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
cmd.Parse (argc, argv);
if (verbose)
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma = nCsma == 0 ? 1 : nCsma;
O prximo passo a criao de dois ns que iremos conectar atravs da ligao ponto-a-ponto. O NodeContainer
usado para fazer isto, assim como foi feito em first.cc.
NodeContainer p2pNodes;
p2pNodes.Create (2);
Em seguida, declaramos outro NodeContainer para manter os ns que sero parte da rede em barramento (CSMA).
Primeiro, instanciamos somente o continer.
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma);
Depois, na prxima linha de cdigo, obtm-se o primeiro n do continer ponto-a-ponto e o adiciona ao continer
de ns que iro receber dispositivos CSMA. O n em questo vai acabar com um dispositivo ponto-a-ponto e um
dispositivo CSMA. Em seguida, criamos uma srie de ns extra que compem o restante da rede CSMA. Visto que
44
j temos um n na rede CSMA aquele que ter tanto um dispositivo ponto-a-ponto quanto um dispositivo de rede
CSMA, o nmero de ns extras representa o nmero desejado de ns na seo CSMA menos um.
Instanciamos um PointToPointHelper e definimos os atributos padres de forma a criar uma transmisso de
cinco megabits por segundo e dois milsimos de segundo de atraso para dispositivos criados utilizando este assistente.
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
Lembre-se que pegamos um dos ns do continer p2pNodes e o adicionamos ao continer csmaNodes. Assim, s
precisamos instalar as pilhas nos ns p2pNodes restantes e todos os ns do continer csmaNodes para abranger
todos os ns na simulao.
Assim como no exemplo first.cc, vamos usar o Ipv4AddressHelper para atribuir endereos IP para as interfaces de nossos dispositivos. Primeiro, usamos a rede 10.1.1.0 para criar os dois endereos necessrios para os
dispositivos ponto-a-ponto.
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
Lembre-se que salvamos as interfaces criadas em um continer para tornar mais fcil a obteno de informaes sobre
o endereamento para uso na criao dos aplicativos.
45
Precisamos agora atribuir endereos IP s interfaces dos dispositivo CSMA. A operao a mesma realizada para o
ponto-a-ponto, exceto que agora estamos realizando a operao em um continer que possui um nmero varivel de
dispositivos CSMA lembre-se que fizemos o nmero de dispositivos CSMA serem passados na linha de comando.
Os dispositivos CSMA sero associados com endereos IP da rede 10.1.2.0, como visto a seguir.
address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
Agora a topologia j est construda, mas precisamos de aplicaes. Esta seo muito similar a seo de aplicaes
do exemplo first.cc, mas vamos instanciar o servidor em um dos ns que tem um dispositivo CSMA e o cliente
em um n que tem apenas um dispositivo ponto-a-ponto.
Primeiro, vamos configurar o servidor de eco. Criamos um UdpEchoServerHelper e fornecemos o atributo obrigatrio do construtor que o nmero da porta. Lembre-se que esta porta pode ser alterada posteriormente, utilizando
o mtodo SetAttribute.
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
Lembre-se que o csmaNodes NodeContainer contm um dos ns criados para a rede ponto-a-ponto e os nCsma
ns extra. O que queremos o ltimo dos ns extra. A entrada zero do continer csmaNodes ser o n pontoa-ponto. O jeito fcil de pensar nisso , ao criar um n CSMA extra, este ser o n um do continer csmaNodes.
Por induo, se criarmos nCsma ns extra, o ltimo ser o de ndice nCsma. Isto ocorre no Get da primeira linha
de cdigo.
A aplicao cliente criada exatamente como fizemos no exemplo first.cc. Novamente, fornecemos os atributos
necessrios no construtor do UdpEchoClientHelper (neste caso, o endereo e porta remotos). Dizemos ao cliente
para enviar pacotes para o servidor. Instalamos o cliente no n ponto-a-ponto mais esquerda visto na ilustrao da
topologia.
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Visto que construmos uma inter-rede, precisamos de alguma forma de roteamento. O ns-3 fornece o que chamamos
de roteamento global para simplificar essa tarefa. O roteamento global tira proveito do fato de que toda a inter-rede
acessvel na simulao ele realiza a disponibilizao do roteamento sem a necessidade de configurar roteadores
individualmente.
Basicamente, o que acontece que cada n se comporta como se fosse um roteador OSPF que se comunica instantaneamente e magicamente com todos os outros roteadores transparentemente. Cada n gera anncios de ligaes e os
comunica diretamente a um gerente de rota global. O gerente, por sua vez, utiliza esta informao para construir as
tabelas de roteamento de cada n. A configurao deste tipo de roteamento realizada em uma linha:
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Em seguida, vamos habilitar o rastreamento pcap. A primeira linha de cdigo para habilita o rastreamento pcap no
assistente ponto-a-ponto. A segunda linha habilita o rastreamento pcap no assistente CSMA e h um parmetro extra
que ainda no havamos usado.
46
pointToPoint.EnablePcapAll ("second");
csma.EnablePcap ("second", csmaDevices.Get (1), true);
A rede CSMA uma rede multi-ponto-a-ponto. Isto significa que pode (e neste caso, de fato h) vrios ns em um
meio compartilhado. Cada um destes ns tem um dispositivo de rede associado. Existem duas alternativas para a
coleta de informaes de rastreamento em uma rede desse tipo. Uma maneira criar um arquivo de rastreamento para
cada dispositivo de rede e armazenar apenas os pacotes que so enviados ou recebidos por esse dispositivo. Outra
maneira escolher um dos dispositivos e coloc-lo em modo promscuo. Esse dispositivo ento sniffs a rede por
todos os pacotes e os armazena em um nico arquivo pcap. Isto como o tcpdump funciona, por exemplo. O ltimo
parmetro informa ao assistente CSMA se deve ou no capturar pacotes em modo promscuo.
Neste exemplo, vamos selecionar um dos dispositivos CSMA e pedir para realizar uma captura promscua na rede,
emulando, assim, o que o tcpdump faria. Se voc estivesse em uma mquina Linux faria algo como tcpdump
-i eth0 para obter o rastreamento. Neste caso, especificamos o dispositivo usando csmaDevices.Get(1), que
seleciona o primeiro dispositivo no continer. Configurando o ltimo parmetro para verdadeiro habilita a captura no
modo promscuo.
A ltima seo do cdigo apenas executa e limpa a simulao como no exemplo first.cc.
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
Para executar este exemplo, copie o arquivo de second.cc para o diretrio scratch e use o comando waf para
compilar exatamente como voc fez com first.cc. Se voc estiver no diretrio raiz do repositrio, digite,
cp examples/tutorial/second.cc scratch/mysecond.cc
./waf
Ateno: Usamos o arquivo second.cc como um dos nossos testes de regresso para verificar se ele funciona
exatamente como achamos que deve, a fim de fazer o seu tutorial uma experincia positiva. Isto significa que um
executvel chamado second j existe no projeto. Para evitar qualquer confuso sobre o que voc est executando,
renomeie para mysecond.cc como sugerido acima.
Se voc est seguindo o tutorial religiosamente (voc est? certo?), ainda vai ter a varivel NS_LOG definida, ento
limpe a varivel e execute o programa.
export NS_LOG=
./waf --run scratch/mysecond
Uma vez que configuramos aplicaes UDP de eco para rastrear, assim como fizemos em first.cc, voc ver uma
sada semelhante quando executar o cdigo.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.415s)
Sent 1024 bytes to 10.1.2.4
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.2.4
Lembre-se que a primeira mensagem, Sent 1024 bytes to 10.1.2.4, o cliente UDP enviando um pacote de eco para o servidor. Neste caso, o servidor est em uma rede diferente (10.1.2.0). A segunda mensagem,
Received 1024 bytes from 10.1.1.1, do servidor de eco, gerado quando ele recebe o pacote de eco.
A mensagem final, Received 1024 bytes from 10.1.2.4, do cliente de eco, indicando que ele recebeu
seu eco de volta.
Se voc olhar no diretrio raiz, encontrar trs arquivos de rastreamento:
47
second-0-0.pcap
second-1-0.pcap
second-2-0.pcap
A primeira linha do despejo (dump) indica que o tipo da ligao PPP (ponto-a-ponto). Voc ento v o pacote
de eco deixando o n zero atravs do dispositivo associado com o endereo IP 10.1.1.1, destinado para o endereo IP
10.1.2.4 (o n CSMA mais direita). Este pacote vai passar pela ligao ponto-a-ponto e ser recebido pelo dispositivo
ponto-a-ponto no n um. Vamos dar uma olhada:
tcpdump -nn -tt -r second-1-0.pcap
Aqui vemos que o tipo de ligao tambm PPP. Vemos nesta interface o pacote do endereo IP 10.1.1.1 (que foi
enviado a 2,000000 segundos) endereado ao IP 10.1.2.4. Agora, internamente a este n, o pacote ser enviado para a
interface CSMA e devemos v-lo saindo nesse dispositivo a caminho de seu destino final.
Lembre-se que selecionamos o n 2 como o sniffer promscuo para a rede CSMA, por isso, vamos analisar o arquivo
second-2-0.pcap.
tcpdump -nn -tt -r second-2-0.pcap
Observamos que o tipo de ligao agora Ethernet. Algo novo apareceu. A rede em barramento necessicita do ARP,
o Address Resolution Protocol. O n um sabe que precisa enviar o pacote para o endereo IP 10.1.2.4, mas no sabe
o endereo MAC do n correspondente. Ele transmite na rede CSMA (ff:ff:ff:ff:ff:ff) pedindo ao dispositivo que tem o
48
endereo IP 10.1.2.4. Neste caso, o n mais direita responde dizendo que est no endereo MAC 00:00:00:00:00:06.
Note que o n dois no est diretamente envolvido nesta troca, mas est capturando todo o trfego da rede.
Esta troca vista nas seguintes linhas,
2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
Em seguida, o n um, dispositivo um, envia o pacote de eco UDP para o servidor no endereo IP 10.1.2.4.
2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
O servidor recebe a solicitao de eco e tenta enviar de volta para a origem. O servidor sabe que este endereo est
em outra rede que chega atravs do endereo IP 10.1.2.1. Isto porque inicializamos o roteamento global. Entretanto, o
n servidor de eco no sabe o endereo MAC do primeiro n CSMA, por isso tem que solicitar via ARP assim como
o primeiro n CSMA teve que fazer.
2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
Observamos o pacote que ecoou vindo de volta para a lingao ponto-a-ponto na ltima linha do despejo.
reading from file second-1-0.pcap, link-type PPP (PPP)
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
Finalmente, lembre-se que adicionamos a habilidade de controlar o nmero de dispositivos CSMA na simulao por
meio da linha de comando. Voc pode alterar esse argumento da mesma forma como quando alteramos o nmero de
pacotes de eco no exemplo first.cc. Tente executar o programa com o nmero de dispositivos extra em quatro:
./waf --run "scratch/mysecond --nCsma=4"
Observe que o servidor de eco foi agora transferido para o ltimo dos ns CSMA, que 10.1.2.5 em vez de o caso
padro, 10.1.2.4.
49
possvel que voc no se satisfaa com um arquivo de rastreamento gerado por um espectador na rede CSMA. Voc
pode querer obter o rastreamento de um nico dispositivo e pode no estar interessado em qualquer outro trfego na
rede. Voc pode fazer isso facilmente.
Vamos dar uma olhada em scratch/mysecond.cc e adicionar o cdigo permitindo-nos ser mais especficos. Os
assistentes do ns-3 fornecem mtodos que recebem um nmero de n e um nmero de dispositivo como parmetros.
Substitua as chamadas EnablePcap pelas seguites:
pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
Sabemos que queremos criar um arquivo pcap com o nome base second e sabemos tambm que o dispositivo de
interesse em ambos os casos vai ser o zero, ento estes parmetros no so interessantes.
A fim de obter o nmero do n, voc tem duas opes: primeiro, os ns so numerados de forma crescente a partir de
zero na ordem em que voc os cria. Uma maneira de obter um nmero de n descobrir este nmero manualmente
atravs da ordem de criao. Se olharmos na ilustrao da topologia da rede no incio do arquivo, perceberemos que
foi o que fizemos. Isto pode ser visto porque o ltimo n CSMA vai ser o de nmero nCsma + 1. Esta abordagem
pode tornar-se muito difcil em simulaes maiores.
Uma maneira alternativa, que usamos aqui, perceber que os NodeContainers contm ponteiros para objetos
Node do ns-3. O objeto Node tem um mtodo chamado GetId que retornar o ID do n, que o nmero do n que
buscamos. Vamos dar uma olhada por Node no Doxygen e localizar esse mtodo, que est mais abaixo no cdigo do
ncleo do que vimos at agora. s vezes voc tem que procurar diligentemente por coisas teis.
Consulte a documentao em Doxygen para a sua distribuio do ns (lembre-se que voc pode encontr-la no site
do projeto). Voc pode chegar a documentao sobre o objeto Node procurando pela guia Classes, at encontrar
ns3::Node na Class List. Selecione ns3::Node e voc ser levado a documentao para a classe Node. Se
voc ir at o mtodo GetId e selecion-lo, ser levado a documentao detalhada do mtodo. Usar o mtodo getId
pode tornar muito mais fcil determinar os nmeros dos ns em topologias complexas.
Vamos limpar os arquivos de rastreamento antigos do diretrio raiz para evitar confuso sobre o que est acontecendo,
rm *.pcap
rm *.tr
Observe que o servidor de eco est agora em 10.1.2.101, que corresponde a ter 100 ns CSMA extras com o servidor
de eco no ltimo. Se voc listar os arquivos pcap no diretrio principal, voc ver,
second-0-0.pcap
second-100-0.pcap
second-101-0.pcap
50
Para ilustrar a diferena entre o rastreamento promscuo e o no promscuo, tambm solicitamos um rastreamento
no-promscuo para o n vizinho ao ltimo. D uma olhada no tcpdump para second-100-0.pcap.
tcpdump -nn -tt -r second-100-0.pcap
Agora observamos que o n 100 realmente um espectador na troca de eco. Os nicos pacotes que ele recebe so os
pedidos ARP que so transmitidos para a rede CSMA inteira (em broadcast).
reading from file second-100-0.pcap, link-type EN10MB (Ethernet)
2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
51
52
como no exemplo second.cc, se voc mudar nCsma, ele lhe dar um nmero extra de ns CSMA. Da mesma
forma, voc pode definir nWifi para controlar quantos ns (estaes) STA sero criados na simulao. Sempre haver
um n AP (access point) na rede sem fio. Por padro, existem trs ns extra no CSMA e trs ns sem fio STA.
O cdigo comea pelo carregamento de mdulos atravs da incluso dos arquivos, assim como no exemplo
second.cc. H algumas novas incluses correspondentes ao mdulo Wifi e ao mdulo de mobilidade que discutiremos a seguir.
#include
#include
#include
#include
#include
#include
#include
#include
"ns3/core-module.h"
"ns3/point-to-point-module.h"
"ns3/network-module.h"
"ns3/applications-module.h"
"ns3/wifi-module.h"
"ns3/mobility-module.h"
"ns3/csma-module.h"
"ns3/internet-module.h"
Observamos que estamos acrescentando um novo dispositivo de rede ao n esquerda da ligao ponto-a-ponto que
se torna o ponto de acesso da rede sem fios. Alguns ns STA sem fio so criados para preencher a nova rede 10.1.3.0,
como mostrado no lado esquerdo da ilustrao.
Aps a ilustrao, o namespace ns-3 usado e um componente de registro definido.
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
O programa principal comea exatamente como em second.cc, adicionando parmetros de linha de comando para
habilitar ou desabilitar componentes de registro e para alterar o nmero de dispositivos criados.
bool verbose = true;
uint32_t nCsma = 3;
uint32_t nWifi = 3;
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
cmd.Parse (argc,argv);
if (verbose)
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
53
Assim como em todos os exemplos anteriores, o prximo passo a criao de dois ns que iro se ligar atravs da
ligao ponto-a-ponto.
NodeContainer p2pNodes;
p2pNodes.Create (2);
Em seguida, instanciamos um PointToPointHelper e definimos os atributos padres para criar uma transmisso
de cinco megabits por segundo e dois milsimos de segundo de atraso para dispositivos que utilizam este assistente.
Ento instalamos os dispositivos nos ns e o canal entre eles.
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
Em seguida, declaramos outro NodeContainer para manter os ns que sero parte da rede em barramento (CSMA).
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma);
A prxima linha de cdigo obtm o primeiro n do continer ponto-a-ponto e o adiciona ao continer de ns que iro
receber dispositivos CSMA. O n em questo vai acabar com um dispositivo ponto-a-ponto e um dispositivo CSMA.
Em seguida, criamos uma srie de ns extra que compem o restante da rede CSMA.
Em seguida, instanciamos um CsmaHelper e definimos seus atributos assim como fizemos no exemplo anterior. Criamos um NetDeviceContainer para gerenciar os dispositivos CSMA criados e ento instalamos dispositivos
CSMA nos ns selecionados.
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
Em seguida, vamos criar os ns que faro parte da rede Wifi. Vamos criar alguns ns estaes, conforme especificado
na linha de comando, e iremos usar o n mais esquerda da rede ponto-a-ponto como o n para o ponto de acesso.
NodeContainer wifiStaNodes;
wifiStaNodes.Create (nWifi);
NodeContainer wifiApNode = p2pNodes.Get (0);
A prxima parte do cdigo constri os dispositivos Wifi e o canal de interligao entre esses ns. Primeiro, vamos
configurar os assistentes PHY e de canal:
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
Para simplificar, este cdigo usa a configurao padro da camada PHY e modelos de canais que
esto documentados na API doxygen para os mtodos YansWifiChannelHelper::Default e
YansWifiPhyHelper::Default. Uma vez que esses objetos so instanciados, criamos um objeto de canal e associamos ele ao nosso gerente de objetos da camada PHY para nos certificarmos de que todos os objetos
da camada PHY criados pelo YansWifiPhyHelper compartilham o mesmo canal subjacente, isto , eles
compartilham o mesmo meio fsico sem fio e podem comunicar-se e interferir:
phy.SetChannel (channel.Create ());
54
Uma vez que o assistente PHY est configurado, podemos nos concentrar na camada MAC. Aqui escolhemos trabalhar
com MACs no-Qos, por isso usamos um objeto NqosWifiMacHelper para definir os parmetros MAC.
WifiHelper wifi = WifiHelper::Default ();
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
O mtodo SetRemoteStationManager diz ao assistente o tipo de algoritmo de controle de taxa a usar. Aqui, ele
est pedindo ao assistente para usar o algoritmo AARF os detalhes esto disponveis no Doxygen.
Em seguida, configuramos o tipo de MAC, o SSID da rede de infraestrutura, e nos certificamos que as estaes no
realizam sondagem ativa (active probing):
Ssid ssid = Ssid ("ns-3-ssid");
mac.SetType ("ns3::StaWifiMac",
"Ssid", SsidValue (ssid),
"ActiveProbing", BooleanValue (false));
Este cdigo primeiro cria um objeto de um identificador de conjunto de servios (SSID 802.11) que ser utilizado para
definir o valor do atributo Ssid da implementao da camada MAC. O tipo particular da camada MAC que ser criado
pelo assistente especificado como sendo do tipo ns3::StaWifiMac. O uso do assistente NqosWifiMacHelper
ir garantir que o atributo QosSupported para os objetos MAC criados ser falso. A combinao destas duas configuraes implica que a instncia MAC criada em seguida ser uma estao (STA) no-QoS e no-AP, em uma
infraestrutura BSS (por exemplo, uma BSS com um AP). Finalmente, o atributo ActiveProbing definido como
falso. Isto significa que as solicitaes de sondagem no sero enviados pelos MACs criados por este assistente.
Depois que todos os parmetros especficos das estaes esto completamente configurados, tanto na camada MAC
como na PHY, podemos invocar o nosso mtodo j familiar Instalar para criar os dispositivos Wifi destas estaes:
NetDeviceContainer staDevices;
staDevices = wifi.Install (phy, mac, wifiStaNodes);
J configuramos o Wifi para todos ns STA e agora precisamos configurar o AP. Comeamos esse processo mudando
o atributo padro NqosWifiMacHelper para refletir os requisitos do AP.
mac.SetType ("ns3::ApWifiMac",
"Ssid", SsidValue (ssid)));
Neste caso, o NqosWifiMacHelper vai criar camadas MAC do ns3::ApWifiMac, este ltimo especificando que
uma instncia MAC configurado como um AP deve ser criado, com o tipo de assistente implicando que o atributo
QosSupported deve ser definido como falso - desativando o suporte a Qos do tipo 802.11e/WMM nos APs criados.
As prximas linhas criam um AP que compartilha os mesmos atributos a nvel PHY com as estaes:
NetDeviceContainer apDevices;
apDevices = wifi.Install (phy, mac, wifiApNode);
Agora, vamos adicionar modelos de mobilidade. Queremos que os ns STA sejam mveis, vagando dentro de uma
caixa delimitadora, e queremos fazer o n AP estacionrio. Usamos o MobilityHelper para facilitar a execuo desta tarefa. Primeiro, instanciamos um objeto MobilityHelper e definimos alguns atributos controlando a
funcionalidade de alocao de posio.
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (10.0),
55
Este cdigo diz ao assistente de mobilidade para usar uma grade bidimensional para distribuir os ns STA. Sinta-se
vontade para explorar a classe ns3::GridPositionAllocator no Doxygen para ver exatamente o que est
sendo feito.
Arranjamos os ns em uma grade inicial, mas agora precisamos dizer-lhes como se mover. Escolhemos o modelo
RandomWalk2dMobilityModel em que os ns se movem em uma direo aleatria a uma velocidade aleatria
dentro de um delimitador quadrado.
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
Queremos que o ponto de acesso permanea em uma posio fixa durante a simulao. Conseguimos isto definindo o
modelo de mobilidade para este n como ns3::ConstantPositionMobilityModel:
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiApNode);
Agora temos os nossos ns, dispositivos e canais e modelos de mobilidade escolhidos para os ns Wifi, mas no temos
pilhas de protocolo. Assim como j fizemos muitas vezes, usaremos o InternetStackHelper para instalar estas
pilhas.
InternetStackHelper stack;
stack.Install (csmaNodes);
stack.Install (wifiApNode);
stack.Install (wifiStaNodes);
Assim como no exemplo second.cc, vamos usar o Ipv4AddressHelper para atribuir endereos IP para as
interfaces de nossos dispositivos. Primeiro, usamos a rede 10.1.1.0 para criar os dois endereos necessrios para os
dois dispositivos ponto-a-ponto. Ento, usamos rede 10.1.2.0 para atribuir endereos rede CSMA e, por ltimo,
atribuir endereos da rede 10.1.3.0 para ambos os dispositivos STA e o ponto de acesso na rede sem fio.
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
address.SetBase ("10.1.3.0", "255.255.255.0");
address.Assign (staDevices);
address.Assign (apDevices);
56
E colocamos o cliente de eco no ltimo n STA criado, apontando-o para o servidor na rede CSMA.
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps =
echoClient.Install (wifiStaNodes.Get (nWifi - 1));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Uma vez que construmos uma inter-rede aqui, precisamos ativar o roteamento inter-redes, assim como fizemos no
exemplo second.cc.
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Algo que pode surpreender alguns usurios o fato de que a simulao que acabamos de criar nunca vai parar naturalmente. Isto acontece porque pedimos para o ponto de acesso gerar beacons. Ele ir gerar beacons para sempre,
e isso ir resultar em eventos sendo escalonados no futuro indefinidamente, por isso devemos dizer para o simulador
parar, ainda que hajam eventos de gerao de beacons agendados. A seguinte linha de cdigo informa ao simulador
para parar, para que no simulemos beacons para sempre e entremos no que essencialmente um lao sem fim.
Simulator::Stop (Seconds (10.0));
Estas trs linhas de cdigo iro iniciar o rastreamento do pcap em ambos os ns ponto-a-ponto que funcionam como
nosso backbone, iro iniciar um modo promscuo (monitor) de rastreamento na rede Wifi e na rede CSMA. Isto vai
permitir ver todo o trfego com um nmero mnimo de arquivos de rastreamento.
Finalmente, executamos a simulao, limpamos e, em seguida, saimos do programa.
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
Para executar este exemplo, voc deve copiar o arquivo third.cc para o diretrio scratch e usar o Waf para
compilar exatamente como com o exemplo second.cc. Se voc est no diretrio raiz do repositrio voc dever
digitar,
cp examples/tutorial/third.cc scratch/mythird.cc
./waf
./waf --run scratch/mythird
Novamente, uma vez que configuramos aplicaes de eco UDP, assim como fizemos no arquivo second.cc, voc
ver uma sada similar.
Waf: Entering directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
Waf: Leaving directory /home/craigdo/repos/ns-3-allinone/ns-3-dev/build
build finished successfully (0.407s)
Sent 1024 bytes to 10.1.2.4
Received 1024 bytes from 10.1.3.3
Received 1024 bytes from 10.1.2.4
57
Lembre-se que a primeira mensagem, Sent 1024 bytes to 10.1.2.4, o cliente de eco UDP enviando um
pacote para o servidor. Neste caso, o cliente est na rede wireless (10.1.3.0). A segunda mensagem, Received
1024 bytes from 10.1.3.3, do servidor de eco UDP, gerado quando este recebe o pacote de eco. A mensagem final, Received 1024 bytes from 10.1.2.4, do cliente de eco, indicando que este recebeu o seu
eco de volta do servidor.
No diretrio raiz, encontraremos quatro arquivos de rastreamento desta simulao, dois do n zero e dois do n um:
third-0-0.pcap
third-0-1.pcap
third-1-0.pcap
third-1-1.pcap
IBSS
Mbit]
Mbit]
Mbit]
IBSS
IBSS
IBSS
Observamos que o tipo de ligao agora 802.11, como esperado. Voc provavelmente vai entender o que est
acontecendo e encontrar o pacote de pedido de eco e a resposta nesta sada de rastreamento. Vamos deixar como um
exerccio a anlise completa da sada.
Agora, analisando o arquivo pcap do lado direito da ligao ponto-a-ponto,
tcpdump -nn -tt -r third-0-0.pcap
Este o pacote de eco indo da esquerda para a direita (do Wifi para o CSMA) e de volta atravs da ligao ponto-aponto.
Agora, analisando o arquivo pcap do lado direito da ligao ponto-a-ponto,
58
Este o pacote de eco indo da esquerda para a direita (do Wifi para o CSMA) e depois voltando atravs do ligao
ponto-a-ponto com tempos um pouco diferentes, como esperado.
O servidor de eco est na rede CSMA, vamos olhar para a sada de rastreamento promscua:
tcpdump -nn -tt -r third-1-1.pcap
Isto deve ser de fcil entendimento. Se esqueceu, volte e olhe para a discusso em second.cc. Este exemplo segue
a mesma seqncia.
Passamos algum tempo com a criao de modelos de mobilidade para a rede sem fio e por isso seria uma vergonha
encerrar sem mostrar que os ns STA esto realmente se movendo durante a simulao. Vamos fazer isto ligando o
MobilityModel fonte de rastreamento. Isto apenas uma viso geral da seo que detalha o rastreamento, mas
um timo lugar para um exemplo.
Como mencionado na seo Aperfeioando, o sistema de rastreamento dividido em origem de rastreamento e
destino de rastreamento, com funes para conectar um ao outro. Vamos usar a mudana de curso padro do modelo
de mobilidade para originar os eventos de rastreamento. Vamos precisar escrever um destino de rastreamento para se
conectar a origem que ir exibir algumas informaes importantes. Apesar de sua reputao como difcil, de fato
muito simples. Antes do programa principal do cdigo scratch/mythird.cc, adicione a seguinte funo:
void
CourseChange (std::string context, Ptr<const MobilityModel> model)
{
Vector position = model->GetPosition ();
NS_LOG_UNCOND (context <<
" x = " << position.x << ", y = " << position.y);
}
Este cdigo obtm as informaes de posio do modelo de mobilidade e registra a posio x e y do n. Vamos
criar o cdigo para que esta funo seja chamada toda vez que o n com o cliente de eco mude de posio. Fazemos
isto usando a funo Config::Connect. Adicione as seguintes linhas de cdigo no cdigo antes da chamada
Simulator::Run.
std::ostringstream oss;
oss <<
"/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
"/$ns3::MobilityModel/CourseChange";
Config::Connect (oss.str (), MakeCallback (&CourseChange));
59
O que fazemos aqui criar uma string contendo o caminho do namespace de rastreamento do evento ao qual se deseja
conectar. Primeiro, temos que descobrir qual n que queremos usando o mtodo GetId como descrito anteriormente.
No caso de usar o nmero padro do CSMA e dos ns de rede sem fio, este acaba sendo o n sete e o caminho do
namespace de rastreamento para o modelo de mobilidade seria:
/NodeList/7/$ns3::MobilityModel/CourseChange
Com base na discusso na seo de rastreamento, voc pode inferir que este caminho referencia o stimo n na lista
NodeList global. Ele especifica o que chamado de um objeto agregado do tipo ns3::MobilityModel. O prefixo
cifro implica que o MobilityModel agregado ao n sete. O ltimo componente do caminho significa que estamos
ligando ao evento CourseChange desse modelo.
Fazemos uma conexo entre a origem de rastreamento no n sete com o nosso destino de rastreamento chamando
Config::Connect e passando o caminho do namespace como parmetro. Feito isto, cada evento de mudana de
curso no n sete ser capturado em nosso destino de rastreamento, que por sua vez ir imprimir a nova posio.
Se voc executar a simulao, ver as mudanas de curso assim que elas ocorrerem.
Build finished successfully (00:00:01)
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
Sent 1024 bytes to 10.1.2.4
Received 1024 bytes from 10.1.3.3
Received 1024 bytes from 10.1.2.4
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
/NodeList/7/$ns3::MobilityModel/CourseChange
60
x
x
x
x
x
x
x
=
=
=
=
=
=
=
10, y = 0
9.41539, y = -0.811313
8.46199, y = -1.11303
7.52738, y = -1.46869
6.67099, y = -1.98503
5.6835, y = -2.14268
4.70932, y = -1.91689
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
x
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
5.53175, y = -2.48576
4.58021, y = -2.17821
4.18915, y = -1.25785
4.7572, y = -0.434856
4.62404, y = 0.556238
4.74127, y = 1.54934
5.73934, y = 1.48729
6.18521, y = 0.59219
6.58121, y = 1.51044
7.27897, y = 2.22677
6.42888, y = 1.70014
7.40519, y = 1.91654
6.51981, y = 1.45166
7.34588, y = 2.01523
7.81046, y = 2.90077
6.89186, y = 3.29596
7.46617, y = 2.47732
7.05492, y = 1.56579
8.00393, y = 1.25054
7.00968, y = 1.35768
7.33503, y = 2.30328
7.18682, y = 3.29223
7.96865, y = 2.66873
CAPTULO 7
Rastreamento
7.1 Introduo
Como abordado na seo Usando o Sistema de Rastreamento, o objetivo principal de uma simulao no ns-3 a gerao de sada para estudo. H duas estratgias bsicas: usar mecanismos predefinidos de sada e processar o contedo
para extrair informaes relevantes; ou desenvolver mecanismos de sada que resultam somente ou exatamente na
informao pretendida.
Usar mecanismos predefinidos de sada possui a vantagem de no necessitar modificaes no ns-3, mas requer programao. Geralmente, as mensagens de sada do pcap ou NS_LOG so coletadas durante a execuo da simulao e
processadas separadamente por cdigos (scripts) que usam grep, sed ou awk para reduzir e transformar os dados para
uma forma mais simples de gerenciar. H o custo do desenvolvimento de programas para realizar as transformaes
e em algumas situaes a informao de interesse pode no estar contida em nenhuma das sadas, logo, a abordagem
falha.
Se precisarmos adicionar o mnimo de informao para os mecanismos predefinidos de sada, isto certamente pode ser
feito e se usarmos os mecanismos do ns-3, podemos ter nosso cdigo adicionado como uma contribuio.
O ns-3 fornece outro mecanismo, chamado Rastreamento (Tracing), que evita alguns dos problemas associados com
os mecanismos de sada predefinidos. H vrias vantagens. Primeiro, reduo da quantidade de dados para gerenciar
(em simulaes grandes, armazenar toda sada no disco pode gerar gargalos de Entrada/Sada). Segundo, o formato
da sada pode ser controlado diretamente evitando o ps-processamento com cdigos sed ou awk. Se desejar, a sada
pode ser processada diretamente para um formato reconhecido pelo gnuplot, por exemplo. Podemos adicionar ganchos
(hooks) no ncleo, os quais podem ser acessados por outros usurios, mas que no produziro nenhuma informao
exceto que sejam explicitamente solicitados a produzir. Por essas razes, acreditamos que o sistema de rastreamento
do ns-3 a melhor forma de obter informaes fora da simulao, portanto um dos mais importantes mecanismos
para ser compreendido no ns-3.
61
uint32_t x = SOME_INTERESTING_VALUE;
...
std::cout << "The value of x is " << x << std::endl;
...
}
Ningum impedir que editemos o ncleo do ns-3 e adicionemos cdigos de impresso. Isto simples de fazer,
alm disso temos controle e acesso total ao cdigo fonte do ns-3. Entretanto, pensando no futuro, isto no muito
interessante.
Conforme aumentarmos o nmero de comandos de impresso em nossos programas, ficar mais difcil tratar a grande
quantidade de sadas. Eventualmente, precisaremos controlar de alguma maneira qual a informao ser impressa;
talvez habilitando ou no determinadas categorias de sadas, ou aumentando ou diminuindo a quantidade de informao desejada. Se continuarmos com esse processo, descobriremos depois de um tempo que, reimplementamos o
mecanismo NS_LOG. Para evitar isso, utilize o prprio NS_LOG.
Como abordado anteriormente, uma maneira de obter informao de sada do ns-3 processar a sada do NS_LOG,
filtrando as informaes relevantes. Se a informao no est presente nos registros existentes, pode-se editar o ncleo
do ns-3 e adicionar ao fluxo de sada a informao desejada. Claro, isto muito melhor que adicionar comandos de
impresso, desde que seguindo as convenes de codificao do ns-3, alm do que isto poderia ser potencialmente til
a outras pessoas.
Vamos analisar um exemplo, adicionando mais informaes de registro ao socket TCP do arquivo
tcp-socket-base.cc, para isto vamos acrescentando uma nova mensagem de registro na implementao. Observe que em TcpSocketBase::ReceivedAck() no existem mensagem de registro para casos sem o ACK,
ento vamos adicionar uma da seguinte forma:
/** Processa o mais recente ACK recebido */
void
TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
{
NS_LOG_FUNCTION (this << tcpHeader);
// ACK Recebido. Compara o nmero ACK com o mais alto seqno no confirmado
if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK))
{ // Ignora se no h flag ACK
}
...
Isto pode parecer simples e satisfatrio a primeira vista, mas lembre-se que ns escreveremos cdigo para adicionar
ao NS_LOG e para processar a sada com a finalidade de isolar a informao de interesse. Isto porque o controle
limitado ao nvel do componente de registro.
Se cada desenvolvedor adicionar cdigos de sada para um mdulo existente, logo conviveremos com a sada que outro
62
Captulo 7. Rastreamento
desenvolvedor achou interessante. descobriremos que para obter uma pequena quantidade de informao, precisaremos produzir uma volumosa quantidade de mensagens sem nenhuma relevncia (devido aos comandos de sada de
vrios desenvolvedores). Assim seremos forados a gerar arquivos de registros gigantescos no disco e process-los
para obter poucas linhas de nosso interesse.
Como no h nenhuma garantia no ns-3 sobre a estabilidade da sada do NS_LOG, podemos descobrir que partes do
registro de sada, que dependamos, desapareceram ou mudaram entre verses. Se dependermos da estrutura da sada,
podemos encontrar outras mensagens sendo adicionadas ou removidas que podem afetar seu cdigo de processamento.
Por estas razes, devemos considerar o uso do std::cout e as mensagens NS_LOG como formas rpidas e porm
sujas de obter informao da sada no ns-3.
Na grande maioria dos casos desejamos ter um mecanismo estvel, usando APIs que permitam acessar o ncleo do
sistema e obter somente informaes interessantes. Isto deve ser possvel sem que exista a necessidade de alterar e
recompilar o ncleo do sistema. Melhor ainda seria se um sistema notificasse o usurio quando um item de interesse
fora modificado ou um evento de interesse aconteceu, pois o usurio no teria que constantemente vasculhar o sistema
procurando por coisas.
O sistema de rastreamento do ns-3 projetado para trabalhar seguindo essas premissas e integrado com os subsistemas de Atributos (Attribute) e Configurao (Config) permitindo cenrios de uso simples.
63
Callbacks
O objetivo do sistema de Callback, no ns-3, permitir a uma parte do cdigo invocar uma funo (ou mtodo em C++)
sem qualquer dependncia entre mdulos. Isto utilizado para prover algum tipo de indireo desta forma tratamos
o endereo da chamada de funo como uma varivel. Esta varivel denominada varivel de ponteiro-para-funo.
O relacionamento entre funo e ponteiro-para-funo no to diferente que de um objeto e ponteiro-para-objeto.
Em C, o exemplo clssico de um ponteiro-para-funo um ponteiro-para-funo-retornando-inteiro (PFI). Para um
PFI ter um parmetro inteiro, poderia ser declarado como,
int (*pfi)(int arg) = 0;
O cdigo descreve uma varivel nomeada como pfi que inicializada com o valor 0. Se quisermos inicializar este
ponteiro com um valor significante, temos que ter uma funo com uma assinatura idntica. Neste caso, poderamos
prover uma funo como,
int MyFunction (int arg) {}
Podemos ento chamar MyFunction indiretamente, usando uma forma mais clara da chamada,
int result = (*pfi) (1234);
uma forma mais clara, pois como se estivssemos dereferenciando o ponteiro da funo como dereferenciamos
qualquer outro ponteiro. Tipicamente, todavia, usa-se uma forma mais curta pois o compilador sabe o que est fazendo,
int result = pfi (1234);
Esta forma como se estivessemos chamando uma funo nomeada pfi, mas o compilador reconhece que uma
chamada indireta da funo MyFunction por meio da varivel pfi.
Conceitualmente, quase exatamente como o sistema de rastreamento funciona. Basicamente, uma origem do rastreamento um callback. Quando um destino do rastreamento expressa interesse em receber eventos de rastreamento,
ela adiciona a callback para a lista de callbacks mantida internamente pela origem do rastreamento. Quando um
evento de interesse ocorre, a origem do rastreamento invoca seu operator() provendo zero ou mais parmetros. O
operator() eventualmente percorre o sistema e faz uma chamada indireta com zero ou mais parmetros.
Uma diferena importante que o sistema de rastreamento adiciona para cada origem do rastreamento uma lista interna
de callbacks. Ao invs de apenas fazer uma chamada indireta, uma origem do rastreamento pode invocar qualquer
nmero de callbacks. Quando um destino do rastreamento expressa interesse em notificaes de uma origem, ela
adiciona sua prpria funo para a lista de callback.
Estando interessado em mais detalhes sobre como organizado o sistema de callback no ns-3, leia a seo Callback
do manual.
Cdigo de Exemplo
Analisaremos uma implementao simples de um exemplo de rastreamento. Este cdigo est no diretrio do tutorial,
no arquivo fourth.cc.
/*
/*
*
*
*
*
64
Captulo 7. Rastreamento
USA
"ns3/object.h"
"ns3/uinteger.h"
"ns3/traced-value.h"
"ns3/trace-source-accessor.h"
#include <iostream>
using namespace ns3;
A maior parte deste cdigo deve ser familiar, pois como j abordado, o sistema de rastreamento faz uso constante dos
sistemas Objeto (Object) e Atributos (Attribute), logo necessrio inclu-los. As duas primeiras incluses (include)
declaram explicitamente estes dois sistemas. Poderamos usar o cabealho (header) do mdulo ncleo, este exemplo
simples.
O arquivo traced-value.h uma declarao obrigatria para rastreamento de dados que usam passagem por
valor. Na passagem por valor passada uma cpia do objeto e no um endereo. Com a finalidade de usar passagem
por valor, precisa-se de um objeto com um construtor de cpia associado e um operador de atribuio. O conjunto de
operadores predefinidos para tipos de dados primitivos (plain-old-data) so ++, , +, ==, etc.
Isto significa que somos capazes de rastrear alteraes em um objeto C++ usando estes operadores.
Como o sistema de rastreamento integrado com Atributos e este trabalham com Objetos, deve obrigatoriamente
existir um Object ns-3 para cada origem do rastreamento. O prximo cdigo define e declara um Objeto.
class MyObject : public Object
{
public:
static TypeId GetTypeId (void)
{
static TypeId tid = TypeId ("MyObject")
.SetParent (Object::GetTypeId ())
.AddConstructor<MyObject> ()
.AddTraceSource ("MyInteger",
"An integer value to trace.",
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
return tid;
}
MyObject () {}
TracedValue<int32_t> m_myInt;
};
65
void
IntTrace (int32_t oldValue, int32_t newValue)
{
std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
}
Esta a definio do destino do rastreamento. Isto corresponde diretamente a funo de callback. Uma vez que est
conectada, esta funo ser chamada sempre que um dos operadores sobrecarregados de TracedValue executado.
Ns temos a origem e o destino do rastreamento. O restante o cdigo para conectar a origem ao destino.
int
main (int argc, char *argv[])
{
Ptr<MyObject> myObject = CreateObject<MyObject> ();
myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));
myObject->m_myInt = 1234;
}
deveria ser interpretada como uma invocao do operador = na varivel membro m_myInt com o inteiro 1234
passado como parmetro.
Por sua vez este operador definido (por TracedValue) para executar um callback que retorna void e possui dois
inteiros como parmetros um valor antigo e um novo valor para o inteiro em questo. Isto exatamente a assinatura
da funo para a funo de callback que ns fornecemos IntTrace.
Para resumir, uma origem do rastreamento , em essncia, uma varivel que mantm uma lista de callbacks. Um
destino do rastreamento uma funo usada como alvo da callback. O Atributo e os sistemas de informao de tipo
de objeto so usados para fornecer uma maneira de conectar origens e destinos do rastreamento. O ao de acionar
uma origem do rastreamento executar um operador na origem, que dispara os callbacks. Isto resulta na execuo das
callbacks dos destinos do rastreamento registrados na origem com os parmetros providos pela origem.
Se compilarmos e executarmos este exemplo,
./waf --run fourth
observaremos que a sada da funo IntTrace processada logo aps a execuo da origem do rastreamento:
66
Captulo 7. Rastreamento
Traced 0 to 1234
Quando executamos o cdigo, myObject->m_myInt = 1234; a origem do rastreamento disparou e automaticamente forneceu os valores anteriores e posteriores para o destino do rastreamento. A funo IntTrace ento
imprimiu na sada padro, sem maiores problemas.
Quando conectamos a origem do rastreamento CourseChange para o destino do rastreamento anteriormente, usamos o que chamado de caminho de configurao (Config Path) para especificar a origem e o novo destino do
rastreamento.
std::ostringstream oss;
oss <<
"/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
"/$ns3::MobilityModel/CourseChange";
Config::Connect (oss.str (), MakeCallback (&CourseChange));
Para entendermos melhor o cdigo, suponha que o nmero do n retornado por GetId() 7. Neste caso, o
caminho seria,
"/NodeList/7/$ns3::MobilityModel/CourseChange"
O ltimo segmento de um caminho de configurao deve ser um Atributo de um Objeto. Na verdade, se tnhamos um
ponteiro para o Objeto que tem o Atributo CourseChange , poderamos escrever como no exemplo
anterior. Ns j sabemos que guardamos tipicamente ponteiros para outros ns
em um NodeContainer. No exemplo third.cc, os ns de rede de interesse esto armazenados no
wifiStaNodes NodeContainer. De fato enquanto colocamos o caminho junto usamos este continer para
obter um Ptr<Node>, usado na chamada GetId(). Poderamos usar diretamente o Ptr<Node> para chamar um
mtodo de conexo.
Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
theObject->TraceConnectWithoutContext ("CourseChange", MakeCallback (&CourseChange));
No exemplo third.cc, queremos um contexto adicional para ser encaminhado com os parmetros do callback
(os quais so explicados a seguir) ento podemos usar o cdigo equivalente,
Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
theObject->TraceConnect ("CourseChange", MakeCallback (&CourseChange));
67
Acontece que o cdigo interno para Config::ConnectWithoutContext e Config::Connect permite localizar um Ptr<Object> e chama o mtodo TraceConnect, no nvel mais baixo.
As funes Config aceitam um caminho que representa uma cadeia de ponteiros de Objetos. Cada segmento do
caminho corresponde a um Atributo Objeto. O ltimo segmento o Atributo de interesse e os seguimentos anteriores
devem ser definidos para conter ou encontrar Objetos. O cdigo Config processa o caminho at obter o segmento
final. Ento, interpreta o ltimo segmento como um Atributo no ltimo Objeto ele encontrou no caminho. Ento as
funes Config chamam o mtodo TraceConnect ou TraceConnectWithoutContext adequado no Objeto
final.
Vamos analisar com mais detalhes o processo descrito.
O primeiro caractere / no caminho faz referncia a um namespace. Um dos namespaces predefinidos no sistema
de configurao NodeList que uma lista de todos os ns na simulao. Itens na lista so referenciados por
ndices , logo /NodeList/7 refere-se ao oitavo n na lista de ns criados durante a simulao. Esta referncia um
Ptr<Node>, por consequncia uma subclasse de um ns3::Object.
Como descrito na seo Modelo de Objeto do manual ns-3, h suporte para Agregao de Objeto. Isto permite realizar
associao entre diferentes Objetos sem qualquer programao. Cada Objeto em uma Agregao pode ser acessado a
partir de outros Objetos.
O prximo segmento no caminho inicia com o carcter $. O cifro indica ao sistema de configurao que uma
chamada GetObject deveria ser realizada procurando o tipo especificado em seguida. diferente do que o
MobilityHelper usou em third.cc gerenciar a Agregao, ou associar, um modelo de mobilidade para cada
dos ns de rede sem fio. Quando adicionamos o $, significa que estamos pedindo por outro Objeto que tinha
sido presumidamente agregado anteriormente. Podemos pensar nisso como ponteiro de comutao do Ptr<Node>
original como especificado por /NodeList/7 para os modelos de mobilidade associados quais so do tipo
$ns3::MobilityModel. Se estivermos familiarizados com GetObject, solicitamos ao sistema para fazer o seguinte:
Ptr<MobilityModel> mobilityModel = node->GetObject<MobilityModel> ()
Classes derivadas chamaro este mtodo toda vez que fizerem uma alterao na rota para suportar rastreamento. Este
mtodo invoca operator() em m_courseChangeTrace, que invocar todos os callbacks registrados, chamando
todos os trace sinks que tem interesse registrado na origem do rastreamento usando a funo de Configurao.
68
Captulo 7. Rastreamento
No exemplo third.cc ns vimos que sempre que uma mudana de rota realizada em uma das instncias
RandomWalk2dMobilityModel instaladas, haver uma chamada NotifyCourseChange() da classe base
MobilityModel. Como observado, isto invoca operator() em m_courseChangeTrace, que por sua vez,
chama qualquer destino do rastreamento registrados. No exemplo, o nico cdigo que registrou interesse foi aquele
que forneceu o caminho de configurao. Consequentemente, a funo CourseChange que foi ligado no Node de
nmero sete ser a nica callback chamada.
A pea final do quebra-cabea o contexto. Lembre-se da sada de third.cc:
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
A primeira parte da sada o contexto. simplesmente o caminho pelo qual o cdigo de configurao localizou a
origem do rastreamento. No caso, poderamos ter qualquer nmero de origens de rastreamento no sistema correspondendo a qualquer nmero de ns com modelos de mobilidade. necessrio uma maneira de identificar qual origem
do rastreamento disparou o callback. Uma forma simples solicitar um contexto de rastreamento quando usado o
Config::Connect.
No caso, esta foi a origem do rastreamento usada no exemplo third.cc, esta lista ser muito til.
69
e poderemos encontrar um cdigo operacional que atenda nossas necessidades. Por exemplo, neste caso,
./ns-3-dev/examples/wireless/mixed-wireless.cc tem algo que podemos usar:
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
MakeCallback (&CourseChangeCallback));
Se no localizamos nenhum exemplo na distribuio, podemos tentar o Doxygen do ns-3. provavelmente mais
simples que percorrer o exemplo CourseChanged.
Suponha que encontramos a origem do rastreamento CourseChanged na The list of all trace sources e queremos
resolver como nos conectar a ela. Voc sabe que est usando um ns3::RandomWalk2dMobilityModel. Logo,
acesse o item Class List na documentao do ns-3. Ser exibida a lista de todas as classes. Selecione a entrada para
ns3::RandomWalk2dMobilityModel para exibir a documentao da classe.
Acesse a seo Member Function Documentation e obter a documentao para a funo GetTypeId. Voc
construiu uma dessas em um exemplo anterior:
static TypeId GetTypeId (void)
{
static TypeId tid = TypeId ("MyObject")
.SetParent (Object::GetTypeId ())
.AddConstructor<MyObject> ()
.AddTraceSource ("MyInteger",
"An integer value to trace.",
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
return tid;
}
Como abordado, este cdigo conecta os sistemas Config e Atributos origem do rastreamento. tambm o local onde
devemos iniciar a busca por informao sobre como conectar.
Voc est observando a mesma informao para RandomWalk2dMobilityModel; e a informao que voc precisa est explcita no Doxygen:
This object is accessible through the following paths with Config::Set
and Config::Connect:
/NodeList/[i]/$ns3::MobilityModel/$ns3::RandomWalk2dMobilityModel
A documentao apresenta como obter o Objeto RandomWalk2dMobilityModel. Compare o texto anterior com
o texto que ns usamos no cdigo do exemplo:
"/NodeList/7/$ns3::MobilityModel"
70
Captulo 7. Rastreamento
e
voc
poder
encontrar
cdigo
operacional.
Por
exemplo,
neste
./ns-3-dev/examples/wireless/mixed-wireless.cc tem cdigo para ser reaproveitado.
caso,
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
MakeCallback (&CourseChangeCallback));
como resultado, MakeCallback indicaria que h uma funo callback que pode ser usada. Para reforar:
static void
CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
{
...
}
No h uma correspondncia de um-para-um entre a lista de parmetro padro na declarao e os argumentos formais
da funo callback. Aqui, h um parmetro padro, que um Ptr<const MobilityModel>. Isto significa que
precisamos de uma funo que retorna void e possui um parmetro Ptr<const MobilityModel>. Por exemplo,
void
CourseChangeCallback (Ptr<const MobilityModel> model)
{
...
}
71
Isto tudo que precisamos para Config::ConnectWithoutContext. Se voc quer um contexto, use
Config::Connect e uma funo callback que possui como um parmetro uma string de contexto, seguido pelo
argumento.
void
CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
{
...
}
Para garantir que CourseChangeCallback seja somente visvel em seu arquivo, voc pode adicionar a palavra
chave static, como no exemplo:
static void
CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
{
...
}
Esta declarao para um template. O parmetro do template est entre <>, logo estamos interessados em descobrir
o que TracedCallback<>. Se no tem nenhuma ideia de onde pode ser encontrado, use o utilitrio grep.
Estamos interessados em uma declarao similar no cdigo fonte do ns-3, logo buscamos no diretrio src. Ento,
sabemos que esta declarao tem um arquivo de cabealho, e procuramos por ele usando:
find . -name *.h | xargs grep TracedCallback
Obteremos 124 linhas, com este comando. Analisando a sada, encontramos alguns templates que podem ser teis.
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::TracedCallback ()
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext (c ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Connect (const CallbackB ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::DisconnectWithoutContext ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Disconnect (const Callba ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (void) const ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1) const ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
Observamos que todas linhas so do arquivo de cabealho traced-callback.h, logo ele parece muito promissor.
Para confirmar, verifique o arquivo mobility-model.h e procure uma linha que corrobore esta suspeita.
72
Captulo 7. Rastreamento
#include "ns3/traced-callback.h"
=
=
=
=
empty,
empty,
empty,
empty,
typename
typename
typename
typename
T2
T4
T6
T8
=
=
=
=
empty,
empty,
empty,
empty>
Isto significa que TracedCallback uma classe genrica (templated class). Possui oito possveis tipos de parmetros
com valores padres. Retorne e compare com a declarao que voc est tentando entender:
TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
O typename T1 na declarao da classe corresponde a Ptr<const MobilityModel> da declarao anterior. Todos os outros parmetros so padres. Observe que o construtor no contribui com muita informao. O
nico lugar onde h uma conexo entre a funo callback e o sistema de rastreamento nas funes Connect e
ConnectWithoutContext. Como mostrado a seguir:
template<typename T1, typename T2,
typename T3, typename T4,
typename T5, typename T6,
typename T7, typename T8>
void
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext ...
{
Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> cb;
cb.Assign (callback);
m_callbackList.push_back (cb);
}
Voc est no olho do furao. Quando o template instanciado pela declarao anterior, o compilador substitui T1
por Ptr<const MobilityModel>.
void
TracedCallback<Ptr<const MobilityModel>::ConnectWithoutContext ... cb
{
Callback<void, Ptr<const MobilityModel> > cb;
cb.Assign (callback);
m_callbackList.push_back (cb);
}
Podemos observar a implementao de tudo que foi explicado at este ponto. O cdigo cria uma callback do tipo
adequado e atribui sua funo para ela. Isto equivalente a pfi = MyFunction discutida anteriormente. O cdigo
73
ento adiciona a callback para a lista de callbacks para esta origem. O que no observamos ainda a definio da
callback. Usando o utilitrio grep podemos encontrar o arquivo ./core/callback.h e verificar a definio.
No arquivo h muito cdigo incompreensvel. Felizmente h algum em Ingls.
This class template implements the Functor Design Pattern.
It is used to declare the type of a Callback:
- the first non-optional template argument represents
the return type of the callback.
- the second optional template argument represents
the type of the first argument to the callback.
- the third optional template argument represents
the type of the second argument to the callback.
- the fourth optional template argument represents
the type of the third argument to the callback.
- the fifth optional template argument represents
the type of the fourth argument to the callback.
- the sixth optional template argument represents
the type of the fifth argument to the callback.
Agora entendemos que o primeiro parmetro, void, indica o tipo de retorno da callback. O segundo parmetro,
Ptr<const MobilityModel> representa o primeiro argumento da callback.
A callback em questo a sua funo que recebe os eventos de rastreamento. Logo, podemos deduzir que precisamos
de uma funo que retorna void e possui um parmetro Ptr<const MobilityModel>. Por exemplo,
void
CourseChangeCallback (Ptr<const MobilityModel> model)
{
...
}
Se queremos garantir que CourseChangeCallback visvel somente em seu arquivo, voc pode adicionar a
palavra chave static, como no exemplo:
static void
CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
{
...
}
o que exatamente usado no exemplo third.cc. Talvez seja interessante reler a seo (Acredite em Minha Palavra).
H mais detalhes sobre a implementao de callbacks no manual do ns-3. Elas esto entre os mais usados construtores
das partes de baixo-nvel do ns-3. Em minha opinio, algo bastante elegante.
74
Captulo 7. Rastreamento
Verificamos que TracedValue uma classe parametrizada. No caso simples do incio da seo, o nome do tipo
int32_t. Isto significa que a varivel membro sendo rastreada (m_v na seo privada da classe) ser int32_t m_v.
O mtodo Set possui um argumento const int32_t &v. Voc deveria ser capaz de entender que o cdigo Set
dispar o callback m_cb com dois parmetros: o primeiro sendo o valor atual do TracedValue; e o segundo sendo
o novo valor.
A callback m_cb declarada como um TracedCallback<T, T>
TracedCallback<int32_t, int32_t> quando a classe instanciada.
que
corresponder
um
Lembre-se que o destino da callback de um TracedCallback sempre retorna void. Lembre tambm que h uma
correspondncia de um-para-um entre a lista de parmetros polimrfica e os argumentos formais da funo callback.
Logo, a callback precisa ter uma assinatura de funo similar a:
void
MyCallback (int32_t oldValue, int32_t newValue)
{
...
}
75
tempo. Stevens denomina de Figure 21.10. Value of cwnd and send sequence number while data is being transmitted.
Vamos recriar a parte cwnd daquele grfico em ns-3 usando o sistema de rastreamento e gnuplot.
no
arquivo
de
cabealho
Voc deveria entender este cdigo. Se ns temos um ponteiro para TcpNewReno, podemos fazer TraceConnect
para a origem do rastreamento CongestionWindow se fornecermos uma callback adequada. o mesmo tipo de
origem do rastreamento que ns abordamos no exemplo simples no incio da seo, exceto que estamos usando
uint32_t ao invs de int32_t.
Precisamos prover uma callback que retorne void e receba dois parmetros uint32_t, o primeiro representando o
valor antigo e o segundo o novo valor:
void
CwndTrace (uint32_t oldValue, uint32_t newValue)
{
...
}
76
Captulo 7. Rastreamento
Encontramos
alguns
candidatos:
examples/tcp/tcp-large-transfer.cc
src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc.
Ns no visitamos nenhum cdigo de teste ainda, ento vamos fazer isto agora. Cdigo de teste pequeno, logo
uma tima escolha. Acesse o arquivo src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc e localize CongestionWindow. Como resultado, temos
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (&Ns3TcpCwndTestCase1::CwndChange, this));
Como abordado, temos uma origem do rastreamento CongestionWindow; ento ela aponta para TcpNewReno,
poderamos alterar o TraceConnect para o que ns desejamos. Vamos extrair o cdigo que precisamos desta
funo (Ns3TcpCwndTestCase1::DoRun (void)). Se voc observar, perceber que parece como um cdigo
ns-3. E descobre-se exatamente que realmente um cdigo. um cdigo executado pelo framework de teste, logo
podemos apenas coloc-lo no main ao invs de DoRun. A traduo deste teste para um cdigo nativo do ns-3
apresentada no arquivo examples/tutorial/fifth.cc.
77
USA
<fstream>
"ns3/core-module.h"
"ns3/network-module.h"
"ns3/internet-module.h"
"ns3/point-to-point-module.h"
"ns3/applications-module.h"
Todo o cdigo apresentado j foi discutido. As prximas linhas so comentrios apresentando a estrutura da rede e
comentrios abordando o problema descrito com o Socket.
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
78
===========================================================================
node 0
node 1
+----------------+
+----------------+
|
ns-3 TCP
|
|
ns-3 TCP
|
+----------------+
+----------------+
|
10.1.1.1
|
|
10.1.1.2
|
+----------------+
+----------------+
| point-to-point |
| point-to-point |
+----------------+
+----------------+
|
|
+---------------------+
5 Mbps, 2 ms
Captulo 7. Rastreamento
//
//
//
//
//
//
//
//
//
//
So, we can cook up a simple version of the on-off application that does what
we want. On the plus side we dont need all of the complexity of the on-off
application. On the minus side, we dont have a helper, so we have to get
a little more involved in the details, but this is trivial.
So first, we create a socket and do the trace connect on it; then we pass
this socket into the constructor of our simple application which we then
install in the source node.
===========================================================================
A prxima parte a declarao da Aplicao MyApp que permite que o Socket seja criado na fase de configurao.
class MyApp : public Application
{
public:
MyApp ();
virtual ~MyApp();
void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
uint32_t nPackets, DataRate dataRate);
private:
virtual void StartApplication (void);
virtual void StopApplication (void);
void ScheduleTx (void);
void SendPacket (void);
Ptr<Socket>
Address
uint32_t
uint32_t
DataRate
EventId
bool
uint32_t
m_socket;
m_peer;
m_packetSize;
m_nPackets;
m_dataRate;
m_sendEvent;
m_running;
m_packetsSent;
};
A
classe
MyApp
herda
a
classe
Application
do
ns-3.
Acesse
o
arquivo
src/network/model/application.h se estiver interessado sobre detalhes dessa herana. A classe
MyApp obrigada sobrescrever os mtodos StartApplication e StopApplication. Estes mtodos so
automaticamente chamado quando MyApp solicitada iniciar e parar de enviar dados durante a simulao.
Como Aplicaes so Iniciadas e Paradas (Opcional)
Nesta seo explicado como eventos tem incio no sistema. uma explicao mais detalhada e no necessria se
no planeja entender detalhes do sistema. interessante, por outro lado, pois aborda como partes do ns-3 trabalham
e mostra alguns detalhes de implementao importantes. Se voc planeja implementar novos modelos, ento deve
entender essa seo.
A maneira mais comum de iniciar eventos iniciar uma Aplicao. Segue as linhas de um cdigo ns-3 que faz
exatamente isso:
ApplicationContainer apps = ...
apps.Start (Seconds (1.0));
79
Isto significa que sempre que um Node criado em uma simulao, como uma implicao, uma chamada para o
mtodo Start do n agendada para que ocorra no tempo zero. Isto no significa que o n vai iniciar fazendo
alguma coisa, pode ser interpretado como uma chamada informacional no Node dizendo a ele que a simulao teve
incio, no uma chamada para ao dizendo ao Node iniciar alguma coisa.
Ento, o NodeList::Add indiretamente agenda uma chamada para Node::Start no tempo zero, para informar
ao novo n que a simulao foi iniciada. Se olharmos em src/network/model/node.h no acharemos um
mtodo chamado Node::Start. Acontece que o mtodo Start herdado da classe Object. Todos objetos no
sistema podem ser avisados que a simulao iniciou e objetos da classe Node so exemplos.
Observe em seguida src/core/model/object.cc. Localize por Object::Start. Este cdigo no to
simples como voc esperava desde que Objects ns-3 suportam agregao. O cdigo em Object::Start ento
percorre todos os objetos que esto agregados e chama o mtodo DoStart de cada um. Este uma outra prtica
muito comum em ns-3. H um mtodo pblica na API, que permanece constante entre implementaes, que chama
um mtodo de implementao privada que herdado e implementado por subclasses. Os nomes so tipicamente algo
como MethodName para os da API pblica e DoMethodName para os da API privada.
Logo, deveramos procurar por um mtodo Node::DoStart em src/network/model/node.cc. Ao localizar
o mtodo, descobrir um mtodo que percorre todos os dispositivos e aplicaes no n chamando respectivamente
device->Start e application->Start.
As classes Device e Application herdam da classe Object, ento o prximo passo entender o que acontece quando Application::DoStart executado.
Observe o cdigo em
80
Captulo 7. Rastreamento
src/network/model/application.cc:
void
Application::DoStart (void)
{
m_startEvent = Simulator::Schedule (m_startTime, &Application::StartApplication, this);
if (m_stopTime != TimeStep (0))
{
m_stopEvent = Simulator::Schedule (m_stopTime, &Application::StopApplication, this);
}
Object::DoStart ();
}
Aqui finalizamos nosso detalhamento. Ao implementar uma Aplicao do ns-3, sua nova aplicao herda da classe
Application. Voc sobrescreve os mtodos StartApplication e StopApplication e prov mecanismos para iniciar e finalizar o fluxo de dados de sua nova Application. Quando um Node criado na simulao,
ele adicionado a uma lista global NodeList. A ao de adicionar um n na lista faz com que um evento do
simulador seja agendado para o tempo zero e que chama o mtodo Node::Start do Node recentemente adicionado para ser chamado quando a simulao inicia. Como um Node herda de Object, a chamada invoca o mtodo
Object::Start no Node, o qual, por sua vez, chama os mtodos DoStart em todos os Objects agregados ao
Node (pense em modelos mveis). Como o Node Object tem sobrescritos DoStart, o mtodo chamado quando
a simulao inicia. O mtodo Node::DoStart chama o mtodo Start de todas as Applications no n.
Por sua vez, Applications so tambm Objects, o que resulta na invocao do Application::DoStart.
Quando Application::DoStart chamada, ela agenda eventos para as chamadas StartApplication e
StopApplication na Application. Estas chamadas so projetadas para iniciar e parar o fluxo de dados da
Application.
Aps essa longa jornada, voc pode entende melhor outra parte do ns-3.
A Aplicao MyApp
A Aplicao MyApp precisa de um construtor e um destrutor,
MyApp::MyApp ()
: m_socket (0),
m_peer (),
m_packetSize (0),
m_nPackets (0),
m_dataRate (0),
m_sendEvent (),
m_running (false),
m_packetsSent (0)
{
}
MyApp::~MyApp()
{
m_socket = 0;
}
81
m_packetSize = packetSize;
m_nPackets = nPackets;
m_dataRate = dataRate;
}
Neste cdigo inicializamos os atributos da classe. Do ponto de vista do rastreamento, a mais importante
Ptr<Socket> socket que deve ser passado para a aplicao durante o fase de configurao. Lembre-se que
vamos criar o Socket como um TcpSocket (que implementado por TcpNewReno) e associar sua origem do
rastreamento de sua CongestionWindow antes de pass-lo no mtodo Setup.
void
MyApp::StartApplication (void)
{
m_running = true;
m_packetsSent = 0;
m_socket->Bind ();
m_socket->Connect (m_peer);
SendPacket ();
}
Este cdigo sobrescreve Application::StartApplication que ser chamado automaticamente pelo simulador para iniciar a Application no momento certo. Observamos que realizada uma operao Socket Bind. Se
voc conhece Sockets de Berkeley isto no uma novidade. responsvel pelo conexo no lado do cliente, ou seja,
o Connect estabelece uma conexo usando TCP no endereo m_peer. Por isso, precisamos de uma infraestrutura
funcional de rede antes de executar a fase de simulao. Depois do Connect, a Application inicia a criao dos
eventos de simulao chamando SendPacket.
void
MyApp::StopApplication (void)
{
m_running = false;
if (m_sendEvent.IsRunning ())
{
Simulator::Cancel (m_sendEvent);
}
if (m_socket)
{
m_socket->Close ();
}
}
A todo instante um evento da simulao agendado, isto , um Event criado. Se o Event uma execuo pendente
ou est executando, seu mtodo IsRunning retornar true. Neste cdigo, se IsRunning() retorna verdadeiro
(true), ns cancelamos (Cancel) o evento, e por consequncia, removido da fila de eventos do simulador. Dessa
forma, interrompemos a cadeia de eventos que a Application est usando para enviar seus Packets. A Aplicao
no enviar mais pacotes e em seguida fechamos (Close) o socket encerrando a conexo TCP.
O socket deletado no destrutor quando m_socket = 0 executado. Isto remove a ltima referncia para
Ptr<Socket> que ocasiona o destrutor daquele Objeto ser chamado.
Lembre-se que StartApplication chamou SendPacket para iniciar a cadeia de eventos que descreve o comportamento da Application.
void
MyApp::SendPacket (void)
{
Ptr<Packet> packet = Create<Packet> (m_packetSize);
82
Captulo 7. Rastreamento
m_socket->Send (packet);
if (++m_packetsSent < m_nPackets)
{
ScheduleTx ();
}
}
Enquanto a Application est executando, ScheduleTx agendar um novo evento, que chama SendPacket
novamente. Verifica-se que a taxa de transmisso sempre a mesma, ou seja, a taxa que a Application produz
os bits. No considera nenhuma sobrecarga de protocolos ou canais fsicos no transporte dos dados. Se alterarmos a
taxa de transmisso da Application para a mesma taxa dos canais fsicos, poderemos ter um estouro de buffer.
Destino do Rastreamento
O foco deste exerccio obter notificaes (callbacks) do TCP indicando a modificao da janela de congestionamento.
O cdigo a seguir implementa o destino do rastreamento.
static void
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
}
Esta funo registra o tempo de simulao atual e o novo valor da janela de congestionamento toda vez que modificada. Poderamos usar essa sada para construir um grfico do comportamento da janela de congestionamento com
relao ao tempo.
Ns adicionamos um novo destino do rastreamento para mostrar onde pacotes so perdidos. Vamos adicionar um
modelo de erro.
static void
RxDrop (Ptr<const Packet> p)
{
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
}
Este destino do rastreamento ser conectado a origem do rastreamento PhyRxDrop do NetDevice ponto-a-ponto.
Esta origem do rastreamento dispara quando um pacote removido da camada fsica de um NetDevice. Se olharmos rapidamente src/point-to-point/model/point-to-point-net-device.cc verificamos que a
origem do rastreamento refere-se a PointToPointNetDevice::m_phyRxDropTrace. E se procurarmos em
src/point-to-point/model/point-to-point-net-device.h por essa varivel, encontraremos que
7.3. Um Exemplo Real
83
ela est declarada como uma TracedCallback<Ptr<const Packet> >. Isto significa que nosso callback
deve ser uma funo que retorna void e tem um nico parmetro Ptr<const Packet>.
O Programa Principal
O cdigo a seguir corresponde ao incio da funo principal:
int
main (int argc, char *argv[])
{
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
So criados dois ns ligados por um canal ponto-a-ponto, como mostrado na ilustrao no incio do arquivo.
Nas prximas linhas, temos um cdigo com algumas informaes novas. Se ns
rastrearmos uma conexo que comporta-se perfeitamente, terminamos com um
janela de congestionamento que aumenta monoliticamente. Para observarmos um
comportamento interessante, introduzimos erros que causaro perda de pacotes,
duplicao de ACKs e assim, introduz comportamentos mais interessantes a
janela de congestionamento.
O ns-3 prov objetos de um modelo de erros (ErrorModel) que pode ser adicionado aos canais (Channels). Ns
usamos o RateErrorModel que permite introduzir erros no canal dada uma taxa.
Ptr<RateErrorModel> em = CreateObjectWithAttributes<RateErrorModel> (
"RanVar", RandomVariableValue (UniformVariable (0., 1.)),
"ErrorRate", DoubleValue (0.00001));
devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
Neste cdigo configura a pilha de protocolos da internet nos dois ns de rede, cria interfaces e associa endereos IP
para os dispositivos ponto-a-ponto.
Como estamos usando TCP, precisamos de um n de destino para receber as conexes e os dados. O PacketSink
Application comumente usado no ns-3 para este propsito.
84
Captulo 7. Rastreamento
Este cdigo instancia um PacketSinkHelper e cria sockets usando a classe ns3::TcpSocketFactory. Esta
classe implementa o padro de projeto fbrica de objetos. Dessa forma, em vez de criar os objetos diretamente,
fornecemos ao PacketSinkHelper um texto que especifica um TypeId usado para criar um objeto que, por sua
vez, pode ser usado para criar instncias de Objetos criados pela implementao da fbrica de objetos.
O parmetro seguinte especifica o endereo e a porta para o mapeamento.
As prximas duas linhas do cdigo criam o socket e conectam a origem do rastreamento.
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0),
TcpSocketFactory::GetTypeId ());
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (&CwndChange));
A primeira declarao chama a funo esttica Socket::CreateSocket e passa um Node e um TypeId para o
objeto fbrica usado para criar o socket.
Uma vez que o TcpSocket criado e adicionado ao Node, ns usamos TraceConnectWithoutContext para
conectar a origem do rastreamento CongestionWindow para o nosso destino do rastreamento.
Codificamos uma Application ento podemos obter um Socket (durante a fase de configurao) e usar na fase
de simulao. Temos agora que instanciar a Application. Para tal, segue os passos:
Ptr<MyApp> app = CreateObject<MyApp> ();
app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
nodes.Get (0)->AddApplication (app);
app->Start (Seconds (1.));
app->Stop (Seconds (20.));
A primeira linha cria um Objeto do tipo MyApp nossa Application. A segunda linha especifica o socket, o
endereo de conexo, a quantidade de dados a ser enviada em cada evento, a quantidade de eventos de transmisso a
ser gerados e a taxa de produo de dados para estes eventos.
Next, we manually add the MyApp Application to the source node and explicitly call the Start
and Stop methods on the Application to tell it when to start and stop doing its thing.
Depois, adicionamos a MyApp Application para o n origem e chamamos os mtodos Start e Stop para dizer
quando e iniciar e parar a simulao.
Precisamos agora fazer a conexo entre o receptor com nossa callback.
devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));
Estamos obtendo uma referncia para o Node NetDevice receptor e conectando a origem do rastreamento pelo
Atributo PhyRxDrop do dispositivo no destino do rastreamento RxDrop.
Finalmente, dizemos ao simulador para sobrescrever qualquer Applications e parar o processamento de eventos
em 20 segundos na simulao.
85
Simulator::Stop (Seconds(20));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
Lembre-se que quando Simulator::Run chamado, a fase de configurao termina e a fase de simulao inicia.
Todo o processo descrito anteriormente ocorre durante a chamada dessa funo.
Aps o retorno do Simulator::Run, a simulao terminada e entramos na fase de finalizao. Neste caso,
Simulator::Destroy executa a tarefa pesada e ns apenas retornamos o cdigo de sucesso.
Podemos observar o lado negativo de usar prints de qualquer tipo no rastreamento. Temos mensagens waf sendo
impressas sobre a informao relevante. Vamos resolver esse problema, mas primeiro vamos verificar o resultado
redirecionando a sada para um arquivo cwnd.dat:
./waf --run fifth > cwnd.dat 2>&1
Removemos as mensagens do waf e deixamos somente os dados rastreados. Pode-se tambm comentar as mensagens
de RxDrop....
Agora podemos executar o gnuplot (se instalado) e gerar um grfico:
gnuplot>
gnuplot>
gnuplot>
gnuplot>
Devemos obter um grfico da janela de congestionamento pelo tempo no arquivo cwnd.png, similar ao grfico 7.1:
figure:: figures/cwnd.png
Grfico da janela de congestionamento versus tempo.
Captulo 7. Rastreamento
de interesse. Podemos pensar que perdemos muito tempo em um exemplo que apresenta todos os problemas que
propomos resolver usando o sistema de rastreamento do ns-3. Voc estaria correto, mas ns ainda no terminamos.
Uma da coisas mais importantes que queremos fazer controlar a quantidade de sada da simulao. Ns podemos
usar assistentes de rastreamento intermedirios fornecido pelo ns-3 para alcanar com sucesso esse objetivo.
Fornecemos um cdigo que separa em arquivos distintos no disco os eventos de modificao da janela e os eventos de
remoo. As alteraes em cwnd so armazenadas em um arquivo ASCII separadas por TAB e os eventos de remoo
so armazenados em um arquivo pcap. As alteraes para obter esse resultado so pequenas.
Analisando sixth.cc
Vamos verificar as mudanas do arquivo fifth.cc para o sixth.cc. Verificamos a primeira mudana em
CwndChange. Notamos que as assinaturas para o destino do rastreamento foram alteradas e que foi adicionada
uma linha para cada um que escreve a informao rastreada para um fluxo (stream) representando um arquivo
static void
CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
*stream->GetStream () << Simulator::Now ().GetSeconds () << "\t"
<< oldCwnd << "\t" << newCwnd << std::endl;
}
static void
RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
{
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
file->Write(Simulator::Now(), p);
}
Um parmetro stream foi adicionado para o destino do rastreamento CwndChange. Este um objeto que armazena
(mantm seguramente vivo) um fluxo de sada em C++. Isto resulta em um objeto muito simples, mas que gerncia
problemas no ciclo de vida para fluxos e resolve um problema que mesmo programadores experientes de C++ tem
dificuldades. Resulta que o construtor de cpia para o fluxo de sada (ostream) marcado como privado. Isto significa
que fluxos de sada no seguem a semntica de passagem por valor e no podem ser usados em mecanismos que
necessitam que o fluxo seja copiado. Isto inclui o sistema de callback do ns-3. Alm disso, adicionamos a seguinte
linha:
*stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd
<< "\t" << newCwnd << std::endl;
Isto demostra que o Ptr<OutputStreamWrapper> est apenas encapsulando um std::ofstream, logo pode
ser usado como qualquer outro fluxo de sada.
Uma situao similar ocorre em RxDrop, exceto que o objeto passado (Ptr<PcapFileWrapper>) representa um
arquivo pcap. H uma linha no trace sink para escrever um marcador de tempo (timestamp) eo contedo do pacote
perdido para o arquivo pcap.
file->Write(Simulator::Now(), p);
claro, se ns temos objetos representando os dois arquivos, precisamos cri-los em algum lugar e tambm pass-los
aos trace sinks. Se observarmos a funo main, temos o cdigo:
87
AsciiTraceHelper asciiTraceHelper;
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeBoundCallback (&CwndChange, stream));
...
PcapHelper pcapHelper;
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap",
std::ios::out, PcapHelper::DLT_PPP);
devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop",
MakeBoundCallback (&RxDrop, file));
Na primeira seo do cdigo, criamos o arquivo de rastreamento ASCII e o objeto responsvel para gerenci-lo. Em
seguida, usando uma das formas da funo para criao da callback permitimos o objeto ser passado para o destino do
rastreamento. As classes assistentes para rastreamento ASCII fornecem um vasto conjunto de funes para facilitar a
manipulao de arquivos texto. Neste exemplo, focamos apenas na criao do arquivo para o fluxo de sada.
A funo CreateFileStream() instancia um objeto std::ofstream e cria um novo arquivo. O fluxo de sada
ofstream encapsulado em um objeto do ns-3 para gerenciamento do ciclo de vida e para resolver o problema do
construtor de cpia.
Ento pegamos o objeto que representa o arquivo e passamos para MakeBoundCallback(). Esta funo cria
um callback como MakeCallback(), mas associa um novo valor para o callback. Este valor adicionado ao
callback antes de sua invocao.
Essencialmente, MakeBoundCallback(&CwndChange, stream) faz com que a origem do rastreamento adicione um parmetro extra fluxo aps a lista formal de parmetros antes de invocar o callback. Esta mudana est de
acordo com o apresentado anteriormente, a qual inclui o parmetro Ptr<OutputStreamWrapper> stream.
Na segunda seo de cdigo, instanciamos um PcapHelper para fazer a mesma coisa para o arquivo de rastreamento
pcap. A linha de cdigo,
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w",
PcapHelper::DLT_PPP);
cria um arquivo pcap chamado sixth.pcap no modo w (escrita). O parmetro final o tipo da ligao de dados
do arquivo pcap. As opes esto definidas em bpf.h. Neste caso, DLT_PPP indica que o arquivo pcap dever
conter pacotes prefixado com cabealhos ponto-a-ponto. Isto verdade pois os pacotes esto chegando de nosso
driver de dispositivo ponto-a-ponto. Outros tipos de ligao de dados comuns so DLT_EN10MB (10 MB Ethernet)
apropriado para dispositivos CSMA e DLT_IEEE802_11 (IEEE 802.11) apropriado para dispositivos sem fio. O
arquivo src/network/helper/trace-helper.h" define uma lista com os tipos. As entradas na lista so
idnticas as definidas em bpf.h, pois foram duplicadas para evitar um dependncia com o pcap.
Um objeto ns-3 representando o arquivo pcap retornado de CreateFile e usado em uma callback exatamente
como no caso ASCII.
importante observar que ambos objetos so declarados de maneiras muito similares,
Ptr<PcapFileWrapper> file ...
Ptr<OutputStreamWrapper> stream ...
Mas os objetos internos so inteiramente diferentes. Por exemplo, o Ptr<PcapFileWrapper> um ponteiro para um objeto ns-3 que suporta Attributes e integrado dentro do sistema de configurao. O Ptr<OutputStreamWrapper>,
por outro lado, um ponteiro para uma referncia para um simples objeto contado. Lembre-se sempre de analisar o
objeto que voc est referenciando antes de fazer suposies sobre os poderes que o objeto pode ter.
Por exemplo, acesse o arquivo src/network/utils/pcap-file-wrapper.h e observe,
88
Captulo 7. Rastreamento
por
herana.
no
arquivo
que no um Object ns-3, mas um objeto C++ que suporta contagem de referncia.
A questo que se voc tem um Ptr<alguma_coisa>, no necessariamente significa que alguma_coisa um Object
ns-3, no qual voc pode modificar Attributes, por exemplo.
Voltando ao exemplo. Se compilarmos e executarmos o exemplo,
./waf --run sixth
Veremos as mesmas mensagens do fifth, mas dois novos arquivos aparecero no diretrio base de sua distribuio
do ns-3.
sixth.cwnd
sixth.pcap
Como sixth.cwnd um arquivo texto ASCII, voc pode visualizar usando cat ou um editor de texto.
1.20919
1.21511
...
9.30922
9.31754
536
1072
1072
1608
8893
8925
8925
8957
Cada linha tem um marcador de tempo, o valor da janela de congestionamento e o valor da nova janela de congestionamento separados por tabulao, para importar diretamente para seu programa de plotagem de grficos. No h
nenhuma outra informao alm da rastreada, logo no necessrio processamento ou edio do arquivo.
Como sixth.pcap um arquivo pcap, voc pode visualizar usando o tcpdump ou wireshark.
reading from file ../../sixth.pcap, link-type
1.251507 IP 10.1.1.1.49153 > 10.1.1.2.8080: .
1.411478 IP 10.1.1.1.49153 > 10.1.1.2.8080: .
...
7.393557 IP 10.1.1.1.49153 > 10.1.1.2.8080: .
8.141483 IP 10.1.1.1.49153 > 10.1.1.2.8080: .
PPP (PPP)
17689:18225(536) ack 1 win 65535
33808:34312(504) ack 1 win 65535
781568:782072(504) ack 1 win 65535
874632:875168(536) ack 1 win 65535
Voc tem um arquivo pcap com os pacotes que foram descartados na simulao. No h nenhum outro pacote presente
no arquivo e nada mais para dificultar sua anlise.
Foi uma longa jornada, mas agora entendemos porque o sistema de rastreamento interessante. Ns obtemos e
armazenamos importantes eventos da implementao do TCP e do driver de dispositivo. E no modificamos nenhuma
linha do cdigo do ncleo do ns-3, e ainda fizemos isso com apenas 18 linhas de cdigo:
static void
CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
*stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" <<
oldCwnd << "\t" << newCwnd << std::endl;
}
...
AsciiTraceHelper asciiTraceHelper;
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
89
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeBoundCallback (&CwndChange, stream));
...
static void
RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
{
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
file->Write(Simulator::Now(), p);
}
...
PcapHelper pcapHelper;
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w",
PcapHelper::DLT_PPP);
devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop",
MakeBoundCallback (&RxDrop, file));
O que no parece claro que h um modelo consistente para todos os mtodos relacionados rastreamento encontrados
no sistema. Apresentaremos uma viso geral desse modelo.
H dois casos de uso primrios de classes assistentes em ns-3: Classes assistentes de dispositivo e classes assistentes
de protocolo. Classes assistentes de dispositivo tratam o problema de especificar quais rastreamentos deveriam ser
habilitados no domnio do n de rede. Por exemplo, poderamos querer especificar que o rastreamento pcap deveria
ser ativado em um dispositivo particular de um n especfico. Isto o que define o modelo conceitual de dispositivo no
ns-3 e tambm os modelos conceituais de vrias classes assistentes de dispositivos. Baseado nisso, os arquivos criados
seguem a conveno de nome <prefixo>-<n>-<dispositivo>.
As classes assistentes de protocolos tratam o problema de especificar quais rastreamentos deveriam ser ativados no
protocolo e interface. Isto definido pelo modelo conceitual de pilha de protocolo do ns-3 e tambm pelos modelos
conceituais de classes assistentes de pilha de rede. Baseado nisso, os arquivos criados seguem a conveno de nome
<prefixo>-<protocolo>-<interface>.
As classes assistentes consequentemente encaixam-se em uma taxinomia bi-dimensional. H pequenos detalhes que
evitam todas as classes comportarem-se da mesma forma, mas fizemos parecer que trabalham to similarmente quanto
possvel e quase sempre h similares para todos mtodos em todas as classes.
| pcap | ascii |
---------------------------------------------------+------+-------|
Classe Assistente de Dispositivo (*Device Helper*)
|
|
|
90
Captulo 7. Rastreamento
---------------------------------------------------+------+-------|
Classe Assistente de Protocolo (*Protocol Helper*)
|
|
|
---------------------------------------------------+------+-------|
Usamos uma abordagem chamada mixin para adicionar funcionalidade de rastreamento para nossas classes assistentes. Uma mixin uma classe que prov funcionalidade para aquela que herdada por uma subclasse. Herdar de um
mixin no considerado uma forma de especializao mas realmente uma maneira de colecionar funcionalidade.
Vamos verificar rapidamente os quatro casos e seus respectivos mixins.
A assinatura deste mtodo reflete a viso do dispositivo da situao neste nvel. Todos os mtodos pblicos herdados da classe PcapUserHelperForDevice so reduzidos a chamada da implementao deste simples mtodo
dependente de dispositivo. Por exemplo, o nvel mais baixo do mtodo pcap,
void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false,
bool explicitFilename = false);
Em cada mtodo apresentado existe um parmetro padro chamado promiscuous que definido para o valor
false. Este parmetro indica que o rastreamento no deveria coletar dados em modo promscuo. Se quisermos
incluir todo trfego visto pelo dispositivo devemos modificar o valor para true. Por exemplo,
91
Ptr<NetDevice> nd;
...
helper.EnablePcap ("prefix", nd, true);
Podemos ativar o rastreamento pcap em um par n/dispositivo-rede passando uma std::string que representa
um nome de servio para um mtodo EnablePcap. O Ptr<NetDevice> buscado a partir do nome da string.
Novamente, o Ptr<Node> implcito pois o dispositivo de rede deve estar em um Node.
Names::Add ("server" ...);
Names::Add ("server/eth0" ...);
...
helper.EnablePcap ("prefix", "server/eth0");
Podemos ativar o rastreamento pcap em uma coleo de pares ns/dispositivos usando um NetDeviceContainer.
Para cada NetDevice no continer o tipo verificado. Para cada dispositivo com o tipo adequado, o rastreamento
ser ativado. Por exemplo,
NetDeviceContainer d = ...;
...
helper.EnablePcap ("prefix", d);
Podemos ativar o rastreamento em uma coleo de pares n/dispositivo-rede usando um NodeContainer. Para cada
Node no NodeContainer seus NetDevices so percorridos e verificados segundo o tipo. Para cada dispositivo
com o tipo adequado, o rastreamento ativado.
NodeContainer n;
...
helper.EnablePcap ("prefix", n);
Podemos ativar o rastreamento pcap usando o nmero identificador (ID) do n e do dispositivo. Todo Node no sistema
tem um valor inteiro indicando o ID do n e todo dispositivo conectado ao n tem um valor inteiro indicando o ID do
dispositivo.
helper.EnablePcap ("prefix", 21, 1);
Por fim, podemos ativar rastreamento pcap para todos os dispositivos no sistema, desde que o tipo seja o mesmo
gerenciado pela classe assistentes de dispositivo.
helper.EnablePcapAll ("prefix");
92
Captulo 7. Rastreamento
tem um parmetro padro explicitFilename. Quando modificado para verdadeiro, este parmetro desabilita o
mecanismo automtico de completar o nome do arquivo e permite criarmos um nome de arquivo abertamente. Esta
opo est disponvel nos mtodos que ativam o rastreamento pcap em um nico dispositivo.
Por exemplo, com a finalidade providenciar uma classe assistente de dispositivo para criar um nico arquivo de captura
pcap no modo promscuo com um nome especfico (my-pcap-file.pcap) em um determinado dispositivo:
Ptr<NetDevice> nd;
...
helper.EnablePcap ("my-pcap-file.pcap", nd, true, true);
O primeiro parmetro true habilita o modo de rastreamento promscuo e o segundo faz com que o parmetro prefix
seja interpretado como um nome de arquivo completo.
A assinatura deste mtodo reflete a viso do dispositivo da situao neste nvel; e tambm o fato que o assistente
pode ser escrito para um fluxo de sada compartilhado. Todos os mtodos pblicos associados ao rastreamento ASCII
herdam da classe AsciiTraceHelperForDevice resumem-se a chamada deste nico mtodo dependente de
implementao. Por exemplo, os mtodos de rastreamento ASCII de mais baixo nvel,
void EnableAscii (std::string prefix, Ptr<NetDevice> nd,
bool explicitFilename = false);
void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
chamaro uma implementao de EnableAsciiInternal diretamente, passando um prefixo ou fluxo vlido. Todos os outros mtodos pblicos sero construdos a partir destas funes de baixo nvel para fornecer funcionalidades
93
adicionais em nvel de usurio. Para o usurio, isso significa que todos os assistentes de dispositivo no sistema tero todos os mtodos de rastreamento ASCII disponveis e estes mtodos trabalharo do mesmo modo em todos os
dispositivos se estes implementarem EnableAsciiInternal.
Mtodos da Classe Assistente de Dispositivo para Rastreamento ASCII
void EnableAscii (std::string prefix, Ptr<NetDevice> nd,
bool explicitFilename = false);
void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
void EnableAscii (std::string prefix, std::string ndName,
bool explicitFilename = false);
void EnableAscii (Ptr<OutputStreamWrapper> stream, std::string ndName);
void EnableAscii (std::string prefix, NetDeviceContainer d);
void EnableAscii (Ptr<OutputStreamWrapper> stream, NetDeviceContainer d);
void EnableAscii (std::string prefix, NodeContainer n);
void EnableAscii (Ptr<OutputStreamWrapper> stream, NodeContainer n);
void EnableAsciiAll (std::string prefix);
void EnableAsciiAll (Ptr<OutputStreamWrapper> stream);
void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid,
bool explicitFilename);
void EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid,
uint32_t deviceid);
Para maiores detalhes sobre os mtodos interessante consultar a documentao para a classe
AsciiTraceHelperForDevice; mas para resumir ...
H duas vezes mais mtodos disponveis para rastreamento ASCII que para rastreamento pcap. Isto ocorre pois para
o modelo pcap os rastreamentos de cada par n/dispositivo-rede so escritos para um nico arquivo, enquanto que
no ASCII todo as as informaes so escritas para um arquivo comum. Isto significa que o mecanismo de gerao
de nomes de arquivos <prefixo>-<n>-<dispositivo> substitudo por um mecanismo para referenciar um arquivo
comum; e o nmero de mtodos da API duplicado para permitir todas as combinaes.
Assim como no rastreamento pcap, podemos ativar o rastreamento ASCII em um par n/dispositivo-rede passando um
Ptr<NetDevice> para um mtodo EnableAscii. O Ptr<Node> implcito pois o dispositivo de rede deve
pertencer a exatamente um Node. Por exemplo,
Ptr<NetDevice> nd;
...
helper.EnableAscii ("prefix", nd);
Os primeiros quatro mtodos tambm incluem um parmetro padro explicitFilename que opera similar aos
parmetros no caso do pcap.
Neste caso, nenhum contexto de rastreamento escrito para o arquivo ASCII pois seriam redundantes. O sistema
pegar o nome do arquivo para ser criado usando as mesmas regras como descritas na seo pcap, exceto que o
arquivo ter o extenso .tr ao invs de .pcap.
Para habilitar o rastreamento ASCII em mais de um dispositivo de rede e ter todos os dados de rastreamento enviados
para um nico arquivo, pode-se usar um objeto para referenciar um nico arquivo. Ns j verificamos isso no exemplo
cwnd:
Ptr<NetDevice> nd1;
Ptr<NetDevice> nd2;
94
Captulo 7. Rastreamento
...
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream
("trace-file-name.tr");
...
helper.EnableAscii (stream, nd1);
helper.EnableAscii (stream, nd2);
Neste caso, os contextos so escritos para o arquivo ASCII quando necessrio distinguir os dados de rastreamento
de dois dispositivos. interessante usar no nome do arquivo a extenso .tr por motivos de consistncia.
Podemos habilitar o rastreamento ASCII em um par n/dispositivo-rede especfico passando ao mtodo
EnableAscii uma std::string representando um nome no servio de nomes de objetos.
O
Ptr<NetDevice> obtido a partir do nome. Novamente, o <Node> implcito pois o dispositivo de rede deve
pertencer a exatamente um Node. Por exemplo,
Names::Add ("client" ...);
Names::Add ("client/eth0" ...);
Names::Add ("server" ...);
Names::Add ("server/eth0" ...);
...
helper.EnableAscii ("prefix", "client/eth0");
helper.EnableAscii ("prefix", "server/eth0");
Isto resultaria em um nico arquivo chamado trace-file-name.tr que contm todosos eventos rastreados para ambos
os dispositivos. Os eventos seriam diferenciados por strings de contexto.
Podemos habilitar o rastreamento ASCII em um coleo de pares n/dispositivo-rede fornecendo um
NetDeviceContainer. Para cada NetDevice no continer o tipo verificado. Para cada dispositivo de um
tipo adequado (o mesmo tipo que gerenciado por uma classe assistente de dispositivo), o rastreamento habilitado.
Novamente, o <Node> implcito pois o dispositivo de rede encontrado deve pertencer a exatamente um Node.
NetDeviceContainer d = ...;
...
helper.EnableAscii ("prefix", d);
Isto resultaria em vrios arquivos de rastreamento ASCII sendo criados, cada um seguindo a conveno
<prefixo>-<id do n>-<id do dispositivo>.tr.
Para obtermos um nico arquivo teramos:
NetDeviceContainer d = ...;
...
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream
("trace-file-name.tr");
95
...
helper.EnableAscii (stream, d);
Isto resultaria em vrios arquivos ASCII sendo criados, cada um seguindo a conveno <prefixo>-<id do
n>-<id do dispositivo>.tr.
Podemos habilitar o rastreamento pcap na base da ID do n e ID do dispositivo to bem como com um Ptr. Cada
Node no sistema possui um nmero identificador inteiro associado ao n e cada dispositivo conectado possui um
nmero identificador inteiro associado ao dispositivo.
helper.EnableAscii ("prefix", 21, 1);
Isto resultaria em vrios arquivos ASCII sendo criados, um para cada dispositivo no sistema do tipo gerenciado pelo assistente. Todos estes arquivos seguiriam a conveno <prefixo>-<id do n>-<id do
dispositivo>.tr.
Selecionando Nome de Arquivo para as Sadas ASCII
Implcito nas descries de mtodos anteriores a construo do nome de arquivo por meio do mtodo da implementao. Por conveno, rastreamento ASCII no ns-3 usa a forma <prefixo>-<id do n>-<id do
dispositivo>.tr.
Como mencionado, todo n no sistema ter um id de n associado; e todo dispositivo ter um ndice de interface
(tambm chamado de id do dispositivo) relativo ao seu n. Por padro, ento, um arquivo ASCII criado como um
resultado de ativar rastreamento no primeiro dispositivo do n 21 usando o prefixo prefix seria prefix-21-1.tr.
Sempre podemos usar o servio de nome de objeto do ns-3 para tornar isso mais claro. Por exemplo, se
usarmos o servio para associar o nome server ao n 21, o arquivo ASCII resultante automaticamente ser,
prefix-server-1.tr e se tambm associarmos o nome eth0 ao dispositivo, o nome do arquivo ASCII automaticamente ser denominado prefix-server-eth0.tr.
Diversos mtodos tem um parmetro padro explicitFilename. Quando modificado para verdadeiro, este parmetro desabilita o mecanismo automtico de completar o nome do arquivo e permite criarmos um nome de arquivo
abertamente. Esta opo est disponvel nos mtodos que possuam um prefixo e ativem o rastreamento em um nico
dispositivo.
96
Captulo 7. Rastreamento
Nesta seo ilustraremos os mtodos aplicados ao protocolo Ipv4. Para especificar rastreamentos em protocolos
similares, basta substituir pelo tipo apropriado. Por exemplo, use um Ptr<Ipv6> ao invs de um Ptr<Ipv4> e
chame um EnablePcapIpv6 ao invs de EnablePcapIpv4.
A classe PcapHelperForIpv4 prov funcionalidade de alto nvel para usar rastreamento no protocolo Ipv4. Cada
classe assistente de protocolo devem implementar um mtodo herdado desta. Haver uma implementao separada
para Ipv6, por exemplo, mas a diferena ser apenas nos nomes dos mtodos e assinaturas. Nomes de mtodos
diferentes so necessrio para distinguir a classe Ipv4 da Ipv6, pois ambas so derivadas da classe Object, logo
os mtodos compartilham a mesma assinatura.
virtual void EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4> ipv4,
uint32_t interface, bool explicitFilename) = 0;
A assinatura desse mtodo reflete a viso do protocolo e interface da situao neste nvel. Todos os mtodos herdados da classe PcapHelperForIpv4 resumem-se a chamada deste nico mtodo dependente de dispositivo. Por
exemplo, o mtodo do pcap de mais baixo nvel,
void EnablePcapIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface,
bool explicitFilename = false);
interessante
consultar
na
documentao
da
classe
Podemos habilitar o rastreamento pcap em um par protocolo/interface passando um Ptr<Ipv4> e interface para
um mtodo EnablePcap. Por exemplo,
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
...
helper.EnablePcapIpv4 ("prefix", ipv4, 0);
Podemos ativar o rastreamento pcap em um par protocolo/interface passando uma std::string que representa um
nome de servio para um mtodo EnablePcapIpv4. O Ptr<Ipv4> buscado a partir do nome da string. Por
exemplo,
97
Podemos ativar o rastreamento em uma coleo de pares protocolo/interface usando um NodeContainer. Para
cada Node no NodeContainer o protocolo apropriado encontrado. Para cada protocolo, suas interfaces so
enumeradas e o rastreamento ativado nos pares resultantes. Por exemplo,
NodeContainer n;
...
helper.EnablePcapIpv4 ("prefix", n);
Pode ativar o rastreamento pcap usando o nmero identificador do n e da interface. Neste caso, o ID do n traduzido
para um Ptr<Node> e o protocolo apropriado buscado no n. O protocolo e interface resultante so usados para
especificar a origem do rastreamento resultante.
helper.EnablePcapIpv4 ("prefix", 21, 1);
Por fim, podemos ativar rastreamento pcap para todas as interfaces no sistema, desde que o protocolo seja do mesmo
tipo gerenciado pela classe assistente.
helper.EnablePcapIpv4All ("prefix");
Captulo 7. Rastreamento
Diversos mtodos tem um parmetro padro explicitFilename. Quando modificado para verdadeiro, este parmetro desabilita o mecanismo automtico de completar o nome do arquivo e permite criarmos um nome de arquivo
abertamente. Esta opo est disponvel nos mtodos que ativam o rastreamento pcap em um nico dispositivo.
A assinatura deste mtodo reflete a viso central do protocolo e interface da situao neste nvel; e tambm o fato que
o assistente pode ser escrito para um fluxo de sada compartilhado. Todos os mtodos pblicos herdados desta classe
PcapAndAsciiTraceHelperForIpv4 resumem-se a chamada deste nico mtodo dependente de implementao. Por exemplo, os mtodos de rastreamento ASCII de mais baixo nvel,
void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface,
bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4,
uint32_t interface);
chamaro uma implementao de EnableAsciiIpv4Internal diretamente, passando um prefixo ou fluxo vlido. Todos os outros mtodos pblicos sero construdos a partir destas funes de baixo nvel para fornecer funcionalidades adicionais em nvel de usurio. Para o usurio, isso significa que todos os assistentes de protocolos no
sistema tero todos os mtodos de rastreamento ASCII disponveis e estes mtodos trabalharo do mesmo modo em
todos os protocolos se estes implementarem EnableAsciiIpv4Internal.
Mtodos da Classe Assistente de Protocolo para Rastreamento ASCII
void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface,
bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4,
uint32_t interface);
void EnableAsciiIpv4 (std::string prefix, std::string ipv4Name, uint32_t interface,
bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, std::string ipv4Name,
uint32_t interface);
void EnableAsciiIpv4 (std::string prefix, Ipv4InterfaceContainer c);
void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ipv4InterfaceContainer c);
void EnableAsciiIpv4 (std::string prefix, NodeContainer n);
void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, NodeContainer n);
99
Para maiores detalhes sobre os mtodos consulte na documentao a classe PcapAndAsciiHelperForIpv4; mas
para resumir ...
H duas vezes mais mtodos disponveis para rastreamento ASCII que para rastreamento pcap. Isto ocorre pois para
o modelo pcap os rastreamentos de cada par protocolo/interface so escritos para um nico arquivo, enquanto que
no ASCII todo as as informaes so escritas para um arquivo comum. Isto significa que o mecanismo de gerao
de nomes de arquivos <prefixo>-n<id do n>-i<interface> substitudo por um mecanismo para referenciar um
arquivo comum; e o nmero de mtodos da API duplicado para permitir todas as combinaes.
Assim, como no rastreamento pcap, podemos ativar o rastreamento ASCII em um par protocolo/interface passando
um Ptr<Ipv4> e uma interface para um mtodo EnableAsciiIpv4. Por exemplo,
Ptr<Ipv4> ipv4;
...
helper.EnableAsciiIpv4 ("prefix", ipv4, 1);
Neste caso, nenhum contexto de rastreamento escrito para o arquivo ASCII pois seriam redundantes. O sistema
pegar o nome do arquivo para ser criado usando as mesmas regras como descritas na seo pcap, exceto que o
arquivo ter o extenso .tr ao invs de .pcap.
Para habilitar o rastreamento ASCII em mais de uma interface e ter todos os dados de rastreamento enviados para um
nico arquivo, pode-se usar um objeto para referenciar um nico arquivo. Ns j verificamos isso no exemplo cwnd:
Ptr<Ipv4> protocol1 = node1->GetObject<Ipv4> ();
Ptr<Ipv4> protocol2 = node2->GetObject<Ipv4> ();
...
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream
("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (stream, protocol1, 1);
helper.EnableAsciiIpv4 (stream, protocol2, 1);
Neste caso, os contextos so escritos para o arquivo ASCII quando necessrio distinguir os dados de rastreamento
de duas interfaces. interessante usar no nome do arquivo a extenso .tr por motivos de consistncia.
Pode habilitar o rastreamento ASCII em protocolo especfico passando ao mtodo EnableAsciiIpv4 uma
std::string representando um nome no servio de nomes de objetos. O Ptr<Ipv4> obtido a partir do nome. O
<Node> implcito, pois h uma correspondncia de um-para-um entre instancias de protocolos e ns. Por exemplo,
Names::Add ("node1Ipv4" ...);
Names::Add ("node2Ipv4" ...);
...
helper.EnableAsciiIpv4 ("prefix", "node1Ipv4", 1);
helper.EnableAsciiIpv4 ("prefix", "node2Ipv4", 1);
100
Captulo 7. Rastreamento
Isto resultaria em um nico arquivo chamado trace-file-name.tr que contm todos os eventos rastreados para
ambas as interfaces. Os eventos seriam diferenciados por strings de contexto.
Podemos habilitar o rastreamento ASCII em um coleo de pares protocolo/interface provendo um
Ipv4InterfaceContainer. Para cada protocolo no continer o tipo verificado. Para cada protocolo do tipo
adequado (o mesmo tipo que gerenciado por uma classe assistente de protocolo), o rastreamento habilitado para
a interface correspondente. Novamente, o <Node> implcito, pois h uma correspondncia de um-para-um entre
protocolo e seu n. Por exemplo,
NodeContainer nodes;
...
NetDeviceContainer devices = deviceHelper.Install (nodes);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
...
...
helper.EnableAsciiIpv4 ("prefix", interfaces);
Isto resultaria em vrios arquivos de rastreamento ASCII sendo criados, cada um seguindo a conveno
<prefixo>-n<id do n>-i<interface>.tr.
Para obtermos um nico arquivo teramos:
NodeContainer nodes;
...
NetDeviceContainer devices = deviceHelper.Install (nodes);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
...
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream
("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (stream, interfaces);
Podemos habilitar o rastreamento ASCII em uma coleo de pares protocolo/interface provendo um NodeContainer.
Para cada Node no NodeContainer os protocolos apropriados so encontrados. Para cada protocolo, sua interface
enumerada e o rastreamento habilitado nos pares. Por exemplo,
NodeContainer n;
...
helper.EnableAsciiIpv4 ("prefix", n);
Podemos habilitar o rastreamento pcap usando o nmero identificador do n e nmero identificador do dispositivo.
Neste caso, o ID do n traduzido para um Ptr<Node> e o protocolo apropriado procurado no n de rede. O
protocolo e interface resultantes so usados para especificar a origem do rastreamento.
helper.EnableAsciiIpv4 ("prefix", 21, 1);
101
Isto resultaria em vrios arquivos ASCII sendo criados, um para cada interface no sistema relacionada ao protocolo do tipo gerenciado pela classe assistente.Todos estes arquivos seguiriam a conveno <prefix>-n<id do
node>-i<interface>.tr.
Seleo de Nome de Arquivo para Rastreamento ASCII da Classe Assistente de Protocolo
Implcito nas descries de mtodos anteriores a construo do nome do arquivo por meio do mtodo da implementao. Por conveno, rastreamento ASCII no sistema ns-3 so da forma <prefix>-<id node>-<id do
dispositivo>.tr.
Como mencionado, todo n no sistema ter um nmero identificador de n associado. Como h uma correspondncia
de um-para-um entre instncias de protocolo e instncias de n, usamos o ID de n. Cada interface em um protocolo
ter um ndice de interface (tambm chamando apenas de interface) relativo ao seu protocolo. Por padro, ento, um
arquivo de rastreamento ASCII criado a partir do rastreamento no primeiro dispositivo do n 21, usando o prefixo
prefix, seria prefix-n21-i1.tr. O uso de prefixo distingue mltiplos protocolos por n.
Sempre podemos usar o servio de nomes de objetos do ns-3 para tornar isso mais claro. Por exemplo, se usarmos
o servio de nomes para associar o nome serverIpv4 ao Ptr<Ipv4> no n 21, o nome de arquivo resultante seria
prefix-nserverIpv4-i1.tr.
Diversos mtodos tem um parmetro padro explicitFilename. Quando modificado para verdadeiro, este parmetro desabilita o mecanismo automtico de completar o nome do arquivo e permite criarmos um nome de arquivo
abertamente. Esta opo est disponvel nos mtodos que ativam o rastreamento em um nico dispositivo.
102
Captulo 7. Rastreamento
CAPTULO 8
Concluso
8.2 Finalizando
O ns-3 um sistema grande e muito complexo. Por isto, impossvel cobrir todos os aspectos relevantes em um
tutorial.
Ao leitor foi apresentada apenas uma introduo ao ns-3, entretanto, espera-se que tenha abordado o suficiente para o
incio de trabalhos e pesquisas relevantes com o simulador.
Atenciosamente, equipe de desenvolvimento do ns-3.
Traduo
Traduzido para o portugus pelos alunos do programa de doutorado inter institucional do Instituto de Matemtica
e Estatstica da Universidade de So Paulo IME-USP em parceria com a Universidade Tecnolgica Federal do
Paran - Cmpus Campo Mouro UTFPR-CM:
Frank Helbert (frank@ime.usp.br);
103
104
Captulo 8. Concluso