You are on page 1of 50

Tutorial de Redes Definidas por Software

Elton Gastardelli Kleis

Engenheiro de Telecomunicações pela Universidade


Federal Fluminense (UFF), e Pós-graduando em Engenharia
de Redes pelo Instituto Infnet.

Tutorial I: http://www.teleco.com.br/tutoriais/tutorialsw1/pagina_1.asp
Tutorial II: http://www.teleco.com.br/tutoriais/tutorialsw2/pagina_1.asp
Sumário

Redes Definidas por SW I: Introdução .......................................................................................... 3


Redes Definidas por SW I: Redes de Computadores..................................................................... 4
Redes Definidas por SW I: Conceitos Fundamentais .................................................................. 15
Redes Definidas por SW I: OpenFlow .......................................................................................... 19
Redes Definidas por SW I: Considerações finais ......................................................................... 27
Redes Definidas por SW II: Introdução ....................................................................................... 28
Redes Definidas por SW II: Mininet ............................................................................................ 29
Redes Definidas por SW II: Aplicação Desenvolvida ................................................................... 31
Redes Definidas por SW II: Simulação e resultados .................................................................... 34
Redes Definidas por SW II: Códigos Implementados .................................................................. 40
Redes Definidas por SW II: Considerações finais ........................................................................ 50

2
Redes Definidas por SW I: Introdução
As redes de computadores nos permitem fazer coisas inimagináveis há poucas décadas.

Seu embrião teve início no final da década de 1960 com a então denominada ARPANET (Advanced
Research Projects Agency Network), que buscava interligar as bases militares e os departamentos de
pesquisa norte-americanos.

Muito evolui desde então. Modelos para protocolos de comunicação foram criados e muitos
protocolos foram desenvolvidos, sejam para suprir a demanda de aplicações, sejam para calcular os
caminhos que os pacotes devem percorrer ao longo da rede.

Devido à essa evolução de ideias, desde o início das pesquisas sobre comutação de pacotes e da
ARPANET, juntamente com a evolução do hardware utilizado, hoje temos inúmeras possibilidades
na rede. Anexar enormes quantidades de arquivos em nossos e-mails, jogar jogos com pessoas do
mundo inteiro em tempo real, ou até mesmo realizar ligações telefônicas através da Internet.

Entretanto, talvez hoje as redes estejam na iminência de uma mudança de paradigma, mudança essa
que possibilitará o desenvolvimento de aplicações cuja implementação com a tecnologia atual seria
impossível. Com a utilização de redes definidas por software (SDN - Software-Defined Networking),
será possível um total controle da rede. Não haverá mais a necessidade de hardwares especializados,
mas sim, poderá se utilizar hardwares genéricos programáveis. Novos protocolos poderão ser
testados e implementados com uma rapidez nunca antes vista e aplicações que hoje são impensáveis
se tornarão absolutamente viáveis através da implementação dessa tecnologia.

Motivação e Objetivos

Atualmente, as redes de computadores se tornaram parte essencial da infraestrutura de nossa


sociedade. Hoje, inúmeras aplicações “rodam” sobre a Internet, aplicações essas que não foram
imaginadas no projeto inicial das redes de computadores. Com o objetivo de suportar o número
crescente de aplicações e usuários, diversos “remendos” foram sendo feitos ao longo dos anos.
Entretanto, substancialmente, o núcleo da rede se manteve o mesmo. Os softwares de switches e
roteadores não podem ser reprogramados e novas ideias e protocolos não podem ser testados em
uma rede em produção, fato esse denominado por alguns autores como “ossificação” da rede
(McKeown et al., 2008). Nesse cenário, surgem as redes definidas por software.

O conceito de redes programáveis não é novo. Como exemplo, tem-se o conceito de redes ativas na
década de 1990 (Feamster et al., 2014). Entretanto, pela primeira vez, o conceito é amplamente
difundido e aceito. As redes definidas por software vêm apresentando grande aceitação por parte
da comunidade acadêmica e pelos principais fabricantes de equipamentos, que já começaram a
desenvolver soluções voltadas para esse modelo.

Diante o exposto, como objetivo geral, essa monografia pretende apresentar ao leitor esse novo
paradigma em redes de computadores, mostrando o quão importante o mesmo será para
pesquisadores que necessitam testar novos protocolos assim como para gestores que precisam
gerenciar redes de computadores todos os dias.

Para tal, os seguintes objetivos específicos devem ser atingidos:


 Apresentação dos conceitos básicos das redes de computadores atuais, fornecendo um
conhecimento mínimo para aqueles que não estejam familiarizados com redes de
computadores;
 Abordar conceitos como plano de controle e de dados, e sua separação nas redes definidas
por software;

3
 Apresentar conceitos do OpenFlow, implementação mais difundida das redes definidas por
software;
 Apresentação de uma aplicação programada em Python, para redes definidas por software.
Essa aplicação altera o caminho de um fluxo pré-estabelecido, mediante a uma alta
utilização da largura de banda do caminho principal;

Tutoriais

Este tutorial parte I apresenta inicialmente os conceitos básicos de redes de computadores para que
seja possível o entendimento posterior das redes definidas por software. A seguir trata dos conceitos
básicos sobre planos de controle e de dados e em seguida da definição de redes definidas por
software. Finaliza apresentando o padrão/protocolo OpenFlow, os switches OpenFlow, e os
principais controladores disponíveis, dando enfoque ao POX, controlador utilizado neste estudo.

O tutorial parte II apresentará inicialmente as características do emulador de redes Mininet, utilizado


neste estudo. A seguir apresentará uma descrição detalhada da aplicação desenvolvida e os
resultados dos testes realizados, verificando como o uso da aplicação reduziu a perda de pacotes.
Serão apresentados também os códigos das aplicações implementadas por software para este
estudo. Finalmente apresentará as conclusões deste estudo.

Redes Definidas por SW I: Redes de Computadores

Nesta seção serão abordados conceitos como modelo de camadas TCP/IP, endereçamento,
encaminhamento e classificação de pacotes. Conceitos esses fundamentais para o pleno
entendimento das vantagens e desvantagens das redes definidas por software.

Modelo em Camadas

As redes de computadores atuais, em sua maioria, seguem o modelo denominado TCP/IP


(Transmission Control Protocol / Internet Protocol). O modelo apresenta um conjunto de protocolos
para comunicação entre dispositivos. Esses protocolos são organizados de acordo com uma pilha de
camadas, onde cada camada irá oferecer serviços para as camadas superiores. Essa divisão em
camadas, ao reduzir a complexidade, facilita a implementação de novas tecnologias, permitindo
também a interconectividade entre sistemas.

A figura 1 apresenta o modelo TCP/IP de 4 camadas.

Figura 1: As quatro camadas do modelo TCP/IP

4
Na camada de aplicação, o nível mais alto do modelo, usuários utilizam programas que acessam
serviços disponíveis através da rede TCP/IP. A aplicação irá interagir com protocolos da camada de
transporte para enviar e receber dados. Como será visto adiante, o modelo foi concebido para que
todas as outras camadas sejam transparentes para o usuário final, ou seja, o mesmo não precisa ter
conhecimento sobre a implementação das camadas subjacentes.

A principal função da camada de transporte é prover uma comunicação ponto-a-ponto, ou seja,


conectando uma aplicação de um dispositivo origem com uma aplicação em um dispositivo destino,
independentemente da quantidade de equipamentos intermediários. Com isso, a camada transporte
deve aceitar dados provenientes de diversas aplicações, encapsulá-los, incluindo informações que
serão utilizadas para controle e para identificação da aplicação de origem e destino e enviar esses
dados encapsulados para as camadas mais baixas.

A camada de transporte pode também regular o fluxo de informações, podendo inclusive oferecer
um transporte confiável, como por exemplo, verificando periodicamente a conexão estabelecida e
assegurando que os dados estão sendo enviados e recebidos corretamente, chegando sem erros.
São exemplos de protocolos dessa camada, o UDP (Datagram Protocol) e o TCP.

A camada de internet lida com a comunicação de um dispositivo a outro, aceitando pedidos de envio
de pacotes da camada de transporte. A mesma irá encapsular os dados da camada de transporte em
um pacote IP, preenchendo o cabeçalho com diversas informações, inclusive com o endereço lógico
de origem (IP de origem) e o endereço lógico de destino (IP de destino).

A camada de internet também é responsável por encaminhar esses pacotes para a camada de acesso
à rede, onde os mesmos serão encaminhados diretamente para o destino (podendo vir a passar por
dispositivos como switches e hubs), se os hosts estiverem na mesma rede. Caso não estejam, como
duas redes diferentes não se “enxergam” os pacotes devem ser enviados para equipamentos que
fazem a interligação entre redes, denominados roteadores. Através dos roteadores os pacotes
podem ser encaminhados por redes intermediárias, até chegarem ao destino final. A camada de
internet também é responsável por lidar com os pacotes IP's recebidos, checando sua validade e
verificando se os mesmos são destinados para um host na rede local ou se devem ser encaminhados
para outras redes. Maiores detalhes sobre a camada de rede serão vistos na seção sobre
encaminhamento.

A camada de acesso à rede define as regras de acesso ao meio físico definindo o endereçamento
físico e os protocolos necessários para essa transmissão. Além disso, converte os dados vindos da
camada superior (internet) em sinais elétricos/ópticos, tornando possível a transmissão em cabos e
fibras ópticas.

É importante entender que para a camada de internet não importa a localização física das máquinas,
mas a localização lógica das redes. A camada de acesso à rede, é responsável pela identificação de
cada máquina (endereçamento físico) em uma rede local. O ARP (Address Resolution Protocol),
protocolo da camada de rede, fará a tradução do endereço lógico para o endereço físico, quando o
pacote de dados já estiver na rede de destino.

Para finalizar, as redes em camadas são projetadas de modo que uma determinada camada no
destino receba exatamente os mesmos objetos enviados pela mesma camada correspondente na
origem, ou seja, os mesmos dados enviados pela camada de aplicação na origem, devem ser os
mesmos dados recebidos pela camada de aplicação no destino.

As redes de computadores em geral, sobretudo a Internet, foram projetadas para prover uma
interconexão universal entre computadores independentemente das particularidades da rede aos
quais estejam conectados, tornando-se transparente para o usuário, que a vê como uma única rede

