Você está na página 1de 11

i Universidade de Coimbra Faculdade de Cincias e Tecnologia

DEPARTAMENTO DE ENGENHARIA INFORMTICA


Introduo s Redes de Comunicao

Network Simulator 3 (ns-3)


Ano Lectivo de 2009/2010 www.nsnam.org

1. Introduo
O Network Simulator 3 (ns-3) um simulador de rede que pretende ser uma nova alternativa ao popular Network Simulator 2 (ns-2). O ns-3 um software gratuito, distribudo sob a licena GNU GPLv2 e que disponibilizado gratuitamente para investigao, desenvolvimento e utilizao. O desenvolvimento do ns-3 comeou em Julho de 2006 e est programado que dure cerca de quatro anos. O projecto ns-3 financiado por vrias instituies como a Universidade de Washington, o Georgia Institute of Technology e o ICSI Center for Internet Research, tendo ainda o suporte do Plante research group do INRIA Sophia-Antipolis. O ns-3 escrito em C++ e Python e esta disponvel para vrios sistema operativos como Linux, OS X e Windows (atravs utilizao do Cygwin).

2. Objectivos
Nesta ficha pretende-se explicar o funcionamento geral do simulador ns-3 e o desenvolvimentos de alguns scripts C / Python que simulem topologias simples. Ao mesmo tempo sero mostrados alguns mtodos para avaliao dos resultados obtidos, atravs da utilizao do NAM The Network Animator para a visualizao grfica da simulao e tambm do Wireshark para uma anlise mais detalhada dos pacotes.

3. Instalao e documentao
As duas principais dependncias exigidas para a instalao de ns-3 so: uma instalao actualizada de Python (2.4 ou acima) e um compilador GNU C. Assim como a alternativa de simulao anterior (ns2), ns-3 distribudo de duas formas: em uma verso compacta (all-in-one) e tambm uma verso do cdigo fonte disponvel em repositrios remotos (neste caso Mercurial). Caso a escolha tenha sido pela distribuio compacta, importante observar os requisitos de software necessrios para a devida instalao de ns-3. Essa lista de pr-requisitos pode ser encontrada em: http://www.nsnam.org/wiki/index.php/Installation e dependem da distribuio linux em que ser feita a instalao.

IRC 2009/2010

Caso a escolha tenha sido a distribuio compacta, a instalao d-se pela execuo das seguintes instrues:
tar xvf ns-allinone-3.6.tar.bz2 cd ns-allinone-3.6 ./build.py

Posteriormente, torna-se necessrio configurar o ambiente ns. Embora a maioria das aplicaes linux se baseiem no uso de make para este propsito, o ns-3 baseia-se na aplicao waf que um sistema de build especfico para python. Desta forma, o prximo passo ser:
./waf configure

Um ltimo passo para avaliar se a instalao ocorreu correctamente o teste da instalao. Este teste pode ser feito pela execuo da seguinte instruo:
./test.py

