Universidade Federal do Rio de Janeiro
Bacharelado em Ciência da Computação
Teleprocessamento e Redes
Prof.: Silvana
Implementação das funções da
camada de enlace
__________________________________________________________________________
Grupo:
Diego Felix
DRE: 104019581
Marco Reina
DRE: 105091358
Pedro Henrique
DRE: 105035988
1. Introdução
Este trabalho consiste em implementar as funções da camada de enlace da
arquitetura de rede utilizando a API de sockets. Essas funções serão utilizadas pela
camada de rede para receber e enviar quadros de dados.
Este simulador não vai implementar as funcionalidades de entrega confiável e
controle de fluxo da camada de enlace.
2. Visão geral da camada de enlace
A camada de enlace possui as seguintes características:
•
Trata o envio, seja por canal broadcast ou por canal ponto-a-ponto, de
pacotes(chamados quadros) entre enlaces individuais.
•
•
Define as ações tomadas pelos terminais ao enviar ou receber quadros.
Controla o acesso ao meio, especificando regras para transmissão de
quadros em enlaces broadcast.
•
•
•
Provê empacotamento do datagrama de rede antes da transmissão.
Detecção de erros.
Transmissão full-duplex.
3. Projeto da camada de enlace
•
Descrição das estruturas de dados:
◦
T_D_QUADRO: Tamanho do espaço reservado para os dados em
um quadro;
◦
T_H_QUADRO: Tamanho do espaço reservado para o cabeçalho de
um quadro;
◦
MAX_HOSTS: Número máximo de hosts que podem ser plugados no
comutador;
◦
◦
unsigned char macLocal: Endereço MAC da máquina local.
Enlace en: Estrutura de dados da camada de enlace, possui os
buffers de envio e recebimento do comutador de enlace, flags para
determinar quadros prontos para envio e recebimento, e a Tabela do
comutador;
▪
TabelaComutador tc[MAX_HOSTS]: Tabela do comutador de
enlace, em cada linha possui o mac do host, seu endereco
para conexao e um flag de preenchimento. Se o flag estiver
com 0, o host se "plugou" ao comutador, mas ele ainda não
possui entrada em sua tabela de controle, se estiver com 1, a
tabela do comutador possui uma entrada com o MAC desse
host.
◦
int portaComutador: Porta utilizada para a comunicação com o
comutador;
◦
struct sockaddr_in addrComut: Estrutura para conexão com o
comutador;
◦
•
double taxaPerda: Taxa de perda de quadros;
Descrição das funções oferecidas:
◦
int L_Activate_Request(unsigned char, int, char *, int): Efetua as
inicializações do nível de enlace, recebe como parâmetros o MAC
local, porta do comutador e ip do comutador. O último parâmetro
indica se é a inicialização de um host ou de um comutador;
◦
void L_Data_Request(unsigned char, char, int): solicita a transmissão
de um quadro, recebe como parâmetro o MAC de destino e os dados
que vao ser enviados.
◦
int L_Data_Indication(): Testa se há um quadro recebido no nível de
enlace;
◦
int L_Data_Receive(unsigned char, char, int): Busca no nível de
enlace os dados do último quadro recebido, recebe o MAC do host
que enviou o quadro e os seus dados;
◦
void L_MainLoop(): Executa um ciclo básico de execução da camada
de enlace, para tratar envio e recebimento de bytes e a manipulação
da tabela do comutador;
◦
void L_Set_Loss_Probability(double): Configura a taxa de perda de
quadros da camada de enlace, recebe a probabilidade da perda de
um quadro;
◦
void L_Deactivate_Request(): Finaliza o funcionamento dos níveis de
enlace e físico, no caso do host, ele envia um sinal ao comutador
para se "desplugar" dele. No caso do comutador, ele envia um sinal
para todos os hosts serem desligados dele;
◦
void l_Recebe_Byte(): Recebe um byte e armazena no buffer da
camada de enlace, quando o último byte de um quadro é recebido
ele é validado.
◦
void l_Valida_Quadro(): Valida o quadro recebido, verificando se ele
foi destinado ao seu MAC ou broadcast, e faz a checagem de erro do
quadro;
◦
void l_Transmite_Byte(): Transmite um byte do quadro e checa se
terminou a transmissão do quadro.;
4. Implementaçao (emulação) da camada de enlace
•
Estratégias de implementação adotadas:
◦
Criar um estrutura com todos os dados do comutador da camada de
enlace (buffers, flags, tabela, etc.).
◦
Criar apenas uma Tabela para o comutador, onde um flag sinaliza se
o MAC do host esta na tabela logica ou nao.
◦
Utilizar a estrutura sockaddr_in para fazer a comunicação com os
hosts, estrutura esta que é retornada pela função rcvfrom, e é
inserida na tabela do comutador, para este fazer a comunicação com
seus hosts.
◦
Reservar endereços MAC especiais para fazer envios de quadro de
controle (MAC 1 simboliza o comutador, 2 pedido de conexão, 3
pedido de desconexão/desligamento, etc).
◦
Utilizar um array de tamanho fixo de unsigned chars para representar
um quadro, onde os caracteres representados por 0 simbolizam inicio
e fim de um quadro.
◦
Utilização dos controles da biblioteca <termios.h> para poder realizar
a leitura de dados do teclado de forma não-bloqueante.
•
Estrutura do programa de teste e resultados obtidos:
◦
O programa de teste pode ser inicializado tanto como um host a se
conectar ou um comutador, o primeiro passo do programa é
perguntar se vai ser inicializado um host ou um comutador.
◦
Se o programa for um comutador, ele pergunta qual porta será
utilizada para a comunicação, inicializa o nivel de enlace e executa o
loop de execução do comutador (transmissão de quadros e
manipulação da tabela).
◦
Se o programa for um host, ele pergunta o ip do comutador q ele
quer se comunicar, porta para comunicação e o MAC do host. Então
ele vai poder enviar e receber quadros para hosts conectados a este
comutador.
◦
Para cada mudança na tabela do comutador, ele imprime na saída a
sua situação atual.
◦
O comutador ou o host imprimem na tela uma mensagem de erro
quando a validação do quadro recebido falhar.
◦
O host ao receber um quadro efetivamente, imprime o MAC que
enviou o quadro e o seu conteúdo.
5. Dificuldades encontradas
O nosso grupo teve muitas dificuldades, muito mais do que tivemos na
implementação da camada física. Isso porque além das dificuldades que seriam
inerentes à camada de enlace, tivemos que fazer ajustes na camada física ou até
mesmo implementar funcionalidades que deixaram a desejar na 1ª etapa do
trabalho, desta forma tendo que voltar e repensar um pouco do código que
teoricamente não deveria ter sido tocado.
Tivemos como primeira dificuldade, já citada acima, o fato de ter que modificar a
camada física para atender as necessidades da camada de enlace. Na época que a
implementamos ainda não tínhamos noção suficiente de como a camada de enlace
funcionava e portanto, de que serviços ela necessitaria.
Uma outra dificuldade que herdamos da primeira etapa foi como fazer a leitura do
teclado de forma não bloqueante. Na implementação do teste da camada física
acabamos por não encontrar uma solução e optamos por testar um host sendo
servidor e o outro sendo cliente, já que o teste envolvia apenas duas máquinas. Só
para recordar, o problema é que com a função select conseguíamos resolver o
problema do rcvfrom(), mas na hora de obter do terminal os bytes a serem enviados,
com a função scanf(), por exemplo, acabava sendo bloqueante pois não saia da
leitura enquanto não fosse pressionado o ENTER. Porém na camada de enlace, por
ter que simular transmissão full-duplex não caberia uma implementação clitente-
servidor. Então de certa forma tivemos que retirar a "sujeira debaixo do tapete" e
limpar de vez. A solução encontrada foi chamar a biblioteca <termios.h> que permite
mudar a forma como se ler do terminal, passando a detectar cada caracter teclado,
ao invés de apenas a string após o ENTER. Assim, pudemos usar o select para
monitorar o teclado.
A implementação da lógica da tabela que o comutador mantém também foi uma
dificuldade. Afinal afim de simulá-la, na verdade precisamos manter duas tabelas de
forma que as informações de ambas fossem consistentes entre si. Ao se
desconectar, por exemplo, a informação do host deve ser retirada e tem que haver
toda uma reordenação da tabela.
E uma das principais dificuldades foi como testar o que estavamos codificando.
Afinal o produto final teria que rodar em três máquinas distintas, no mínimo. Na
maior parte do tempo, por falta de disponibilidade de tempo não pudemos testar
juntos, os três integrantes do grupo, o que nos levou a modificar um pouco o
programa para que simulasse diversos hosts numa só maquina, o que torna as
coisas um pouco mais confusa na nossa opinião.
6. Conclusões
Achamos essa simulação mais interessante do que a da camada física por já ter
mais lógica envolvida nessa camada. Mais uma vez percebemos como a divisão da
arquitetura de rede em camadas e suas abstrações facilitam a vida de todos. Apesar
de termos tido um pouco de dificuldade em fazer algumas modificações na camada
física, ficou óbvio que deu muito menos trabalho do que se tivéssemos que fazer
tudo do zero, num bloco só. Até mesmo a divisão da lógica do programa fica bem
mais clara, quando se tem a divisão em camadas. E pudemos notar agora de fato,
uma camada provendo serviços à outra.
7. Referências bibliográficas
•
•
•
•
Slides do curso.
http://beej.us/guide/bgnet/output/html/multipage/advanced.html
http://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input
Redes de computadores, Andrew S. Tanembaum.
Download

Implementação das funções da camada de enlace