5
virtual (como pode ser visto na figura 2, a qual todas as máquinas estão conectadas. Essa
virtualização será importante para o entendimento das redes definidas por software.

Figura 2: Visão do usuário da rede (a) e Estrutura física com enlaces e roteadores (b)
Fonte: Comer, 2013

Endereçamento

Sendo a camada de internet uma das mais importantes do modelo TCP/IP, torna-se interessante o
entendimento da divisão e endereçamento lógicos dos dispositivos, assim como também é
interessante entender como ocorre o roteamento e encaminhamento dos pacotes.

Em uma rede TCP/IP, cada adaptador de rede existente em um dispositivo é identificado por um
número chamado endereço IP. Tomando-se como base o IP versão 4, esse endereço IP consiste em
quatro conjuntos de 8 bits.

Esses octetos, quando representados, são separados por pontos. Um exemplo de endereço IP segue
abaixo:

00001010.00000000.00000000.00000001

Dessa forma, todos os 32 bits são representados. Entretanto, a forma mais usual de representação
do endereço IP, é a decimal. O mesmo endereço IP representado acima, pode ser escrito como:

10.0.0.1

Dito isso, pode-se concluir que o menor octeto possível é o 00000000 (0 em decimal) e o maior octeto
possível é o 11111111 (255 em decimal), ou seja, cada octeto pode variar de 0 a 255.

Parte do endereço IP será utilizada para representar a rede a qual o dispositivo está conectado e a
outra parte será utilizada para representar o dispositivo em si.

Máscara de rede

A máscara de rede é um recurso utilizado para segmentar redes logicamente. Com esse recurso,
pode-se ter várias redes lógicas diferentes disponíveis no mesmo espaço físico, ou ainda, pode-se ter
uma única rede lógica em mais de uma localidade física.

6
Essa rede lógica pode ser entendida como conjuntos independentes de dispositivos (computadores,
impressoras, switches) conectados à rede em um determinado espaço físico. As divisões em redes
lógicas diferentes são feitas justamente com base no endereço IP e na máscara de rede.

A máscara de rede é definida como um conjunto de 32 bits divididos em quatro octetos, assim como
o endereço IP. Entretanto, algumas regras são levadas em consideração na criação da máscara de
rede (Filho, 2013):
 Não pode haver a mistura de algarismos 0 e 1;
 Não pode haver algarismo 0 antes de algarismo 1;

Segue abaixo um exemplo de máscara de rede, com os bits representados e também na forma
decimal:

11111111.00000000.00000000.00000000

255.0.0.0

Essa máscara de rede será comparada com o endereço IP. Os bits que forem 1 na máscara de rede
representam a porção da rede no endereço IP e os bits que forem 0 representam o dispositivo.

Logo, pegando-se o endereço IP do exemplo acima e analisando-o com o exemplo de máscara de


rede, tem-se que os oito primeiros bits do endereço IP são referentes à rede, ou seja, o valor “10”.
Já os “.0.0.1” representam o dispositivo dessa rede.

A notação usual, a notação CIDR (Classless Inter-Domain Routing), é a representação do endereço IP,
seguido de uma barra (/) e da quantidade de bits que são correspondentes à porção de rede.

Logo, como foram utilizados oito bits para a máscara de rede acima, temos a seguinte notação:

10.0.0.1/8

Outro exemplo segue abaixo:

IP: 11000000.10101000.00000000.00000001 = 192.168.0.1

Máscara: 11111111.11111111.11111111.00000000 = 255.255.255.0

Notação CIDR: 192.168.0.1/24

Logo, os 24 primeiros bits representam a porção do IP destinado à rede e os últimos 8 bits


representam o dispositivo daquela rede. Para representar o endereço de rede, completa-se a parte
do endereço IP referente ao dispositivo com bits zero.

Logo para os dois exemplos apresentados têm-se as redes:

10.0.0.0/8

192.168.0.0/24

Os conceitos de máscaras de rede e de endereço de rede são importantes, pois os mesmos serão
utilizados nos roteadores para a realização do encaminhamento que será abordado a seguir.

7
Encaminhamento

Para que o conceito de encaminhamento de pacotes em redes de computadores atuais possa ser
compreendido, é importante diferenciar-se os tipos de serviços que a camada de internet pode
oferecer.

A camada de internet oferece dois tipos distintos de serviços. O serviço orientado a conexão e o
serviço não orientado a conexão. As redes orientadas a conexões são denominadas redes de circuitos
virtuais. Como exemplos, têm-se as redes ATM (Asynchronous Transfer Mode) e Frame Relay. Já a
Internet é uma rede de datagramas, ou seja, uma rede não orientada a conexões. Nesse trabalho,
quando não especificado o contrário, o texto estará tratando das redes não orientadas a conexões.

O serviço de entregas oferecido pela camada de rede em uma rede de datagramas, como a Internet,
pode ser definido como incerto, de melhor esforço (best-effort) e com entrega de pacotes sem
conexão.

O serviço é incerto, pois a entrega de pacotes não é garantida. Os pacotes podem ser perdidos,
duplicados, podem chegar atrasados ou até mesmo fora de ordem. O serviço é dito de melhor
esforço, porque os pacotes tentarão ser entregues, entretanto não há garantias. Não há garantia de
largura de banda e nem mesmo indicações de congestionamento.

Finalmente o serviço também é definido como sem conexão, pois cada pacote é tratado
independentemente. Uma sequência de pacotes enviados de um dispositivo a outro, podem trafegar
por diferentes caminhos. Não existe um circuito pré-definido como existe, por exemplo, nas redes
de circuitos virtuais. Uma exceção seria a tecnologia MPLS (Multiprotocol Label Switching) que será
abordada posteriormente.

O protocolo IP, um dos mais importantes do modelo TCP/IP, apresenta todas as características
supracitadas e ainda:
 Define a unidade básica de dados que será transmitida através da rede TCP/IP, especificando
o formato dos pacotes utilizados por todos os dados.
 O IP define uma série de regras, como por exemplo, como dispositivos e roteadores devem
processar os pacotes e as condições sob as quais os pacotes podem ser descartados (Comer,
2013)

Apenas a título de ilustração, segue na figura 3 o formato do cabeçalho IPv4:;

Figura 3: Cabeçalho do protocolo IPv4


Fonte: RFC 791

Conforme dito anteriormente, a transmissão de datagramas IP entre dois dispositivos em uma única
rede física, não envolverá o uso de roteadores. O dispositivo que está enviando os dados encapsulará

8
o datagrama em um quadro, vinculará o endereço do próximo salto ao endereço físico do dispositivo
de destino e enviará o quadro resultante para o dispositivo de próximo salto.

Caso o dispositivo não esteja na mesma rede, o protocolo selecionará o próximo roteador para onde
o pacote deve ser enviado. Esse processo se repete até que o pacote chegue a um roteador que
possa entregar o pacote diretamente para o dispositivo de destino.

Com o objetivo de descobrir se o dispositivo de destino se encontra conectado em uma de suas


redes, o roteador realiza um teste simples. Como foi visto, o endereço IP é dividido em duas partes,
uma que irá identificar a rede e outra que irá identificar o dispositivo. Logo, ao receber o quadro, o
roteador desencapsula o pacote e compara os bits referentes à identificação da rede do endereço IP
do dispositivo destino com o endereço de rede dos endereços IP's de suas interfaces. Uma
equivalência significa que o dispositivo destino se encontra na rede ligada a essa interface. Esse teste
é computacionalmente eficiente, pois requer apenas algumas instruções de máquina.

O encaminhamento dos pacotes é do tipo próximo salto, ou seja, o roteador que acabou de receber
o pacote, não precisa saber quais são todos os saltos intermediários que o pacote deverá percorrer
até chegar ao destino. Precisa saber apenas qual é o próximo salto, e para isso, o mesmo irá verificar
sua tabela de encaminhamento (FIB - Forwarding information base).

Se todos os roteadores da internet precisassem ter em suas tabelas de encaminhamento todos os


IP's disponíveis, os mesmos precisariam de uma enorme quantidade de memória além de que, a cada
alteração de rota os roteadores precisariam reescrever inúmeras entradas. Entretanto, as tabelas de
encaminhamento precisam conter apenas o endereço das redes, ou seja, o prefixo das redes dos
endereços IP.

Então, uma tabela de encaminhamento terá, conceitualmente, um conjunto de pares (P,R) onde “P”
é o prefixo da rede e “R”, é o endereço IP do próximo roteador para onde os dados devem ser
enviados com o objetivo de chegarem a rede “P”.

Pode-se pensar que o protocolo de roteamento, software que preencherá as informações na FIB,
escolherá as melhores rotas de acordo com a utilização corrente do link, pelo tamanho do
datagrama, tipo de dados que estão sendo transportados ou ainda de acordo com o custo dos links.
Entretanto, será visto que a maioria dos protocolos de roteamento são bem menos sofisticados,
selecionando rotas baseadas em dados fixos sobre menores caminhos. Fato que é interessante
ressaltar, já que nas redes definidas por software, novos protocolos de roteamento com as mais
diversas métricas poderão ser implementados facilmente, tornando o encaminhamento mais
inteligente e robusto.

Voltando-se ao encaminhamento de pacotes, o algoritmo realizado pelo roteador ao receber um


pacote pode ser resumido na figura 4.

9
Figura 4: Algoritmo executado pelo roteador ao receber um pacote
Fonte: Algoritmo baseado em Comer, 2013

Entretanto, para o algoritmo acima funcionar corretamente, algumas condições precisam ser pré-
definidas.

Primeiramente, diferentemente do modelo conceitual de tabelas de encaminhamento, a tabela


precisa conter o IP da sub-rede de destino que será comparado, a máscara de rede, o IP do próximo
roteador e a interface para onde devem ser enviados os pacotes. A interface também é importante,
pois como um roteador pode estar conectado a duas ou mais redes, o mesmo precisa saber por qual
interface deve enviar os frames. Em segundo, as entradas na tabela de encaminhamento precisam
ser organizadas de forma decrescente, ou seja, as rotas que apresentarem uma máscara de rede
maior (rotas mais específicas) devem ser verificadas antes das rotas mais genéricas (Comer, 2013).

O encaminhamento, como foi visto, é uma das principais funções do protocolo IP e dos roteadores.
O mesmo não poderia atualmente ser executado corretamente, se não existissem os protocolos de
roteamento. Como será visto a seguir, as entradas na tabela de encaminhamento poderiam até ser
configuradas manualmente, mas essa ação com as redes de computadores atuais, principalmente a
Internet, se tornaria impraticável.

Roteamento

Na seção anterior, foi visto o encaminhamento desempenhado pelo IP, onde dado um determinado
pacote IP, é feita a verificação do próximo salto na tabela de encaminhamento e o direcionamento
desse pacote para o mesmo.

As rotas da tabela de encaminhamento podem ser originadas basicamente de três formas. A primeira
são as rotas diretas. São as redes as quais o roteador se conecta diretamente. A segunda é a forma
estática, onde o gestor da rede precisa configurar cada rota manualmente. Pode ser utilizada em
pequenas redes domésticas, entretanto em redes mais complexas, onde existirão diversos
roteadores organizados em uma malha, existindo diversos enlaces entre eles, essa configuração
manual torna-se muito onerosa. A configuração das rotas manualmente também se torna um
problema devido à necessidade de reagir dinamicamente às mudanças da rede, como por exemplo
devido a falhas de um enlace ou ainda quando novos roteadores são acrescentados.

10
Já na terceira forma, chamada de roteamento dinâmico, as rotas serão configuradas
automaticamente, de acordo com os protocolos de roteamento e como será visto, existem
basicamente dois tipos predominantes, os protocolos do tipo vetor distância e do tipo estado de
enlace.

Antes de verificar-se o roteamento dinâmico, torna-se interessante a distinção de protocolos IGP


(Interior Gateway Protocol) e EGP (Exterior Gateway Protocol). A Internet, como é sabido, é uma rede
de redes de computadores. Cada agrupamento organizacional é definido como um sistema
autônomo (AS - Autonomous System), sistema esse que pode operar isoladamente de todos os
outros agrupamentos. Logo, nem todas as informações de roteamento que são trafegadas
internamente dentro de um AS devem ser compartilhadas com outros AS's, já que não é interessante
a divulgação de detalhes internos do mesmo. Com isso, têm-se os protocolos que distribuem
informações de roteamento dentro dos AS's, chamados de IGP's e os protocolos EGP's, protocolos
de roteamento que distribuem informações entre AS's (Farrel, 2004).

A figura 5 ilustra o aprendizado das rotas pelo rotador.

Figura 5: Aprendizado de rotas e distinção entre as bases de roteamento e encaminhamento


Fonte: Farrel, 2004

As rotas provenientes a partir dos protocolos de roteamento são combinadas com as rotas estáticas
configuradas e com as rotas diretas descobertas, dando origem a RIB (Routing Information Base).

A RIB apresenta diversas informações sobre as rotas disponíveis na rede. Parte dessa informação
pode sugerir várias rotas para um único destino, e um mecanismo de decisão de roteamento aplica
políticas de roteamento para determinar as melhores rotas. A RIB dará origem a FIB. A FIB oferece
informações não ambíguas ao componente do roteador que encaminha os pacotes de dados.

11
Protocolos do tipo Vetor Distância

A ideia dos protocolos dessa modalidade é bastante simples. Cada roteador mantém uma lista de
todos os destinos alcançáveis da rede e distribui essa lista de tempos em tempos para seus vizinhos.

Cada entrada na tabela de roteamento identificará a rede de destino, o roteador usado para o
próximo salto e a ``distância'' até a rede de destino. Essa distância geralmente será a quantidade de
saltos (hops) até o destino. Por exemplo, uma rede diretamente conectada estará a zero saltos de
distância. Se um datagrama precisa passar por “N” roteadores para chegar ao destino, o destino está
a “N” saltos de distância.

Quando um roteador novo “X” é inserido, primeiramente ele irá se anunciar aos vizinhos. Os vizinhos
propagarão a informação dizendo que podem chegar até “X” com um salto de distância e assim
sucessivamente.

Quando uma mensagem, por exemplo, proveniente de “X”, chega em “Y”, “Y” tomará as seguintes
ações:
 Se “X” conhece um destino que “Y” não, “Y” irá adicionar esse destino a sua tabela de
roteamento, configurando como próximo salto “X” e somando 1 ao custo para se chegar a
determinado destino;
 Se “X” conhece um caminho mais curto para o destino, “Y” substitui a entrada em sua tabela
de roteamento, configurando o próximo salto para “X” e corrigindo o custo;
 Se a entrada para um determinado destino já existe em “Y”, sendo o próximo salto para a
mesma, “X” e “X” anuncia um valor de custo diferente ao anterior, “Y” irá atualizar sua
tabela, corrigindo o custo;

Exemplo de tabela de encaminhamento pode ser visto na figura 6.

Figura 6: Tabela de encaminhamento de “Y” (a), Mensagem de “X” e mudanças em “Y” (b)
Fonte: Figura baseada em Comer, 2013

Essa modalidade de protocolos, torna-se ideal para redes pequenas a médias, uma vez que a
transmissão de toda a tabela de roteamento para cada vizinho é lenta e a ocorrência de perdas pode
causar loops, demandando um longo tempo para a convergência das informações. Como vantagens,
têm-se a baixa complexidade de implementação e os baixos requisitos de processamento e memória.

Como exemplos de protocolos do tipo vetor distância, têm-se os protocolos RIP (Routing Information
Protocol) e EIGRP (Enhanced Interior Gateway Routing Protocol).

Protocolos do tipo Estado de Enlace

Diferentemente dos protocolos do tipo vetor distância, os protocolos do tipo estado de enlace não
irão distribuir uma lista de rotas, informando os custos e os destinos que o mesmo pode atingir.

12
Os roteadores ficarão, periodicamente, testando os status das conexões com seus vizinhos,
realizando a troca de pequenas mensagens para constatar se o vizinho está ativo e é atingível. Caso
o vizinho responda a mensagem, o link estará up, caso negativo, o mesmo será considerado down.

Após a descoberta dos vizinhos, o roteador envia periodicamente mensagens para informar aos
outros roteadores da rede sobre os status de cada um de seus links (mensagens LSP - Link State
Packet - ou LSA - Link State Advertisement - de acordo com o protocolo). É importante enfatizar que
essas mensagens de status não especificam rotas, informam apenas se a comunicação é possível
entre o par de roteadores referidos na mensagem.

Esse processo de inundação das mensagens é simples. O roteador recebe um LSP e verifica em seu
banco de dados de estado de enlace se já conhece o enlace referido na mensagem. Se conhecer, ele
descartará o LSP, mas caso não conheça, ele acrescentará o enlace ao seu banco de dados e enviará
o novo LSP em cada uma de suas interfaces, exceto a interface em que a mensagem foi recebida
originalmente.

Logo, após a rede convergir, cada roteador possuirá um mapa completo e idêntico da rede.

Para calcular as rotas entre os enlaces disponíveis na rede, os roteadores executam o algoritmo de
Dijkstra, algoritmo esse que irá calcular o melhor caminho entre o roteador local e todos os outros
destinos.

Um dos protocolos de estado de enlace mais conhecidos, o OSPF (Open Shortest Path First), têm
métrica padrão proporcional à largura de banda dos enlaces. Com isso, o melhor caminho sempre
será o mais rápido, ao contrário do vetor distância, que usa o caminho com menor número de saltos.

Outra vantagem dos protocolos de estado de enlace é que cada roteador realiza os cálculos das rotas
independentemente, usando os mesmos dados de status originais, não dependendo de roteadores
intermediários como o vetor distância. Esse tipo de protocolo é ideal para redes grandes, pois sua
percepção de problemas ou de novos roteadores e a consequente propagação dessas informações
são rápidas. Mas, como desvantagem, o cálculo das alterações nas tabelas de roteamento exige
bastante processamento.

São exemplos de protocolos o OSPF e o IS-IS.

Nessa seção, termina-se uma breve introdução ao funcionamento das redes de computadores atuais.
A próxima seção, tem como objetivo apresentar a comutação baseada em rótulos, que será a base
da tecnologia MPLS. Devido à flexibilidade de roteamento existente em tal tecnologia, torna-se
interessante a citação da mesma, para posterior compreensão das redes definidas por software.

Comutação Baseada em Rótulos

A comutação baseada em rótulos é o processo de encaminhar pacotes de dados dentro da rede,


baseado em algum rótulo associado com cada pacote. Essa ideia surgiu em meados da década de
1980, com o objetivo de melhorar o desempenho na transmissão de pacotes.

A tecnologia nos comutadores explora o indexamento para atingir velocidades extremamente altas
no encaminhamento de dados. Para isso, cada pacote carrega um número inteiro conhecido como
rótulo. Quando um pacote chega no comutador, o comutador extrai o rótulo e usa o valor como
índice na tabela que irá especificar a ação apropriada. Cada comutador pode ter uma série de
interfaces de saída e a ação geralmente consiste em enviar o pacote por uma dessas interfaces.

A comutação baseada em rótulos, apresenta como grande vantagem a flexibilidade em roteamento.


Nem sempre é desejável que todos os dados para um mesmo destino sejam roteados pelo mesmo

13
caminho. Pode ser desejado que um tráfego de maior prioridade percorra um caminho mais curto,
enquanto que os tráfegos de menor prioridade, podem ser enviados por caminhos mais longos. A
maioria das técnicas de roteamento como foi visto, costuma enviar o tráfego para o caminho mais
curto.

Como citado, comutação de rótulos consiste em associar um rótulo pequeno e de formato fixo em
cada pacote de dados de modo que ele possa ser encaminhado na rede. Isso significa que cada
pacote, precisa transportar um identificador que irá dizer aos nós da rede como encaminhá-lo. Em
cada salto por meio da rede, o pacote é encaminhado com base no valor do rótulo que chega e é
encaminhado com um novo valor de rótulo. A figura 7 ilustra essa troca de rótulos e o
encaminhamento dos pacotes.

Figura 7: Troca de rótulos realizada por cada dispositivo


Fonte: Comer, 2013

Até o momento, a comutação baseada em rótulos foi descrita como uma tecnologia de rede
orientada para conexões de propósito geral. Será apresentado agora, como a comutação baseada
em rótulos pode ser combinada com a Internet. Em 1991, a IETF (Internet Engineering Task Force)
padronizou através da RFC 3031 o MPLS.

O protocolo utiliza a comutação baseada em rótulos, explicada anteriormente e como o próprio


nome sugere, o mesmo foi projetado para transportar quaisquer payloads. Na prática, o MPLS é
usado quase que exclusivamente para transportar pacotes IP.

Geralmente o MPLS é utilizado no núcleo de grandes ISP's (Internet Service Providers). Roteadores
na borda da rede do ISP irão examinar cada datagrama e decidir se utilizará algum caminho da rede
MPLS para encaminhar os dados ou se lidará com o datagrama com o encaminhamento
convencional.

O MPLS permite ao ISP oferecer serviços especiais para clientes individuais. Por exemplo, considere
uma grande empresa com escritórios no Rio de Janeiro e em Porto Alegre. Supondo que a empresa
deseje uma conexão segura entre essas duas localidades com performances garantidas, o ISP pode
estabelecer um caminho na rede MPLS entre esses dois escritórios e pode configurar os roteadores
ao longo do caminho para garantir o desempenho contratado.

Classificação de Pacotes

Como citado anteriormente, o MPLS por utilizar comutação por rótulos, permite uma maior
flexibilidade no roteamento. Isso quer dizer que, em muitos casos, gerentes de redes usam
protocolos da camada de transporte para escolherem quais caminhos determinados fluxos de dados
devem seguir dentro da rede MPLS. Por exemplo, pode existir uma regra que especifique que todo
tráfego web percorra um determinado caminho diferente dos outros tráfegos.

14
Com isso, o modelo de camadas tradicional apresentado na seção “Modelo em camadas” é
insuficiente para a tarefa de seleção de caminhos na rede MPLS, já que no modelo tradicional os
datagramas em trânsito não são desencapsulados até a camada de transporte.

Logo, se faz necessário definir a classificação de tráfego. Um sistema de classificação difere do


desencapsulamento devido à habilidade de atravessar as camadas.

Para entender a classificação de tráfego, imagine um pacote que foi recebido no roteador e colocado
na memória. Pensando no pacote como um array de bytes, para saber se um determinado pacote
corresponde a um tráfego web, basta verificar alguns bytes. Como por exemplo, verificar os bytes
correspondentes ao Ethernet type, para saber se é um pacote IP, verificar os bytes correspondentes
ao campo protocolo, no pacote IP, para saber se o protocolo utilizado é o TCP e verificar os bytes
correspondentes a porta de destino, para verificar se os mesmos correspondem à porta 80 (Comer,
2013).

Observe que todas as ações representam pesquisas no array de bytes. O sistema de classificação não
precisa entender nenhum dos cabeçalhos dos protocolos ou o significado dos bytes.

Na prática, o mecanismo de classificação geralmente utiliza uma série de regras de classificação e as


aplica até que uma correspondência é encontrada. Por exemplo, um gerente pode especificar
algumas regras como: enviar todo tráfego web pelo caminho MPLS 1, enviar todo tráfego RTP pelo
caminho MPLS 2 e enviar todo tráfego VPN pelo caminho MPLS 3.

Redes Definidas por SW I: Conceitos Fundamentais

As redes de computadores atuais são compostas de inúmeros dispositivos diferentes como


roteadores, switches e hosts que implementam diversos protocolos complexos. Conforme as
mesmas foram crescendo e se tornando parte essencial da infraestrutura de nossa sociedade,
tornou-se árdua a tarefa de testar e implementar novos protocolos.

Com esse cenário em mente, a ideia de redes programáveis foi proposta com o objetivo de facilitar
futuras evoluções nas redes de computadores. Nesta seção serão apresentados os conceitos
fundamentais das redes definidas por software, uma forma de programar a rede que vem se
destacando consideravelmente nos últimos anos.

É um novo paradigma que tem como objetivo facilitar substancialmente a gerência de redes e
permitir inovações e evoluções que o nosso modelo ``ossificado'' atual não permite (Nunes et al.,
2014).

Engenharia de Tráfego

O modelo básico de encaminhamento de pacotes consiste em encaminhar o tráfego com um dado


endereço IP de destino por um caminho pré-estabelecido pelos protocolos de roteamento.
Independente das outras características dos pacotes, como endereço IP de origem, portas TCP/UDP
ou ToS, todo o tráfego para um determinado endereço IP de destino, ao chegar em um dado
roteador, será encaminhado pela mesma interface.

Isso exposto, surge a necessidade de realizar uma engenharia de tráfego, ou seja, realizar uma maior
distinção entre os diferentes pacotes e, consequentemente, priorizar alguns em detrimento de
outros, com o objetivo de otimizar o desempenho da rede. Hoje, existem tecnologias que realizam
uma distinção e oferecem ao usuário final garantias de qualidade de serviço, como por exemplo, as

15
já citadas redes MPLS. Nas mesmas, através da criação de circuitos virtuais e da comutação baseada
em rótulos, pacotes com o mesmo endereço IP de destino podem percorrer caminhos diferentes
dentro de uma mesma rede.

Como será visto, implementando o paradigma de redes definidas por software, haverá um salto na
engenharia de tráfego, já que cada fluxo, ou seja, conjunto de pacotes de dados com algumas
características em comum, poderá ser tratado individualmente e novos softwares e formas de
encaminhar esses fluxos poderão ser desenvolvidos e implementados de acordo com as
necessidades do gestor da rede.

Um novo Paradigma em Redes de Computadores

Conceitualmente, um dispositivo de rede, como um roteador ou um switch, pode ser dividido


internamente em dois planos: o plano de controle e o plano de dados.

O plano de controle é a parte responsável pela “inteligência” do dispositivo. Por exemplo, é o plano
de controle que executa os códigos dos protocolos de roteamento, responsável pela realização do
cálculo das rotas em roteadores. Já o plano de dados é responsável por lidar com os pacotes
entrantes no dispositivo, verificando na tabela de encaminhamento por qual interface o mesmo
deverá ser encaminhado.

Atualmente, os dispositivos convencionais apresentam uma estreita ligação entre esses planos. Essa
interligação torna árdua a depuração de configurações e o controle do comportamento de
roteadores e switches (Feamster et al., 2014).

A figura 8 ilustra ambos os planos de controle e de dados:

Figura 8: Planos de controle e dados


Fonte: Comer, 2013

O conceito base das redes definidas por software consiste em separar o plano de controle do plano
de dados e retirá-lo dos dispositivos. Com isso, a rede será formada por dispositivos “burros”
encaminhadores de pacotes e por uma camada de software programável onde haverá um
controlador de rede que coordenará todas as ações dos dispositivos. Esses dispositivos
encaminhadores de pacotes serão programados através de uma interface aberta, como, por
exemplo, a interface definida pelo OpenFlow, que será visto na próxima seção.

Atualmente, encontram-se no mercado switches OpenFlow (nomenclatura dada aos dispositivos


“burros”) tanto puros quanto híbridos. Os puros, não apresentam nenhum plano de controle,
confiando completamente no controlador para lhe dizer como encaminhar os pacotes. Já os híbridos,
suportam comandos do controlador em adição às operações e protocolos atuais (Nunes et al., 2014).

16
A figura 9 ilustra a comunicação do controlador externo com o dispositivo de rede.

Figura 9: Configuração básica SDN: controlador externo configura o dispositivo de rede


Fonte: Comer, 2013

Vale salientar que as redes definidas por software suportam tanto controladores externos
totalmente centralizados, ou seja, apenas um controlador com visão total da rede, quanto
distribuídos, onde há alguns controladores controlando a rede (mesmo que de forma lógica
aparentem ser apenas um).

Na figura 10, segue uma representação de dispositivos de redes genéricos, com um sistema
operacional externo conhecedor de toda a topologia rodando no controlador e programas de
controle diversos, sejam novos ou já em uso, como por exemplo, protocolos de roteamento como
OSPF e RIP.

Figura 10: Representação de uma rede genérica


Fonte: McKeown, 2011

Por ser um novo modelo, existem benefícios e desafios/desvantagens com a sua implementação.
Seguem abaixo alguns benefícios:
 Visualização unificada da rede - Com as redes definidas por software, passa-se a ter uma
visão global de toda a rede através do controlador, simplificando configurações e gerência
dos dispositivos.

17
 Recuperação mais rápida das falhas - Devido ao controle global, seja a falha em um link ou
em um nó da rede, a rede se reorganizará e convergirá mais rapidamente para uma nova
ótima configuração, devido a utilização de algoritmos centralizados ao invés de algoritmos
distribuídos.
 Upgrade e implementação de novas aplicações - Uma das maiores vantagens desse novo
paradigma é a implementação de novas aplicações para a rede. Novos protocolos e novas
formas de encaminhar os dados poderão ser testadas e implementadas rapidamente, pois
não dependem mais de modificações no firmware do switch ou do roteador. Além disso, o
controlador pode ter seu software atualizado e alterado sem haver perda de pacotes em
uma rede em produção.

Alguns desafios/desvantagens encontrados são:


 Segurança - Uma das maiores dúvidas e preocupações são a respeito da segurança.
Retirando a “inteligência” dos dispositivos e levando-a para um controlador externo, passar-
se-ia a ter apenas um ponto crítico, onde caso seja violado, toda a rede sob esse controlador
estaria vulnerável. Essas preocupações se tornam ainda mais evidentes em empresas que já
adotam o conceito de BYOD (Bring Your Own Device) onde os colaboradores da empresa
levam para o ambiente de trabalho seus próprios aparelhos eletrônicos. Aliando esse
conceito com uma rede programável (onde inclusive vírus poderão ser programados com o
objetivo de prejudicar o desempenho e comprometer a rede), os gestores terão uma
preocupação a mais, já que qualquer dispositivo pode estar contaminado com um software
malicioso ao se conectar na rede.
 Conceito novo - As redes definidas por software assim como sua implementação mais
difundida, o OpenFlow, ainda se encontram imaturos. Muitos aspectos ainda precisam ser
amadurecidos e novas padronizações realizadas. Como exemplo, qual o nível de
dependência os dispositivos genéricos devem ter dos controladores? Os mesmos devem ser
totalmente dependentes ou apenas parcialmente? Ou ainda, como os controladores devem
ser implementados? Como deve ser realizada a distribuição e separação de domínios de
cada controlador?

Com a retirada do plano de controle dos dispositivos, pode-se modelar e moldar dinamicamente a
rede, de acordo com a necessidade do gestor, permitindo que a gerência da rede seja feita de forma
muito mais fácil e eficiente.

Atualmente, as limitações de largura de banda para cada tipo de serviço são uma realidade, nos
permitindo priorizar tráfego VoIP por exemplo, sobre outras aplicações. Entretanto, ao longo do dia,
as necessidades dos usuários da rede podem ser alteradas e possivelmente uma determinada
aplicação pode vir a ter uma prioridade maior que um tráfego VoIP.

Com redes definidas por software, em tempo real, pode-se haver essa troca de prioridades e a
determinada aplicação prioritária passa rapidamente a trafegar com alta prioridade.

Todo esse modelamento do tráfego poderá ser feito através de um console de gerência, e em
instantes, os dispositivos da rede seriam configurados, não havendo mais a necessidade de conectar-
se a cada dispositivo.

Um exemplo similar pode ser visto no webinar da Cisco (Yamamoto e Schara, 2014), onde, num
primeiro momento, um streaming de vídeo não era executado corretamente devido a baixa
prioridade e saturação do link principal. Após rápidos ajustes no controlador, o link secundário
(redundância) que antes estava ocioso, passou a ser utilizado e o streaming foi feito corretamente.

Outro exemplo de implementação foi apresentado pelo Google em 2012 na Open Network
Summit(conferência destinada a discussões sobre SDN), onde o mesmo implementou uma solução
OpenFlow/SDN no backbone que trafega os dados entre seus datacenters (Goole, 2012).

18
Como visto, as redes definidas por software já são uma realidade, mesmo que ainda de forma tímida.
Muito precisa ser evoluído e amadurecido. Questões relativas à segurança precisam ser devidamente
estudadas e analisadas. Mas a liberdade proporcionada por esse modelo não deixa dúvidas de que
num futuro próximo as redes serão muito mais dinâmicas e programáveis que as atuais, seja
utilizando o paradigma SDN ou algum outro que venha a ser derivado do mesmo.

Redes Definidas por SW I: OpenFlow

Após a definição do conceito das redes definidas por software, vista na seção anterior, algumas
dúvidas podem vir a surgir como:
 Como se dará a comunicação entre o controlador e os dispositivos de rede genéricos?
 Quais configurações e controle um determinado dispositivo deve oferecer?
 Qual deve ser o formato das mensagens enviadas pelo controlador?

As respostas para tais perguntas podem ser encontradas na implementação mais difundida das redes
definidas por software, o padrão OpenFlow.

Criado originalmente na universidade de Stanford, o OpenFlow é um padrão aberto, que surgiu da


necessidade dos pesquisadores executarem protocolos experimentais na rede acadêmica.

É uma tecnologia proposta para padronizar a forma como o controlador se comunica com os
dispositivos de rede em uma arquitetura SDN, definindo também um protocolo para essa
comunicação. Dessa forma, o OpenFlow provê meios de controlar os dispositivos de rede (switches
OpenFlow) sem a necessidade dos fabricantes exporem o código de seus produtos (Lara et al., 2014).

Assim, através do protocolo OpenFlow, os controladores podem programar as tabelas de fluxo dos
switches. Como será visto abaixo, a tabela de fluxos é parte essencial dos switches OpenFlow.

Diferentes versões do protocolo OpenFlow estão disponíveis. A primeira versão foi a 0.2.0 lançada
em Maio de 2008 e atualmente está obsoleta. A versão 1.0.0 lançada em Dezembro de 2009 foi a
mais amplamente divulgada e implementada, com isso a mesma terá um foco maior nesse trabalho.
Após a versão 1.0.0, foram lançadas as versões 1.1, 1.2, e 1.3 e 1.4 (Lara et al., 2014).

O OpenFlow encontra-se em constante evolução e o mesmo é mantido pela ONF (Open Network
Foundation).

Composição dos Switches OpenFlow

Baseando-se na versão 1.0.0, a versão mais difundida do OpenFlow, os switches OpenFlow devem
possuir/suportar as seguintes características (McKeown et al., 2008):
 Tabela de Fluxos;
 Canal Seguro;
 Protocolo OpenFlow.

A tabela de fluxos contém 12 campos que serão utilizados para a classificação de um fluxo, uma ação
para cada fluxo e contadores.

O canal seguro irá conectar o switch OpenFlow ao controlador e permitirá que os comandos passem
por ele.

Já o protocolo OpenFlow é o que será utilizado para essa comunicação.

19
A figura 11 ilustra as características citadas acima.

Figura 11: Switch OpenFlow idealizado


Fonte: McKeown et al., 2008

O switch OpenFlow deve ser capaz de realizar três simples ações com os fluxos entrantes:
 Encaminhar o fluxo entrante para uma determinada interface de saída, caso haja uma
entrada equivalente para o fluxo em questão em sua tabela de fluxos;
 Caso não haja entrada equivalente na tabela de fluxos, o switch deve ser capaz de encapsular
o primeiro pacote (ou todos, de acordo com a necessidade) e encaminhá-lo para o
controlador através do canal seguro. O controlador que irá decidir o que fazer com esse
pacote. Inclusive, decidirá se uma entrada na tabela de fluxos do switch será adicionada ou
não;
 Por último, o switch OpenFlow também deve ser capaz de descartar pacotes;

Tabela de Fluxos

Como dito anteriomente, a tabela de fluxos é parte essencial da caracterização de um switch


OpenFlow.

Pode ser observado na figura 12 que uma entrada na tabela de fluxos é composta por:

Figura 12: Entrada da tabela de fluxos


Fonte: Foundation, 2009

Os campos de cabeçalho são os campos que serão comparados com o fluxo entrante no switch
OpenFlow.

A figura 13 apresenta os campos definidos na versão 1.0.0:

Figura 13: Campos de cabeçalho


Fonte: Foundation, 2009

20
Cada campo do cabeçalho pode ser ou não definido. Por exemplo, para o switch OpenFlow funcionar
como um roteador, basta especificar o campo IP de destino.

Quanto aos contadores existem quatro tipos diferentes: Os contadores por tabela, por fluxo, por
porta e por fila. Os mesmos serão incrementados sempre que fluxos correspondentes às entradas
na tabela entrem no switch e serão utilizados em mensagens de estatísticas, também definidas pelo
OpenFlow.

A figura 14 apresenta os contadores disponíveis:

Figura 14: Lista dos contadores


Fonte: Foundation, 2009

Quanto às ações que deverão ser tomadas com os pacotes, existem ações obrigatórias que todos os
switches OpenFlow devem implementar e outras opcionais. Ao se conectar ao controlador, o switch
deve informar quais ações opcionais o mesmo implementa.

Cada entrada na tabela de fluxos é associada a uma ou mais ações. Se para uma determinada entrada
na tabela não houver uma ação especificada, os pacotes desse fluxo serão descartados.

Abaixo seguem os tipos de ações:


 Encaminhamento
o Obrigatório
 ALL - Envia o pacote para todas as interfaces, exceto a interface de entrada;
 CONTROLLER - Encapsula e envia o pacote para o controlador;
 LOCAL - Envia o pacote para a pilha de rede local;
 TABLE - Realiza ações na tabela de fluxos;
 IN\_PORT - Envia o pacote para a porta de entrada;
o Opcional
 NORMAL - Processa o pacote utilizando um encaminhamento tradicional;

21
 FLOOD - Inunda o pacote, sem incluir a interface de entrada, levando em
consideração o Spanning Tree.
 Enfileirar (opcional) - Encaminha o pacote através de uma fila relacionada a uma porta;
 Descartar (obrigatória);
 Modificar campo (opcional):
o Setar Vlan ID
o Setar Vlan Priority
o Separar o cabeçalho da Vlan
o Modificar endereço MAC (\textit{Media Access Control}) de origem
o Modificar endereço MAC de destino
o Modificar endereço IP de origem
o Modificar endereço IP de destino
o Modificar ToS
o Modificar a porta de transporte de origem
o Modificar a porta de transporte de destino

A figura 15 apresenta o fluxograma referente a entrada de um pacote em um switch OpenFlow.

Figura 15: Fluxograma do processamento dos pacotes


Fonte: Foundation, 2009

Vale salientar que, assim como nos roteadores rotas para sub-redes mais específicas têm prioridade,
entradas na tabela de fluxos que especifiquem exatamente o fluxo entrante, ou seja, entradas na
tabela que não apresentem campos coringa, terão sempre a mais alta prioridade.

O canal Seguro

Outra parte essencial da caracterização de um switch OpenFlow é o estabelecimento de um canal


seguro com o controlador. Através desse canal, o controlador irá configurar e gerenciar o switch
OpenFlow.

De acordo com “Comer, 2013”, embora uma conexão TCP seja permitida entre o switch e o
controlador, o uso de SSL/TLS é recomendado com o objetivo de garantir confidencialidade em toda
comunicação. É importante lembrar que o OpenFlow não requer uma conexão física direta entre o
switch e o controlador, podendo utilizar redes já em produção para efetuar a comunicação. Por isso,
a importância de um canal seguro.

O protocolo OpenFlow suporta três tipos diferentes de mensagens:


 Controlador-Switch - Geradas pelo controlador para gerenciar e inspecionar o estado de um
switch;
 Assíncronas - Geradas pelo switch para atualizar o controlador sobre eventos da rede e
mudanças no estado do switch;
 Simétricas - Podem ser geradas tanto pelo controlador quanto pelo switch. São enviadas
sem solicitação;

22
Abaixo, os sub-tipos de cada uma:
 Controlador-Switch
o Características (Features) - O controlador requisita as características do switch. O
switch deve responder com as características suportadas;
o Configuração (Configuration) - Usado para configurar ou solicitar configurações do
switch;
o Modificação de estado (Modify-State) - Usado para adicionar, deletar e modificar a
tabela de fluxos e para setar propriedades nas portas do switch;
o Leitura de estado (Read-State) - Coleta estatísticas;
o Envio de pacote (Send-Packet) - Utilizado para enviar pacotes por uma determinada
porta do switch;
o Barreira (Barrier) - Usado para garantir que as dependências foram atendidas ou
para receber notificações de operações finalizadas;
 Assíncrona
o Entrada de pacotes (Packet-In) - Utilizado quando fluxos não classificados entram
no switch.
o Remoção de fluxo (Flow-Removed) - Mensagem enviada para o controlador,
quando um fluxo é removido da tabela. Seja por Idle Timeout, Hard Timeout ou por
uma mensagem de modificação da tabela de fluxos que delete a entrada em
questão;
o Estado da porta (Port-Status) - Mensagem enviada para o controlador sempre que
há mudanças nas configurações das portas;
o Erro (Error) - Notificações de erros;
 Simétrica
o Hello - Mensagens trocadas entre o controlador e o switch quando uma conexão é
estabelecida;
o Echo - Mensagens usadas para identificação de latência, largura de banda e
existência de conectividade;
o Vendor - Provêem uma forma padrão para os switches OpenFlow oferecerem
funcionalidades adicionais;

No estabelecimento de uma comunicação OpenFlow, cada um dos lados (controlador e switch)


devem enviar imediatamente uma mensagem Hello (OFPT_HELLO), contendo a mais alta versão do
protocolo OpenFlow suportada pelo dispositivo. Ao receber a mensagem, o dispositivo deve escolher
a menor versão do OpenFlow entre a que foi enviada e recebida.

Se as versões forem compatíveis, a comunicação tem continuidade. Caso não sejam, uma mensagem
de erro é gerada (OFPT_ERROR) e a conexão é encerrada.

É interessante informar também que, caso haja alguma perda de conexão entre o switch e o
controlador, o switch tentará se conectar ao controlador back-up, caso exista. Caso essa conexão
também falhe, o switch entrará em modo de emergência, modo esse que utilizará apenas as entradas
na tabela de fluxos marcadas com um bit de emergência e todas as outras entradas serão deletadas.

Para modificar as tabelas de fluxos dos switches, o controlador poderá gerar cinco tipos de
mensagens diferentes. A figura 16 ilustra esses tipos:

Figura 16: Tipos de mensagens para modificação da tabela de fluxos

23
Fonte: Foundation, 2009

Como pode ser observado, as mensagens ADD adicionarão entradas na tabela de fluxos, as
mensagens do tipo MODIFY modificarão entradas já existentes e as mensagens do
tipo DELETE apagarão entradas na tabela de fluxo. As mensagens *_STRICT (OFPFC_MODIFY_STRICT
e OFPFC_DELETE_STRICT) buscarão entradas na tabela de fluxos idênticas às especificadas.

Além das mensagens OFPFC_DELETE e OFPFC_DELETE\_STRICT as entradas na tabela de fluxos


podem ser removidas por idle_timeout ou hard_timeout. Caso não entrem pacotes correspondentes
a uma determinada entrada na tabela em idle_timeout segundos ou caso
transcorra hard_timeout segundos após a inserção da entrada na tabela, a entrada será apagada.

Outras Versões

Nas seções acima, o OpenFlow 1.0.0 foi apresentado em maiores detalhes, considerando que o
mesmo é a versão mais utilizada e difundida. Entretanto, muitas mudanças foram realizadas desde
o lançamento da versão 1.0.0 até a versão mais atual, a 1.4. Abaixo, seguem algumas características
das versões subsequentes:

OpenFlow 1.1

Na especificação do OpenFlow 1.1, os switches OpenFlow contêm diversas tabelas de fluxos e uma
tabela de grupo, ao invés de uma única tabela de fluxos como na versão 1.0.0.

A figura 17 ilustra os componentes do switch OpenFlow 1.1. Nela podem ser vistas as diversas tabelas
de fluxos, assim como, a tabela de grupo.

Figura 17: Componentes de um switch OpenFlow 1.1


Fonte: Foundation, 2011a

Já a figura 18 ilustra como é o processamento de pacotes ao entrarem em um switch OpenFlow 1.1.

24
Figura 18: Fluxograma detalhando o fluxo de pacotes através do switch OpenFlow 1.1
Fonte: Foundation, 2011a

Logo, um fluxo de pacotes ao entrar no switch OpenFlow, poderá passar por várias tabelas de fluxos,
para que diversas ações diferentes sejam realizadas.

A tabela de grupo é um tipo especial de tabela projetada para executar ações que sejam comuns
para diversos fluxos.

Além disso, na versão 1.1.0, três novos campos de cabeçalho foram incluídos: Metadata (pode ser
usada para passar informações entre as tabelas no switch), MPLS label e MPLS traffic class.

Maiores detalhes podem ser encontrados na especificação OpenFlow 1.1.0 em (Foundation, 2011a).

OpenFlow 1.2

O OpenFlow 1.2 foi lançado em dezembro de 2011 e uma das principais implementações foi o
suporte ao protocolo IPv6, incluindo novos campos de cabeçalho nas tabelas de fluxos.

Além disso, o mesmo passou a suportar a possibilidade dos switches se conectarem a mais de um
controlador ao mesmo tempo. Ao se conectar a vários controladores, aumenta-se a segurança já que
o switch pode continuar a operar normalmente mesmo se um controlador ou a conexão ficar
indisponível (Lara et al., 2014).

Maiores detalhes em “Foundation, 2011b”.

OpenFlow 1.3

Sendo lançada em Junho de 2012, a versão 1.3.0 do OpenFlow passou a suportar o controle das taxas
de pacotes através de medidores de fluxos, introduzindo a tabela de medições Meter Table.

A tabela de medições por fluxo permite ao OpenFlow implementar simples operações de QoS, como
limitação de taxas de transmissão e pode ser combinada com as filas por porta para criar políticas de
QoS mais complexas.

25
Além disso, a versão 1.3 permite ao switch criar conexões auxiliares para o controlador, ajudando a
melhorar o desempenho de processamento do switch, explorando o paralelismo presente na maioria
dos switches (Foundation, 2012a).

OpenFlow 1.4

Na versão 1.4 do OpenFlow portas ópticas passaram a ser suportadas. Além disso, os conceitos
deEviction e Vacancy events foram introduzidos para evitar que as tabelas de fluxos fiquem cheias,
já que as mesmas tem capacidades finitas. Nas especificações anteriores quando uma tabela de
fluxos enchia, novos fluxos não eram inseridos nas tabelas e uma mensagem de erro era enviada
para o controlador. Entretanto, atingir tal situação era problemático e poderia causar interrupções
no serviço. O Evictionadiciona um mecanismo que permite ao switch apagar automaticamente as
entradas nas tabelas de fluxos que tenham menor importância. Já o Vacancy events permite ao
controlador configurar um limiar, que ao ser atingido, faz o switch enviar mensagens de alerta para
o controlador. Isso permite que o controlador possa reagir com antecedência, evitando que as
tabelas de fluxos fiquem cheias (Foundation, 2012b).

As subseções acima deram apenas uma visão global sobre as características das versões do OpenFlow
posteriores à 1.0.0. Maiores detalhes e outras características podem ser encontradas nas
especificações técnicas, citadas na bibliografia.

POX

Como visto anteriormente, o controlador é parte fundamental nas redes definidas por software, já
que serão os mesmos que irão definir a lógica de encaminhamento através das regras que irão
configurar nos switches OpenFlow. Atualmente, existem alguns disponíveis para o uso, como o NOX
(Gude et al., 2008), POX (http://www.noxrepo.org./pox/about-pox/), Maestro (Cai et al., 2010),
Trema (http://trema.gitub.io/trema/), Beacon (Erickson, 2013), entre outros como pode ser visto na
figura 19.

Figura 19: Alguns controladores OpenFlow existentes


Fonte: Nunes et al., 2014

O controlador utilizado nesse trabalho foi o POX. O mesmo é derivado do NOX clássico, um dos
primeiros controladores OpenFlow. O POX apresenta como vantagens o fato de ser implementado
em Python, sendo ideal para o ambiente acadêmico. Além disso, o mesmo apresenta diversos
componentes reusáveis e bibliotecas interessantes como as seguintes:
 openflow.discovery: Utiliza mensagens LLDP (Link Layer Discovery Protocol) para descobrir
a conectividade entre os switches com o objetivo de mapear a topologia da rede. O mesmo

26
cria eventos (os quais podem ser “escutados”) quando um link fica up ou down. Esse
componente foi essencial para a aplicação desenvolvida;
 openflow.spanning_tree: Esse componente utiliza o discovery para contruir uma visão da
topologia da rede e constrói uma spanning tree para desabilitar a inundação (flooding) nas
portas dos switches que não estão na árvore;
 pox.lib.revent: Biblioteca do POX que implementa eventos. Todos eventos do POX são
instâncias de sub-classes da classe Event;
 pox.lib.recoco: Biblioteca do POX que implementa threads e timers;
 pox.lib.addresses: Biblioteca utilizada para lidar com endereços IP e Ethernet (MAC);

Redes Definidas por SW I: Considerações finais

Este tutorial parte I procurou apresentar inicialmente os conceitos básicos de redes de


computadores para que seja possível o entendimento posterior das redes definidas por software. A
seguir tratou dos conceitos básicos sobre planos de controle e de dados e em seguida da definição
de redes definidas por software. Finalizou apresentando o padrão/protocolo OpenFlow, os switches
OpenFlow, e os principais controladores disponíveis, dando enfoque ao POX, controlador utilizado
neste estudo.

O tutorial parte II apresentará inicialmente as características do emulador de redes Mininet, utilizado


neste estudo. A seguir apresentará uma descrição detalhada da aplicação desenvolvida e os
resultados dos testes realizados, verificando como o uso da aplicação reduziu a perda de pacotes.
Serão apresentados também os códigos das aplicações implementadas por software para este
estudo. Finalmente apresentará as conclusões deste estudo.

27
Redes Definidas por SW II: Introdução

As redes de computadores nos permitem fazer coisas inimagináveis há poucas décadas.

Seu embrião teve início no final da década de 1960 com a então denominada ARPANET (Advanced
Research Projects Agency Network), que buscava interligar as bases militares e os departamentos de
pesquisa norte-americanos.

Muito evolui desde então. Modelos para protocolos de comunicação foram criados e muitos
protocolos foram desenvolvidos, sejam para suprir a demanda de aplicações, sejam para calcular os
caminhos que os pacotes devem percorrer ao longo da rede.

Devido à essa evolução de ideias, desde o início das pesquisas sobre comutação de pacotes e da
ARPANET, juntamente com a evolução do hardware utilizado, hoje temos inúmeras possibilidades
na rede. Anexar enormes quantidades de arquivos em nossos e-mails, jogar jogos com pessoas do
mundo inteiro em tempo real, ou até mesmo realizar ligações telefônicas através da Internet.

Entretanto, talvez hoje as redes estejam na iminência de uma mudança de paradigma, mudança essa
que possibilitará o desenvolvimento de aplicações cuja implementação com a tecnologia atual seria
impossível. Com a utilização de redes definidas por software (SDN - Software-Defined Networking),
será possível um total controle da rede. Não haverá mais a necessidade de hardwares especializados,
mas sim, poderá se utilizar hardwares genéricos programáveis. Novos protocolos poderão ser
testados e implementados com uma rapidez nunca antes vista e aplicações que hoje são impensáveis
se tornarão absolutamente viáveis através da implementação dessa tecnologia.

Motivação e Objetivos

Atualmente, as redes de computadores se tornaram parte essencial da infraestrutura de nossa


sociedade. Hoje, inúmeras aplicações “rodam” sobre a Internet, aplicações essas que não foram
imaginadas no projeto inicial das redes de computadores. Com o objetivo de suportar o número
crescente de aplicações e usuários, diversos “remendos” foram sendo feitos ao longo dos anos.
Entretanto, substancialmente, o núcleo da rede se manteve o mesmo. Os softwares de switches e
roteadores não podem ser reprogramados e novas ideias e protocolos não podem ser testados em
uma rede em produção, fato esse denominado por alguns autores como “ossificação” da rede
(McKeown et al., 2008). Nesse cenário, surgem as redes definidas por software.

O conceito de redes programáveis não é novo. Como exemplo, tem-se o conceito de redes ativas na
década de 1990 (Feamster et al., 2014). Entretanto, pela primeira vez, o conceito é amplamente
difundido e aceito. As redes definidas por software vêm apresentando grande aceitação por parte
da comunidade acadêmica e pelos principais fabricantes de equipamentos, que já começaram a
desenvolver soluções voltadas para esse modelo.

Diante o exposto, como objetivo geral, essa monografia pretende apresentar ao leitor esse novo
paradigma em redes de computadores, mostrando o quão importante o mesmo será para
pesquisadores que necessitam testar novos protocolos assim como para gestores que precisam
gerenciar redes de computadores todos os dias.

Para tal, os seguintes objetivos específicos devem ser atingidos:


 Apresentação dos conceitos básicos das redes de computadores atuais, fornecendo um
conhecimento mínimo para aqueles que não estejam familiarizados com redes de
computadores;
 Abordar conceitos como plano de controle e de dados, e sua separação nas redes definidas
por software;

28
 Apresentar conceitos do OpenFlow, implementação mais difundida das redes definidas por
software;
 Apresentação de uma aplicação programada em Python, para redes definidas por software.
Essa aplicação altera o caminho de um fluxo pré-estabelecido, mediante a uma alta
utilização da largura de banda do caminho principal;

Tutoriais

O tutorial parte I apresentou inicialmente os conceitos básicos de redes de computadores para que
seja possível o entendimento posterior das redes definidas por software. A seguir tratou dos
conceitos básicos sobre planos de controle e de dados e em seguida da definição de redes definidas
por software. Finalizou apresentando o padrão/protocolo OpenFlow, os switches OpenFlow, e os
principais controladores disponíveis, dando enfoque ao POX, controlador utilizado neste estudo.

Este tutorial parte II apresenta inicialmente as características do emulador de redes Mininet,


utilizado neste estudo. A seguir apresenta uma descrição detalhada da aplicação desenvolvida e os
resultados dos testes realizados, verificando como o uso da aplicação reduziu a perda de pacotes.
Serão apresentados também os códigos das aplicações implementadas por software para este
estudo. Finalmente apresenta as conclusões deste estudo.

Redes Definidas por SW II: Mininet

O ambiente utilizado para o desenvolvimento da aplicação e realização dos testes foi o Mininet. Este
se trata de um emulador de redes, desenvolvido por pesquisadores da Universidade de Stanford nos
Estados Unidos, com o objetivo de apoiar pesquisas colaborativas permitindo protótipos autônomos
de redes definidas por software, para que qualquer pessoa possa fazer o download, executar, avaliar,
explorar e ajustar (Lantz et al., 2010).

O Mininet é um emulador do tipo CBE (Container-Based Emulation) que emprega a virtualização a


nível de processo, uma forma mais leve de virtualização onde muitos recursos do sistema são
compartilhados. Compartilhando recursos como tabela de paginação, estruturas de dados
do kernel e sistema de arquivos, esse tipo de emulação alcança maior escalabilidade que outras que
realizam uma emulação completa, ou seja, usando uma máquina virtual para cada dispositivo da
rede (Heller, 2013).

Na figura 1 é apresentada uma topologia simples que servirá de base para as figuras 2 e 3. Nessas
duas últimas as diferenças citadas acima, entre CBE e a virtualização completa, podem ser
visualizadas.

Figura 1: Topologia simples com dois hosts e um switch


Fonte: Lantz e O’Connor

29
Figura 2: Virtualização completa dos dispositivos
Fonte: Lantz e O’Connor

Figura 3: Virtualização "leve" dos dispositivos


Fonte: Lantz e O’Connor

O Mininet é capaz de emular links, hosts, switches e controladores, utilizando processos que rodem
em espaços de nomes da rede (network namespaces) e pares Ethernet virtuais.
 Links: Um par Ethernet virtual atua como um cabo conectando duas interfaces virtuais.
Pacotes enviados através de uma interface são entregues na outra e cada interface se
comporta como uma interface Ethernet completa e funcional para todo o sistema e
aplicação.
 Host: É simplesmente um processo do shell movido para o seu próprio espaço de nome da
rede, ou seja, cada host apresenta uma instância da interface de rede independente. Cada
dispositivo apresenta uma ou mais interfaces virtuais e um pipe para um processo pai do
Mininet (mn), que envia comandos e monitora a saída.
 Switches: Switches OpenFlow são remotamente configurados e gerenciados pelo
controlador, podendo ser configurados para agirem como switches convencionais.
 Controladores: Controladores OpenFlow podem estar em qualquer lugar da rede, ou seja,
tanto na rede física quanto na virtual (Lantz et al., 2010).

Para controlar e gerenciar todos os dispositivos emulados, o Mininet fornece uma CLI (Command
Line Interface) conhecedora de toda a rede, ou seja, através de um único console, pode-se controlar
todos os dispositivos emulados. Outra grande vantagem desse emulador é a facilidade de criação de
topologias customizadas através de uma API (Application Programming Interface) para programação
em Python.

30
O projeto Mininet nasceu com o objetivo de facilitar os experimentos no campo de redes de
computadores, principalmente para auxiliar nas pesquisas das redes definidas por software e do
OpenFlow.

Pode ser verificado em “Heller, 2013” uma análise completa do Mininet, incluindo uma comparação
entre os tipos de plataformas para pesquisas em redes de computadores mais comuns, os
simuladores, testbeds e emuladores.

Em “Handigol et al., 2012”, pode ser verificada a robustez do Mininet ao reproduzir diversos
experimentos de redes de computadores escolhidos por estudantes.

O emulador Mininet encontra-se em constante evolução, sendo mantido por uma ativa comunidade
online. O mesmo encontra-se na versão 2.1.0 lançada em Setembro de 2013.

Redes Definidas por SW II: Aplicação Desenvolvida

Com a tecnologia de redes de computadores atual, torna-se inviável o teste de novos protocolos em
redes que estejam em produção, já que as mesmas foram implementadas com hardwares
específicos, que não permitem uma reprogramação.

Conforme visto nas seções anteriores, com as redes definidas por software, essa limitação já não
mais existirá. Equipamentos específicos se tornam genéricos e a figura do controlador aparece para
que possa existir uma rede programável e para que mudanças na forma de encaminhar os pacotes
possam ser realizadas rapidamente.

A aplicação desenvolvida busca mostrar essa facilidade presente nas redes definidas por software.

A mesma foi desenvolvida para alterar o roteamento de um fluxo pré-determinado, quando o uso
da largura de banda do caminho inicial estiver alto. Para tal, foram utilizados conceitos do algoritmo
de Dijkstra para o cálculo dos caminhos e módulos presentes no POX, como será visto adiante.

Executando a Aplicação

Ao se inicializar a aplicação, a primeira ação que é realizada é a descoberta da rede. O módulo


discovery presente no POX faz a descoberta da conectividade entre swicthes OpenFlow enviando
pacotes LLDP.

A figura 4 gerada através de uma captura no Wireshark, mostra os pacotes LLDP:

Figura 4: Pacotes LLDP

Conforme a descoberta vai sendo feita, um peso é atribuído aos enlaces. Esse peso pode ser
interpretado como o delay do link por exemplo ou qualquer outro parâmetro que signifique que
quanto maior o valor, pior é o enlace. Para a emulação realizada, se utilizou um gerador de números
aleatórios para a definição dos pesos de cada enlace.

31
Após a topologia ser salva, com a descoberta de todos os switches e a atribuição dos pesos, o
algoritmo de Dijkstra é, então, executado em um código complementar.

Esse código complementar, apresentado na seção Códigos Implementados deste tutorial parte II,
utiliza conceitos do algoritmo de Dijkstra para realizar o cálculo da melhor e da segunda melhor rotas
entre os switches OpenFlow. O código recebe como parâmetros o nó origem e a topologia e retorna
duas listas, uma contendo o menor custo e a outra contendo o segundo menor custo para se chegar
aos outros nós.

A figura 5 apresenta um fluxograma representando essa primeira etapa:

Figura 5: Fluxograma representando primeira etapa da execução da aplicação

Como pode ser visto no fluxograma acima, toda vez que ocorrer um evento de link, ou seja, quando
um link for descoberto ou quando um link ficar down, a topologia será alterada e o código do
algoritmo de Dijkstra será executado.

Ao receber um pacote, o switch enviará uma mensagem de Packet-In para o controlador, se o switch
não possuir entradas em sua tabela de fluxos. A aplicação no controlador tratará de maneiras
diferentes pacotes ARP (Address Resolution Protocol) e os demais.

Se o pacote for um ARP (seja Request ou Reply) o controlador irá gerar um pacote de Packet-Out, ou
seja, o controlador informa ao switch apenas qual deve ser a ação a ser tomada para um pacote, não
havendo modificação da tabela de fluxos do switch. A figura 6 mostra os Packet-In gerados pelos
switches, com a resposta Packet-Out do controlador:

Figura 6: Pacotes ARP e resposta do controlador

Caso o pacote não seja ARP, o controlador gera uma mensagem de Flow-Mod que irá inserir uma
entrada na tabela de fluxos do switch, como pode ser visto na figura 7.

Figura 7: Resposta do controlador para outros pacotes

Segue na figura 8 o fluxograma dos passos citados acima.

32
Figura 8: Fluxograma representando o evento de Packet-In

Para cada par de switches origem e destino, a aplicação monitora a taxa de transmissão, fazendo
requisições periódicas de estatísticas do uso da interface. A quantidade de bytes transmitidos pela
porta conectada ao próximo switch (próximo switch de acordo com o melhor caminho calculado) é
salva em uma variável e será comparada com a quantidade da coleta anterior.

Como na topologia definida para o teste (Código para a Criação da Topologia apresentado na
seção Códigos Implementados deste tutorial parte II) os links foram definidos com uma largura de
banda de 100 Mbps, é feito um cálculo com a diferença de bytes transmitidos em duas coletas e
verifica-se se a quantidade de bits transmitidos por segundo é menor que um determinado limiar.
Esse limiar foi determinado nos testes como 70 Mbps. Caso seja, todos os fluxos destinados ao
mesmo IP de destino passam pelo melhor caminho. Caso a quantidade de bits por segundo seja
maior que 70 Mpbs, os fluxos que apresentem porta UDP igual a 2000 são chaveados para a segunda
melhor rota.

Figura 9: Fluxograma do teste de links e chaveamento entre caminhos

Como pode ser visto no fluxograma da figura 9 com o objetivo de evitar que fiquem ocorrendo
mudanças de rotas a todo momento, foi implementada uma histerese. Assim, existe um contador
que salva o número de ocorrências do evento. Para mudar para o segundo caminho, o mesmo deve

33
ser maior ou igual a 2 (10 segundos). Para que o fluxo volte para o melhor caminho, o uso da banda
do melhor caminho deve ficar abaixo de 70Mbps por no mínimo o tempo que ficou acima desse
limiar. Vale ressaltar que o valor máximo desse contador é 5 (25 segundos).

O incremento desse contador, assim como outros detalhes menores, não foi indicado no fluxograma.
Em um primeiro momento, optou-se pela captura da quantidade de pacotes descartados pela
interface. Quando o mesmo chegasse a um limiar estabelecido, ocorreria o chaveamento do fluxo
para o segundo melhor caminho. Entretanto mesmo após estressar o link, o contador dos pacotes
descartados não foi incrementado. Acreditando ser uma limitação do Mininet, optou-se então pela
análise da utilização da largura de banda.

A aplicação mostra como o controlador pode agir proativamente com o objetivo de evitar sobrecarga
do link e descartes ou até mesmo para a implementação de políticas de QoS de forma facilitada. Vale
ressaltar, que a escolha da porta UDP 2000 foi feita de forma aleatória e, com facilidade, o código
pode ser generalizado para quaisquer portas ou até mesmo para que altere a rota levando em
consideração quaisquer outros campos de cabeçalho definidos na seção Tabela de Fluxos do tutorial
parte I.

O código completo desenvolvido pode ser analisado na seção Códigos Implementados deste tutorial
parte II.

Redes Definidas por SW II: Simulação e resultados

Para a realização dos testes, foi utilizada uma topologia redundante, conforme define o Código para
a Criação da Topologia apresentado na seção Códigos Implementados deste tutorial parte II.

Como a proposta dessa monografia é apresentar as redes definidas por software, mostrando a
facilidade com que aplicações podem ser desenvolvidas, uma topologia simples foi escolhida para a
realização dos testes.

Nela, foram configurados três hosts e cinco switches. Todos os enlaces foram definidos com as
mesmas características, com o objetivo de facilitar os testes e a análise dos resultados.

As principais características são:


 bw - Largura de banda de 100Mbps;
 loss - Perda do link de 1%;
 delay - Atraso de 5ms;
 max_queue_size - Tamanho máximo da fila de 10000 pacotes;

A figura 10 ilustra a topologia utilizada.

34
Figura 10: Topologia utilizada nos testes

Primeiramente, o Mininet é inicializado com a topologia personalizada criada e com alguns


parâmetros extras, para que os endereços MAC fiquem de forma mais legível e definindo que o
controlador será externo, como pode ser visto na figura 11.

Figura 11: Inicialização do Mininet

Após a inicialização do emulador Mininet, a aplicação é inicializada.

Como pode ser visto na figura 12 a aplicação é iniciada com os módulos já citados do POX, discovery
e spanning_tree (seção POX do tutorial parte I), já que por padrão o spanning_tree não é ativado.

Figura 12: Inicialização da aplicação

Para gerar o tráfego para os testes, foi utilizado o Iperf (iper.fr).

Com o Iperf, é possível configurar um host para atuar como servidor, “escutando” em uma
determinada porta e hosts como clientes, que irão enviar tráfegos para o servidor.

Metodologia

Na topologia configurada, o host 3 foi definido como o servidor, e os hosts 1 e 2 como clientes.

Logo, os hosts 1 e 2 gerarão tráfegos para o host 3. Definiu-se que os pacotes enviados pelo host 1
seriam pacotes UDP com a porta de destino 1000. Já o host 2 envia pacotes UDP, usando como porta
de destino a 2000. Além disso, ambas comunicações tentarão utilizar 100% da largura de banda e
ambos os fluxos são gerados por 180 segundos, ao mesmo tempo, como pode ser visto nas figuras
13 e 14.

35
Figura 13: Comandos do Iperf nos clientes

Figura 14: Comandos do Iperf no servidor

Primeiramente, foram realizados os testes com os dois hosts clientes enviando fluxos por caminhos
diferentes, ou seja, o primeiro host enviando pelo melhor caminho e o segundo host enviando pelo
segundo melhor caminho. O objetivo desse procedimento é conhecer os erros intrínsecos de cada
caminho, para que se tenha uma base de comparação para os próximos procedimentos.

Cada um dos procedimentos foi repetido seis vezes, sendo cada um deles executados após a
inicialização do Mininet e do controlador.

A figura 15 apresenta o gráfico do percentual de pacotes perdidos.

Figura 15: Perda de pacotes com fluxos enviados sempre por caminhos diferentes

36
O fluxo 1, é o fluxo enviado pelo host 1 e o fluxo 2, é o enviado pelo host 2.

A figura 16 apresenta a resposta do servidor, após o primeiro teste.

Figura 16: Teste com dois hosts enviando por caminhos diferentes

Em seguida, foram realizados os testes com ambos os fluxos sendo enviados pelo melhor caminho.
O objetivo é verificar qual é a porcentagem dos pacotes perdidos, sem utilizar o chaveamento para
o segundo melhor caminho.

O gráfico com o percentual de perda dos pacotes, nos seis testes realizados, é apresentado na figura
17.

Figura 17: Perda de pacotes com ambos os fluxos enviados sempre pelo melhor caminho

Na figura 18 segue resposta do servidor após o primeiro teste.

Figura 18: Teste com dois hosts enviando pelo mesmo caminho

Por fim, realiza-se o teste com o chaveamento dinâmico ativado. A configuração do caminho
alternativo é efetuada caso a utilização da largura de banda fique acima de 70Mbps. O resultado
pode ser visto na figura 19.

37
Figura 19: Perda dos pacotes realizando a mudança de rota dinamicamente

A figura 20 apresenta a resposta do servidor após o primeiro teste.

Figura 20: Resultado do primeiro teste

Na figura 21 segue a tabela de fluxos do switch 1, mostrando a modificação da interface de saída


para os fluxos que tenham porta UDP igual a 2000.

Figura 21: Tabela de fluxos do switch 1

Os gráficos dos percentuais médios de cada procedimento são apresentados na figura 22.

38
Figura 22: Percentual médio dos erros

Já o gráfico com as taxas médias de transmissão dos fluxos é apresentado na figura 23.

Figura 23: Taxa de transmissão média

Como pode ser verificado, o uso da aplicação reduziu consideravelmente as perdas de pacotes de
todos os fluxos, chegando a valores próximos ao experimento dos fluxos sempre por caminhos
diferentes. Para os testes em questão, que foram realizados por um período de 180 segundos, a
redução de 1% na perda dos pacotes, equivale a um ganho na recepção de aproximadamente 8000
pacotes!

Considerando que a redução da perda foi de aproximadamente 5%, fica bastante clara a melhoria na
entrega dos pacotes.

39
Redes Definidas por SW II: Códigos Implementados

As seções a seguir apresentam os códigos das aplicações implementadas, usando a linguagem


Python.

Código para Criação da Topologia

#Topologia - 5 switches - 3 hosts

from mininet.topo import Topo

class MyTopo( Topo ):

def __init__( self ):

Topo.__init__( self )

h1 = self.addHost( 'h1' )
h2 = self.addHost( 'h2' )
h3 = self.addHost( 'h3' )

s1 = self.addSwitch( 's1' )
s2 = self.addSwitch( 's2' )
s3 = self.addSwitch( 's3' )
s4 = self.addSwitch( 's4' )
s5 = self.addSwitch( 's5' )

#Adicionando links

self.addLink( h1, s1, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )


self.addLink( h2, s1, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )
self.addLink( h3, s5, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )

self.addLink( s1, s2, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )


self.addLink( s1, s3, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )
self.addLink( s1, s4, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )

self.addLink( s2, s5, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )


self.addLink( s3, s5, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )
self.addLink( s4, s5, bw=100,delay='5ms',loss=1,max_queue_size=10000,use_htb=True )

topos = { 'mytopo': ( lambda: MyTopo() ) }

Código para o Cálculo das Rotas

# Executa algoritmo de Dijakstra, calculando o melhor e o segundo melhor caminho;

def recebe_dados (no_origem, topologia):


distancias = {}
distancias_segundo = {}
vizinhos = {}
vizinhos_segundo = {}
num_nos, nos = calcula_num_nos(topologia)

40
nos_segundo = nos[:]

for no in nos:
vizinhos[no] = []
for i in topologia:
if (no == i[0]):
vizinhos[no].append([i[2], i[1]])
if (no == i[2]):
vizinhos[no].append([i[0], i[1]])
if (no != no_origem ):
distancias[no] =[-1,-1, 0]

for no_segundo in nos_segundo:


vizinhos_segundo[no_segundo] = []
for i in topologia:
if (no_segundo == i[0]):
vizinhos_segundo[no_segundo].append([i[2], i[1]])
if (no_segundo == i[2]):
vizinhos_segundo[no_segundo].append([i[0], i[1]])
if (no_segundo != no_origem ):
distancias_segundo[no_segundo] =[-1,-1, 0]

for j in vizinhos[no_origem]:
distancias[j[0]] = j
distancias[j[0]].append(0)

for l in vizinhos_segundo[no_origem]:
distancias_segundo[l[0]] = l
distancias_segundo[l[0]].append(0)

visitado = 0

while visitado == 0:
peso_minimo = -1
no_custo_minimo = None
visitado = 1
for j in distancias:
if (distancias[j][2] == 0):
if (distancias[j][1] != -1):
if ((peso_minimo == -1) or (peso_minimo > distancias[j][1])):
peso_minimo = distancias[j][1]
no_custo_minimo = j
visitado = 0

if visitado == 0:
for vizinho in vizinhos[no_custo_minimo]:
if vizinho[0] != no_origem:
if (distancias[no_custo_minimo][1] + vizinho[1] <= distancias[vizinho[0]][1]) or
(distancias[vizinho[0]][1] == -1):
distancias[vizinho[0]][0] = distancias[no_custo_minimo][0]
distancias[vizinho[0]][1] = distancias[no_custo_minimo][1] + vizinho[1]
distancias[no_custo_minimo][2] = 1

visitado_segundo = 0

41
while visitado_segundo == 0:
peso_minimo_segundo = -1
no_custo_minimo_segundo = None
visitado_segundo = 1

for j in distancias_segundo:
if (distancias_segundo[j][2] == 0):
if (distancias_segundo[j][1] != -1):
if ((peso_minimo_segundo == -1) or (peso_minimo_segundo >
distancias_segundo[j][1])):
peso_minimo_segundo = distancias_segundo[j][1]
no_custo_minimo_segundo = j
visitado_segundo = 0

if visitado_segundo == 0:
for vizinho in vizinhos_segundo[no_custo_minimo_segundo]:
if vizinho[0] != no_origem:
soma_distancias = distancias_segundo[no_custo_minimo_segundo][1] + vizinho[1]
if ((soma_distancias < distancias_segundo[vizinho[0]][1]) or
(distancias_segundo[vizinho[0]][1] == -1)):
if ((soma_distancias > distancias[vizinho[0]][1] or
distancias_segundo[no_custo_minimo_segundo][0] !=
distancias[no_custo_minimo_segundo][0])):
distancias_segundo[vizinho[0]][0] =
distancias_segundo[no_custo_minimo_segundo][0]
distancias_segundo[vizinho[0]][1] = soma_distancias

if ((distancias_segundo[vizinho[0]][0] == distancias[vizinho[0]][0]) and


(distancias_segundo[vizinho[0]][1] == distancias[vizinho[0]][1])):
if (distancias[no_custo_minimo_segundo][0] !=
distancias_segundo[vizinho[0]][0]):
distancias_segundo[vizinho[0]][0] = no_custo_minimo_segundo
distancias_segundo[vizinho[0]][1] =
distancias[no_custo_minimo_segundo][1] + vizinho[1]

else:
distancias_segundo[vizinho[0]][0] = no_custo_minimo_segundo
distancias_segundo[vizinho[0]][1] =
distancias_segundo[no_custo_minimo_segundo][1] + vizinho[1]

distancias_segundo[no_custo_minimo_segundo][2] = 1

#For necessario devido ao problema quando um no so tinha um unico vizinho e nao era visitado
para calcular o segundo melhor caminhos.
#Try necessario pois como o Djakstra e chamado antes de toda a topologia estar criada, ele dava
exception. Caso o codigo seja chamado apenas apos a criacao de toda a topologia, a excecao nao
aparecera mais.

try:
for chaves in vizinhos_segundo.keys():
if vizinhos_segundo[chaves][0] != no_origem:
if len(vizinhos_segundo[chaves]) == 1 and distancias_segundo[chaves][0] == -1:

42
distancias_segundo[chaves][1] =
distancias_segundo[vizinhos_segundo[chaves][0][0]][1] +
vizinhos_segundo[chaves][0][1]
distancias_segundo[chaves][0] =
distancias_segundo[vizinhos_segundo[chaves][0][0]][0]
distancias_segundo[chaves][2] = 1
except Exception:
pass
return distancias, distancias_segundo

#Calcula quantos nos ha na topologia;


def calcula_num_nos (top):
Conj_nos = set()
for i in top:
Conj_nos.add(i[0])
Conj_nos.add(i[2])

Lista_nos = list(Conj_nos)
Num_nos = len (Lista_nos)
return Num_nos, Lista_nos

Código da Aplicação

from pox.core import core


from pox.lib.revent import *
import pox.openflow.libopenflow_01 as of
import pox.openflow.discovery
import pox.openflow.spanning_tree
from random import randrange
import djakstra_v2
from time import sleep
from pox.lib.addresses import IPAddr
from pox.lib.recoco import Timer

from pox.openflow.of_json import *

log=core.getLogger()

class switch_multi(object):
mac_map={}
delay_links={}

def __init__(self):
def startup():
core.openflow.addListeners(self, priority=0)
core.openflow_discovery.addListeners(self)

#Listener para eventos estatisticos


core.openflow.addListenerByName("FlowStatsReceived", self.handle_flow_stats)
core.openflow.addListenerByName("PortStatsReceived", self.handle_portstats_received)

self.connections = set()

core.call_when_ready(startup,('openflow','openflow_discovery'))

43
#Dicionario chave - IP; valores - MAC origem e porta do switch
self.mac_map = {}
self.topologia = []
self.delay_links = {}
self.portas = {}
self.dij_1_melhor = []
self.dij_2_melhor = []
self.dij_1_segundo = []
self.dij_2_segundo = []

#Contador que sera utilizado para executar o Djakstra. Sem o mesmo, o algoritmo de Djakstra
e executado, sem os links terem sido descobertos.
self.count = 0
self.link_count = 0

self.tx_1 = 0
self.tx_2 = 0
self.diferenca = 0

self.LINK_OK = True
self.JA_ENTROU = False

def _handle_LinkEvent(self,event):
chave_1 = str(event.link.dpid1)+str(event.link.dpid2)
chave_2 = str(event.link.dpid2)+str(event.link.dpid1)
delay_1 = self.delay_links.get(chave_1)
delay_2 = self.delay_links.get(chave_2)
if (delay_1 == None and delay_2 == None):
delay = None
chave = chave_1
elif delay_1 != None:
delay = delay_1
chave = chave_1
else:
delay = delay_2
chave = chave_2

if event.added == True:
#Dicionario das conexoes. Retorna o numero da porta de cada conexao
if not chave_1 in self.portas.keys():
self.portas.update({chave_1:event.link.port1})
self.portas.update({chave_2:event.link.port2})
if not (([event.link.dpid1,delay,event.link.dpid2] in self.topologia) or
([event.link.dpid2,delay,event.link.dpid1] in self.topologia)):
if delay == None:
self.delay_links.update({chave:randrange(5,80,5)})
self.topologia.append([event.link.dpid1,self.delay_links.get(chave),event.link.dpid2])
if event.removed == True:
if chave_1 in self.portas.keys():
self.portas.remove({chave_1:event.link.port1})
self.portas.remove({chave_2:event.link.port2})
if ([event.link.dpid1,delay,event.link.dpid2] in self.topologia):
self.topologia.remove([event.link.dpid1,delay,event.link.dpid2])

44
if ([event.link.dpid2,delay,event.link.dpid1] in self.topologia):
self.topologia.remove([event.link.dpid2,delay,event.link.dpid1])

print 'topologia ---- ', self.topologia

self.count = self.count + 1

# PARA TOPOLOGIA COM 6 ENLACES, O CONTADOR CHEGA A 12.


if self.count >= 12:
self.dij_1_melhor, self.dij_1_segundo = djakstra_v2.recebe_dados(1,self.topologia)
self.dij_2_melhor, self.dij_2_segundo = djakstra_v2.recebe_dados(2,self.topologia)
self.dij_3_melhor, self.dij_3_segundo = djakstra_v2.recebe_dados(3,self.topologia)
self.dij_4_melhor, self.dij_4_segundo = djakstra_v2.recebe_dados(4,self.topologia)
self.dij_5_melhor, self.dij_5_segundo = djakstra_v2.recebe_dados(5,self.topologia)
Timer(5,self._timer_func, recurring=True)
Timer(5,self.link_test, recurring=True)

def _handle_ConnectionUp (self, event):


#print "Entrou ConnectionUP"
#print "CONECTION --- ", event.connection
self.connections.add(event.connection)

def handle_flow_stats (self, event):


flow_stats = flow_stats_to_list(event.stats)

def handle_portstats_received(self, event):


segundo_switch = self.dij_1_melhor[5][0]
chave = str("1") + str(segundo_switch)

for i in event.stats:
print "CHAVE -------", chave
if i.port_no == self.portas.get(chave):
self.tx_1 = i.tx_bytes
if (self.tx_2 != 0):
self.diferenca = ((self.tx_1 - self.tx_2)*8)/5
self.tx_2 = i.tx_bytes

stats = flow_stats_to_list(event.stats)

def _timer_func(self):
print "-------- Entrou timer_func -------- "
core.openflow.getConnection(1).send(of.ofp_stats_request(body=of.ofp_flow_stats_reques
t()))
core.openflow.getConnection(1).send(of.ofp_stats_request(body=of.ofp_port_stats_request
()))

def link_test(self):
#A cada 5 segundos havera verificacao do link. O self.LINK_OK comeca como True. Se a
diferenca apos 10 segundos ficar acima de 70000000
if (self.diferenca > 0 and self.diferenca < 70000000):
if self.link_count > 0:
self.link_count = self.link_count -1
else:
self.LINK_OK = True

45
else:
if self.link_count < 5:
self.link_count = self.link_count + 1
if self.link_count >= 2:
self.LINK_OK = False

if self.JA_ENTROU == False:
msg = of.ofp_flow_mod()
msg.match.dl_type = 0x800
msg.match.nw_proto = 17
msg.match.nw_dst = IPAddr("10.0.0.3")
msg.match.tp_dst = 2000
msg.idle_timeout = 10
msg.hard_timeout = 60
prox_salto2 = self.dij_1_segundo[5][0]
chave2 = str(1)+str(prox_salto2)
porta_saida2 = self.portas.get(chave2)
msg.actions.append(of.ofp_action_output(port = porta_saida2))
core.openflow.getConnection(1).send(msg)

def _handle_PacketIn(self,event):

packet = event.parsed

if packet.type == packet.ARP_TYPE:
IP_ORIGEM = str(packet.payload.protosrc)
IP_DESTINO = str(packet.payload.protodst)

else:
IP_ORIGEM = str(packet.payload.srcip)
IP_DESTINO = str(packet.payload.dstip)
PORTA_ORIGEM = None
PORTA_DESTINO = None

if packet.payload.protocol == packet.payload.TCP_PROTOCOL or packet.payload.protocol


== packet.payload.UDP_PROTOCOL:
PORTA_ORIGEM = packet.payload.payload.srcport
PORTA_DESTINO = packet.payload.payload.dstport
print "PORTA ORIGEM -------", PORTA_ORIGEM
print "PORTA DESTINO ---------", PORTA_DESTINO

if IP_DESTINO == "10.0.0.3":
#COMO EM PYTHON NAO EXISTE SWITCH CASE:
if event.dpid == 1:
prox_salto = self.dij_1_melhor[5][0]
chave = str(1)+str(prox_salto)
porta_saida = self.portas.get(chave)
elif event.dpid == 2:
prox_salto = self.dij_2_melhor[5][0]
chave = str(2)+str(prox_salto)
porta_saida = self.portas.get(chave)
elif event.dpid == 3:
prox_salto = self.dij_3_melhor[5][0]
chave = str(3)+str(prox_salto)

46
porta_saida = self.portas.get(chave)
elif event.dpid == 4:
prox_salto = self.dij_4_melhor[5][0]
chave = str(4)+str(prox_salto)
porta_saida = self.portas.get(chave)

#ARP
if packet.type == packet.ARP_TYPE:
msg = of.ofp_packet_out()
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 5:
msg.actions.append(of.ofp_action_output(port = 1))
else:
msg.actions.append(of.ofp_action_output(port = porta_saida))
event.connection.send(msg)

else:
if self.LINK_OK:
msg = of.ofp_flow_mod()
msg.match.dl_type = 0x800
msg.match.nw_proto = 17
msg.match.nw_dst = IPAddr("10.0.0.3")
msg.match.tp_dst = PORTA_DESTINO
msg.idle_timeout = 10
msg.hard_timeout = 60
msg.data = event.ofp
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 5:
msg.actions.append(of.ofp_action_output(port = 1))
else:
msg.actions.append(of.ofp_action_output(port = porta_saida))
event.connection.send(msg)

else:
msg = of.ofp_flow_mod()
msg.match.dl_type = 0x800
msg.match.nw_proto = 17
msg.match.nw_dst = IPAddr("10.0.0.3")
msg.match.tp_dst = PORTA_DESTINO
msg.idle_timeout = 10
msg.hard_timeout = 60
msg.data = event.ofp
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 5:
msg.actions.append(of.ofp_action_output(port = 1))
else:
if PORTA_DESTINO != 2000:
msg.actions.append(of.ofp_action_output(port = porta_saida))

else:
if event.dpid == 1:
prox_salto2 = self.dij_1_segundo[5][0]
chave2 = str(1)+str(prox_salto2)
porta_saida2 = self.portas.get(chave2)

47
elif event.dpid == 2:
chave2 = str(2)+str(5)
porta_saida2 = self.portas.get(chave2)
elif event.dpid == 3:
chave2 = str(3)+str(5)
porta_saida2 = self.portas.get(chave2)
elif event.dpid == 4:
chave2 = str(4)+str(5)
porta_saida2 = self.portas.get(chave2)
msg.actions.append(of.ofp_action_output(port = porta_saida2))

event.connection.send(msg)

elif (IP_DESTINO == "10.0.0.1" or IP_DESTINO == "10.0.0.2"):


if IP_DESTINO == "10.0.0.1":
porta = 1
elif IP_DESTINO == "10.0.0.2":
porta = 2

#COMO EM PYTHON NAO EXISTE SWITCH CASE:


if event.dpid == 2:
prox_salto = self.dij_2_melhor[1][0]
chave = str(2)+str(prox_salto)
porta_saida = self.portas.get(chave)
elif event.dpid == 3:
prox_salto = self.dij_3_melhor[1][0]
chave = str(3)+str(prox_salto)
porta_saida = self.portas.get(chave)
elif event.dpid == 4:
prox_salto = self.dij_4_melhor[1][0]
chave = str(4)+str(prox_salto)
porta_saida = self.portas.get(chave)
elif event.dpid == 5:
prox_salto = self.dij_5_melhor[1][0]
chave = str(5)+str(prox_salto)
porta_saida = self.portas.get(chave)

#ARP
if packet.type == packet.ARP_TYPE:
msg = of.ofp_packet_out()
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 1:
msg.actions.append(of.ofp_action_output(port = porta))
else:
msg.actions.append(of.ofp_action_output(port = porta_saida))
event.connection.send(msg)

else:
if self.LINK_OK:
msg = of.ofp_flow_mod()
msg.match.dl_type = 0x800
msg.match.nw_dst = IPAddr(IP_DESTINO)
msg.idle_timeout = 10
msg.hard_timeout = 30

48
msg.data = event.ofp
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 1:
msg.actions.append(of.ofp_action_output(port = porta))
else:
msg.actions.append(of.ofp_action_output(port = porta_saida))

event.connection.send(msg)

else:
msg = of.ofp_flow_mod()
msg.match.dl_type = 0x800
msg.match.nw_dst = IPAddr(IP_DESTINO)
msg.match.nw_proto = 17
msg.match.tp_src = PORTA_ORIGEM
msg.idle_timeout = 10
msg.hard_timeout = 30
msg.data = event.ofp
msg.buffer_id = event.ofp.buffer_id
if event.dpid == 1:
msg.actions.append(of.ofp_action_output(port = porta))

else:
if (PORTA_ORIGEM != 2000):
msg.actions.append(of.ofp_action_output(port = porta_saida))

else:
if event.dpid == 2:
chave2 = str(2)+str(1)
porta_saida2 = self.portas.get(chave2)
elif event.dpid == 3:
chave2 = str(3)+str(1)
porta_saida2 = self.portas.get(chave2)
elif event.dpid == 4:
chave2 = str(4)+str(1)
porta_saida2 = self.portas.get(chave2)
elif event.dpid == 5:
prox_salto2 = self.dij_5_segundo[1][0]
chave2 = str(5)+str(prox_salto2)
porta_saida2 = self.portas.get(chave2)

msg.actions.append(of.ofp_action_output(port = porta_saida2))

event.connection.send(msg)

def launch():
core.registerNew(switch_multi)

49
Redes Definidas por SW II: Considerações finais

Esse trabalho teve como objetivo introduzir um paradigma diferente da atual implementação de
redes de computadores, modelo esse que pode vir a ser o predominante em poucos anos.

Buscando ajudar na compreensão das redes definidas por software, na seção Conceitos de Redes de
Computadores os conceitos básicos dessas redes de computadores foram explanados. Conceitos
como modelo em camadas, encaminhamento, roteamento e classificação de pacotes, serviram como
uma base para os conceitos seguintes.

A seção Conceitos Fundamentais de SDN apresentou as redes definidas por software, modelo que
propõe a separação dos planos de controle e dados, planos esses encontrados nos dispositivos de
redes como switches e roteadores. Com sua separação, é possível ter um controle total da rede. Já
não são mais necessários hardwares específicos, mas hardwares genéricos podem ser utilizados e,
através do controlador, podem ser programados.

A seção OpenFlow apresentou a implementação mais difundida das redes definidas por software.
Um enfoque maior é dado a versão 1.0.0, a versão mais utilizada do OpenFlow. Entretanto, as
diferenças entre as versões mais novas como as versões 1.1, 1.2, 1.3 e 1.4 são citadas. Nesta seção é
apresentado também o POX, controlador implementado em Python e que foi utilizado nesse
trabalho.

A seção Mininet apresenta esse emulador de redes desenvolvido na universidade de Stanford, cuja
principal vantagem é o fato de empregar uma forma mais leve de virtualização, onde muitos recursos
do sistema são compartilhados.

Nas seções seguintes, a aplicação foi finalmente descrita e seus resultados mostrados.

Como foi visto, uma topologia simples com cinco switches e três hosts foi utilizada. Fluxos são
gerados por dois hosts clientes para o servidor e de acordo com a utilização da largura de banda, o
caminho de um desses fluxos pode ser alterado.

Como visto, foram realizados três procedimentos. No primeiro, foram realizadas uma série de testes
com o objetivo de descobrir a perda intrínseca dos caminhos. Ao fazer isso, encontra-se uma base,
com a qual poderão ser comparados os resultados dos próximos procedimentos.

No segundo procedimento, testes são realizados com os dois fluxos sendo enviados pelo mesmo
caminho. O objetivo é verificar a quantidade de pacotes que estão sendo perdidos devido à utilização
do mesmo link.

No terceiro procedimento, os testes realizados utilizam a aplicação para realizar o chaveamento de


um fluxo específico (no caso, o fluxo cuja porta UDP de destino seja 2000). O mesmo passa a utilizar
o segundo melhor caminho calculado pelo algoritmo de Dijkstra, caso a utilização do link principal
seja maior ou igual a 70Mbps.

No final da seção, um gráfico comparativo dos três procedimentos é apresentado. Nele, percebe-se
que a utilização do algoritmo que realiza a troca de rotas dinamicamente reduziu em torne de 5% a
perda de pacotes.

Logo, a prova de conceito foi realizada com sucesso. Os resultados ficaram dentro do esperado e da
proposta inicial. Ainda, o código da aplicação futuramente pode ser modificado, buscando deixá-lo
mais genérico ou adequando-o a outra situação específica.

50

You might also like