Uma peculiaridade para esta verso do simulador ns-3 so os distintos formatos permitidos para o trace de pacotes e trfego das simulaes. Os ficheiros de trace gerados no ns-2 no so mais lidos nesta verso. Para este novo formato de ficheiros de trace, deve-se utilizar uma aplicao que capaz de analisar e animar as ligaes point-to-point peculiares ao ns-3. Esta aplicao a NetAnim (http://www.nsnam.org/wiki/index.php/NetAnim). Conforme ser observado nos exemplos posteriores, ns-3 trata a construo de ligaes entre ns de uma topologia atravs de ligaes conhecidas como point-to-point. Essas ligaes diferem-se do formato dos canais estabelecidos em ns2. Outra estratgia comum em ns-3 e analisar o trfego pela inspeo de pacotes. Essa uma tcnica bastante comum entre os analisadores de protocolos tais como o Wireshark (http://www.wireshark.org/) ou o tcpdump. Para este fim, conforme ser discutido no segundo script, podem ser gerados ficheiros com a extenso pcap que representam uma inspeo detalhada de pacotes em modo promscuo. Com o intuito de diminuir a complexidade do processo de instalao, configurao e teste, provemos para esta ficha uma mquina virtual gerada a partir do sistema operativo Linux Ubuntu 9.10. Nesta mquina virtual j esto instalados o ns-3 e o NetAnim e pode ser obtido a partir do seguinte link: https://193.136.212.206/irc/irc_vmware_ubuntu_20091111.tar.bz2. Para aceder mquina virtual utiliza-se o seguinte utilizador:
Username: irc Password: IRC$2009

Aps o download, a mquina virtual pode ser descompactada e atravs de um player para mquinas virtuais pode-se aceder ao ambiente j preparado. Para este efeito, sugere-se o uso do ambiente VMWare Player ou Sun VirtualBox. Conforme observado na Figura 1, para o incio da execuo a partir do player, basta escolher a pasta onde foi foi executado o desempacotamento. A partir desse ponto, uma nova sesso ter incio. Nessa sesso usar-se- as seguintes credenciais:
Username: ircuser Password: ircuser

IRC 2009/2010

Figura 1 - Dilogo inicial do VMWare Player .

Abaixo seguem links para documentao ns-3: NS-3 overview: http://www.nsnam.org/docs/ns-3-overview.pdf Tutoriais NS-3: http://www.nsnam.org/tutorials.html Documentao para as classes NS-3: http://www.nsnam.org/doxygen-release/index.html Introduo ao NS-3: http://www.nsnam.org/getting_started.html

4. Criao do primeiro script O ns-3 suporta scripts escritos nas linguagem C e Python. Neste exemplo, optou-se pela criao do script utilizando a linguagem Python.
4.1. Criao do cenrio O nosso cenrio ser composto por dois ns que vo comunicar utilizando o protocolo UDP. Neste exemplo, deve guardar o seu cdigo num ficheiro com o nome primeiro.py.
#Inicializa o modulo ns3 import ns3 #Activa os logs para os vrios componentes ns3.LogComponentEnable("UdpEchoClientApplication", ns3.LOG_LEVEL_INFO) ns3.LogComponentEnable("UdpEchoServerApplication", ns3.LOG_LEVEL_INFO) #Criao de dois ns nodes = ns3.NodeContainer() nodes.Create(2)

O diagrama apresentado na Figura 2 ilustra a criao dos dois ns no nosso cenrio.


nodes: NodeContainer

Node 0

Node 1

Figura 2 Ilustrao da criao dos dois ns do cenrio

IRC 2009/2010

4.2. Criao do canal fsico de comunicao Neste momento o nosso cenrio tem dois ns mas, no entanto, no existe nenhum meio fsico para que esses mesmo ns possam comunicar. Vamos ento estabelecer a ligao fsica entre os ns.
#Criao de um objecto PointToPointHelper para a ligao ponto a ponto entre dois ns. pointToPoint = ns3.PointToPointHelper() #Definio das caracterstica da ligao pointToPoint.SetDeviceAttribute("DataRate", ns3.StringValue("10Mbps")) pointToPoint.SetChannelAttribute("Delay", ns3.StringValue("2ms")) #Instalao da ligao nos ns criados anteriormente devices = pointToPoint.Install(nodes)

A Figura 3 representa o estado actual do nosso cenrio. Neste momento j possumos os dois ns ligados atravs de uma ligao fsica.
Devices: NetDeviceContainer

Node 0

10Mpbs, 5ms

Node 1

PointToPointNetDevice Figura 3 Criao da ligao fsica entre dos dois ns da rede

4.3. Instalao do interface de rede Depois da ligao fsica, vamos agora criar os interfaces de rede para os vrios ns. Neste exemplo iremos utilizar uma stack IPv4(o ns-3 suporta tambm IPv6).
#Agrega as funcionalidades da stack TCP/IP aos ns stack = ns3.InternetStackHelper() stack.Install(nodes) #Criao do endereo IPv4 address = ns3.Ipv4AddressHelper() #Definio da rede e respectiva mascara de rede address.SetBase(ns3.Ipv4Address("192.168.1.0"), ns3.Ipv4Mask("255.255.255.0")) #Atribuio dos endereos aos respectivos ns #Como anteriormente foi definida a rede 192.168.1.0/255.255.255.0, os ns Node0 e Node1 vo ter os endereos 192.168.1.1 e 192.168.1.2, respectivamente interfaces = address.Assign(devices)

4.4. Criao de aplicaes

IRC 2009/2010

Neste momento temos todo o cenrio pronto at ao nvel da camada de rede. No entanto, no existem aplicaes a utilizar a nossa rede. Assim, necessrio criar uma aplicao. Neste exemplo vamos utilizar uma aplicao cliente-servidor, em que o cliente envia pacotes UDP ao servidor e o servidor responde ao cliente com uma cpia desse mesmo pacote.
#Cria uma aplicao que espera por pacotes UDP num determinado porto (neste caso o porto 5000, que passado como parmetro) e envia esse pacote para o remetente original echoServer = ns3.UdpEchoServerHelper(5000) #Instala a aplicao no servidor (i.e. no Node 1, que referenciado atravs da instruo nodes.Get(1)). serverApps = echoServer.Install(nodes.Get(1)) serverApps.Start(ns3.Seconds(1.0)) serverApps.Stop(ns3.Seconds(10.0)) #Cria uma aplicao que envia pacotes UDP e que espera pela resposta echoClient = ns3.UdpEchoClientHelper(interfaces.GetAddress(1), 5000) echoClient.SetAttribute("MaxPackets", ns3.UintegerValue(1)) echoClient.SetAttribute("Interval", ns3.TimeValue(ns3.Seconds (1.5))) echoClient.SetAttribute("PacketSize", ns3.UintegerValue(2048)) #Instala a aplicao anterior no n que ir actuar como remetente (i.e. Node 0) e em seguida inicia a mesma aplicao. clientApps = echoClient.Install(nodes.Get(0)) clientApps.Start(ns3.Seconds(1.5)) clientApps.Stop(ns3.Seconds(10.0))

4.5. Iniciar a simulao Depois da criao do cenrio e respectivas aplicaes, agora necessrio recorrer as primitivas que iro fazer com a simulao inicie e termine.
ns3.Simulator.Run() ns3.Simulator.Destroy()

Para correr a simulao dever colocar o ficheiro criado na pasta scratch na raiz do simulador e correr o seguinte comando:
./waf -pyrun scratch/primeiro.py

5. NetAnim Como mencionado anteriormente, em NS-3 ficheiros de trace no possuem o mesmo formato dos ficheiros produzidos em ns-2. Desta forma, tornou-se necessria uma aplicao que permitisse a leitura e gerasse animaes para ficheiros deste formato. A ferramenta NetAnim uma aplicao que d suporte execuo desta tarefa. Em nossa mquina virtual NetAnim j est instalada e pode ser automaticamente executada desde que o ficheiro de trace esteja no formato ns-3. IRC 2009/2010 5

Apresentaremos NetAnim atravs de um exemplo, disponvel tambm na mquina virtual usada nesta ficha. Aproveitamos para tambm apresentar as funcionalidades de ns-3 em linguagem C.
5.1. Captura dos parmetros iniciais

Para informar a aplicao dos valores dos parmetros (quantidade de ns na disposio esquerda e direita do plano) basta utilizar a seguinte instruo:
./waf --run 'src/contrib/net-anim/test-dumbbell --nLeftLeaf=5 --nRightLeaf=5 -animFile=dumbbell.tr'

Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (512)); Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("500kb/s")); uint32_t nLeftLeaf = 5; uint32_t nRightLeaf = 5; uint32_t nLeaf = 0; // Se diferente de zero o nmero de ns esquerdo e direito uint16_t port = 0; // Porto para onde se executa o bind dessa animao std::string animFile; // Nome que ser dado ao ficheiro de sada CommandLine cmd; cmd.AddValue ("nLeftLeaf", "Nmero de ns esquerda", nLeftLeaf); cmd.AddValue ("nRightLeaf","Nmero de ns direita", nRightLeaf); cmd.AddValue ("nLeaf", "Numero total de ns", nLeaf); cmd.AddValue ("port", "Porto para animao remota", port); cmd.AddValue ("animFile", "Nome do ficheiro de sada para posterior trace", animFile); cmd.Parse (argc,argv); if (nLeaf > 0) { nLeftLeaf = nLeaf; nRightLeaf = nLeaf; }

5.2. Criao das ligaes ponto-a-ponto

Da mesma forma que nos exemplos anteriores um objecto PointToPoint utilizado para se criarem as ligaes entre os ns, neste exemplo essas ligao so associadas a um objecto NetAnim PointToPointDumbellHelper.
PointToPointHelper pointToPointRouter; pointToPointRouter.SetDeviceAttribute ("DataRate", StringValue ("10Mbps")); pointToPointRouter.SetChannelAttribute ("Delay", StringValue ("1ms")); PointToPointHelper pointToPointLeaf; pointToPointLeaf.SetDeviceAttribute ("DataRate", StringValue ("10Mbps")); pointToPointLeaf.SetChannelAttribute ("Delay", StringValue ("1ms")); PointToPointDumbbellHelper d(nLeftLeaf, pointToPointLeaf, nRightLeaf, pointToPointLeaf, pointToPointRouter);

Endereamento e aplicao cliente O endereamento feito atravs de um objecto Ipv4AddressHelper. E a aplicao cliente, baseada em UDP, disparada e finalizada numa distribuio uniforme.
InternetStackHelper stack; d.InstallStack (stack);

IRC 2009/2010

d.AssignAddresses(Ipv4AddressHelper("10.1.1.0", "255.255.255.0"), Ipv4AddressHelper("10.2.1.0", "255.255.255.0"), Ipv4AddressHelper("10.3.1.0", "255.255.255.0")); OnOffHelper clientHelper ("ns3::UdpSocketFactory", Address ()); clientHelper.SetAttribute("OnTime", RandomVariableValue (UniformVariable (0, 1))); clientHelper.SetAttribute("OffTime", RandomVariableValue (UniformVariable (0, 1))); ApplicationContainer clientApps; for (uint32_t i = 0; i < d.RightCount(); ++i) { // Pacotes so gerados e enviados para o ns correspondente da direita AddressValue remoteAddress(InetSocketAddress(d.GetLeftAddress(i), 1000)); clientHelper.SetAttribute("Remote", remoteAddress); clientApps.Add(clientHelper.Install(d.GetRight(i))); } clientApps.Start (Seconds (0.0)); clientApps.Stop (Seconds (10.0)); // Configurao da area onde dar-se- a animao d.BoundingBox(1, 1, 10, 10);

5.3. Inicio da animao

O NetAnim possui uma classe que permite a configurao da animao da simulao a classe AnimationInterface. A partir de um objecto desta classe inicia-se a visualizao desta simulao.
AnimationInterface anim; if (port > 0) { anim.SetServerPort(port); } else if (!animFile.empty()) { anim.SetOutputFile(animFile); } anim.StartAnimation(); Ipv4GlobalRoutingHelper::PopulateRoutingTables (); std::cout << "Running the simulation" << std::endl; Simulator::Run (); std::cout << "Destroying the simulation" << std::endl; Simulator::Destroy (); std::cout << "Stopping the animation" << std::endl; anim.StopAnimation();

5.4. Resultados

Os resultados so animaes similares s previamente obtidas em ns-2, conforme observa-se na Figura 4. O resultado da Figura 4 automaticamente obtido a partir da execuo da instruo NetAnim dumbbell.tr.

IRC 2009/2010

Figura 4 - Animao atravs de NetAnim.

6. Segundo script
Neste segundo exemplo vamos explorar o uso de sockets em conjunto com o protocolo TCP. Criaremos uma topologia simples, como pode ser observado na Figura 5. Nosso intuito enviar pacotes at um tamanho mximo (estipulado no script) de forma que o n n2 j no possa mais responder ao n requisitante (n 0).

Figura 5 - Topologia de teste para o segundo exemplo.

6.1. Definio da topologia


#include <ctype.h> #include <iostream> #include <fstream> #include <string> #include <cassert> #include "ns3/core-module.h" #include "ns3/helper-module.h" #include "ns3/node-module.h" #include "ns3/simulator-module.h" using namespace ns3;
/* Primeiro passo: criar containers para os ns e isolar o n n2 para que ele possa tornar-se nosso terminador */

NodeContainer n0n1; n0n1.Create (2); NodeContainer n1n2; n1n2.Add (n0n1.Get (1)); n1n2.Create (1);
/* Assim como no script anterior, lanamos mo de PointToPointHelper para criar o canal de comunicao que vai abrigar os ns criados anteriormente */

IRC 2009/2010

PointToPointHelper p2p; p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(10000000))); p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(10)));
/* Embora tenhamos criados os ns, estes ainda no foram associados a nenhum tipo de dispositivo. Dessa forma cada container de ns torna-se um container de dispositivos de rede, podendo, posteriormente incorporar caractersticas tpicas destes dipositivos */

NetDeviceContainer dev0 = p2p.Install (n0n1); NetDeviceContainer dev1 = p2p.Install (n1n2);

6.2. Incorporao da pilha de protocolos TCP/IP Para que quaisquer testes possam ser feitos, necessrio associar endereos e os comportamentos associados aos protocolos dessa pilha. Para que o teste possa ser feito cada um dos ns estar associado a um endereo IP.
//As seguintes instrues instala a pilha de protocolos TCP/IP em todos os ns

InternetStackHelper internet; internet.InstallAll ();


/* Agora cada container de dispositivos recebe um endereo base, de onde o script poder obter endereos para os ns */

Ipv4AddressHelper ipv4; ipv4.SetBase ("10.1.3.0", "255.255.255.0"); ipv4.Assign (dev0); ipv4.SetBase ("10.1.2.0", "255.255.255.0"); Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev1);
//Para que ambos conjuntos de endereos sejam alcanveis, popula-se as tabelas de roteamento

Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

6.3. Definio dos comportamentos esperados para os ns Conforme descrito anteriormente, o n n2 comportar-se- como um terminador das requisies. Para tanto, associa-se a esse n um objecto PacketSinkHelper. Por outro lado, por se tratar de um cenrio baseado no protocolo TCP, o requisitante (n1) passa a estar associado a um socket para onde n2 confirma as requisies efectuadas.

//Como recurso da linguagem de programao associamos servPort a um valor de porto fixo

uint16_t servPort = 8007;


/* Cria-se um objecto PacketSinkHelper, com as intrnsecas funcionalidades esperadas para um n que comporte o protocolo de transporte TCP */

PacketSinkHelper sink ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), servPort));


/* Uma aplicao hipottica associada ao n n2. Supe-se, dessa maneira, que o n n0 possa fazer requisies a essa aplicao. */

ApplicationContainer apps = sink.Install (n1n2.Get (1)); apps.Start (Seconds (0.0)); apps.Stop (Seconds (3.0));
/* Agora devemos criar uma fonte para o envio de pacotes a partir de n0. A criao do socket e a associao ao n n0 permitir nossa aplicao identificar o endereo para onde encaminhar a resposta a alguma requisio. */

Ptr<Socket> localSocket = Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId ()); localSocket->Bind ();

IRC 2009/2010

/* Para simular o envio de requisies uma nova funo foi criada StartFlow. Essa funo disparada quando do incio da simulao (Simulator::ScheduleNow). */

Simulator::ScheduleNow (&StartFlow, localSocket,ipInterfs.GetAddress (1), servPort);

6.4. Implementao do envio de pacotes Conforme mencionado anteriormente, espera-se que o n n2 receba requisies do n n0. Essas requisies devem cessar quando atingirem um limite mximo (2000000 bytes). Para explicar como o envio foi produzido e o limite testado, esta etapa foi dividida em duas subetapas: definio dos elementos bsicos para envio e teste do tamanho dos pacotes e posteriormente as funes.
Elementos bsicos para o envio e teste // limite mximo de bytes que se pretende enviar static const uint32_t totalTxBytes = 2000000; static uint32_t currentTxBytes = 0; static const uint32_t writeSize = 1040; //buffer do n n0 de onde sero enviados dados para o n n2 uint8_t data[writeSize]; /* Para efeitos de teste, algum contedo colocado em data para que possa ser enviado ao n n2 */ for(uint32_t i = 0; i < writeSize; ++i) { char m = toascii (97 + i % 26); data[i] = m; } Funes
void StartFlow(Ptr<Socket> localSocket,Ipv4Address servAddress, uint16_t servPort) { // o socket que foi enviado automaticamente conectado ao servidor localSocket->Connect (InetSocketAddress (servAddress, servPort)); /* Sucessivas chamadas sero feitas e logo aps um teste da quantidade de informao enviada feito, dessa forma, quando atingir-se o limite esperado, as chamadas so cessadas. */ localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull)); WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ()); } /* o buffer (data) previamente ocupado com algum contedo, ser constantemente utilizado. Essa funo retornar o fim da conexo socket ao n n0 assim que a quantidade de bytes enviada atingir o valor totalTxBytes e j no houver dados a serem enviados para o n n2. */ void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace) { while (currentTxBytes < totalTxBytes && localSocket->GetTxAvailable () > 0) { uint32_t left = totalTxBytes - currentTxBytes; uint32_t dataOffset = currentTxBytes % writeSize; uint32_t toWrite = writeSize - dataOffset; toWrite = std::min (toWrite, left); toWrite = std::min (toWrite, localSocket->GetTxAvailable ()); int amountSent = localSocket->Send (&data[dataOffset], toWrite, 0); if(amountSent < 0) { return; } currentTxBytes += amountSent; } localSocket->Close (); }

6.5. Avaliao do resultado

IRC 2009/2010

10

Ainda torna-se necessrio definir em que formato o resultado dessa simulao vai ser averiguada. Como dito anteriormente, o ns-3 d a possibilidade de desviar o comportamento das topologias de teste para ficheiros pcap, ou seja, permite a monitorizao dos pacotes em modo promscuo, o qual pode posteriormente ser analisado por um analisador de trfego como o Wiresharck. Para que esse script pudesse comportar-se dessa forma, as seguintes instrues foram adicionadas ao script.
// uma alternativa para monitorizar o trfego atravs de um ficheiro de trace std::ofstream ascii; ascii.open ("segundo.tr"); PointToPointHelper::EnableAsciiAll (ascii); /* o canal previamente estabelecido pode ser colocado em modo promscuo de forma que toda comunicao possa ser monitorizada e armazenada em ficheiros no formato segundo-XX.pcap */ PointToPointHelper::EnablePcapAll ("segundo"); /* Apenas para resguardar de possveis falhas o simulador fora uma parada a um determinado momento para o caso de nunca atingir-se o limite de bytes estipulado. */ Simulator::Stop (Seconds(1000)); Simulator::Run (); Simulator::Destroy ();

Como parte da avaliao do resultado, pode-se utilizar do Wireshark para averiguar todo o trfego do segundo script que foi direccionado para ficheiros pcap. Observe pela Figura 6 que como tratase de uma aplicao TCP inmeros acknowledgments foram necessrios.

Figura 6 - Captura dos primeiros pacotes enviados pelo segundo script no Wireshark.

IRC 2009/2010

11