0% acharam este documento útil (0 voto)
12 visualizações4 páginas

Desafios e Soluções em Redes UFMG

Este documento descreve o trabalho realizado para o TP3 de Redes da UFMG. Os principais desafios enfrentados foram equilibrar a complexidade do código com a manipulação dos dados e garantir a sincronização das informações compartilhadas entre os nós. Os mecanismos implementados incluem atualizações periódicas dos vizinhos, otimização split horizon, balanceamento de carga e remoção de rotas desatualizadas.

Enviado por

FranciscoEli
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
12 visualizações4 páginas

Desafios e Soluções em Redes UFMG

Este documento descreve o trabalho realizado para o TP3 de Redes da UFMG. Os principais desafios enfrentados foram equilibrar a complexidade do código com a manipulação dos dados e garantir a sincronização das informações compartilhadas entre os nós. Os mecanismos implementados incluem atualizações periódicas dos vizinhos, otimização split horizon, balanceamento de carga e remoção de rotas desatualizadas.

Enviado por

FranciscoEli
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

UFMG

Redes
TP3 REDES
Alunos: Francisco Eli Rodrigues Lima
11 de Junho de 2018
Mariana Teatini Ribeiro

1 Desafios
O maior desafio neste trabalho foi o trade-off entre agrupar muita informação nas tabelas usadas no código e
ao mesmo tempo não deixá-lo muito complicado de manipular e achar possı́veis erros. O segundo desafio foi
manter o sincronismo dos dados, apesar de não haver problemas de concorrência sérios, precisávamos garantir
que não ocorresse situações inesperadas como ler estruturas vazias porque não foram preenchidas com os updates
corretos ou mesmo garantir duplicar entradas porque não houve tempo suficiente de fazer alguma checagem
importante.
Dificuldades do projeto: Um problema que consumiu um tempo razoável foi o não conhecimento da estru-
tura de dicionários de python, então na primeira implementação pensávamos que aquele formato dos pacotes
era simplesmente uma grande string com uma formato especı́fico, logo perdemos tempo criando funções que
codificavam e decodificavam pacotes, até percebemos que eles eram de fácil manipulação pela estrutura de
dicionários.

2 Atualizações periódicas:
Foi utilizada uma thread que roda um loop infinito a função abaixo, cada iteração do loop nós usamos duas
funções chamadas flush para limpar as entradas expiradas do vetor de distância de cada vizinho, que fica junto
da estrutura de dados que contém os vizinhos (NeighRoters), assim como limpamos também nosso próprio
vetor de distâncias (RouterList), dessa forma garantimos não mandar informações já expiradas para os nossos
vizinhos. Após isso, para cada vizinho criamos um pacote update especı́fico (create update pack ) e enviamos
para o destino com (udp send communication). Fazemos a thread adormecer por π segundos, conforme consta
na especificação como o tempo para mandar os pacotes de update. Ao final dos π segundos, a thread atualiza
novamente os vizinhos. Se um vizinho for removido ou adicionado, garantimos as atualizações corretas porque
simplesmente será removido da lista de Roteadores vizinhos.
def update_neighbors ( NeighRoters , routerList , myIp , mySock , pitime ):
while True :
flush_NeighList ( NeighRoters , t )
flush_routerList ( RoutersList , t )
for i in range ( len ( NeighRoters )):
destination = NeighRoters [ i ][0]
updatepack = create_update_pack ( dest , myIp , RoutersList )
ud p _ s e n d _ c o m m uni ca ti on ( destination , mySock , updatepack )
time . sleep ( pitime )

3 Split Horizon
A estratégia para garantir a otimização foi que ao criamos o pacote update para mandar para um vizinho, o que
se faz fazendo uma iteração sobre a tabela de distâncias (RoutersList) e adicionando distância por distância

• Se uma entrada nessa tabela de distâncias for igual ao destino do pacote de updates, então simplesmente
pulamos aquela iteração através de um comando continue.

• Em cada da tabela de distância RoutersList[i], guardamos uma lista de rotas possı́veis na 3 posição
RoutersLis[i][2] e pesquisamos sobre essa lista, se alguma dessas rotas for o destino do pacote update que
vamos mandar, então acionamos uma flag no código e simplesmente não colocamos mais tal entrada de
destinos, porque aprendemos daquele nó essa rota
• Dessa forma, nossos pacotes update obedecem à otimização split horizont

def cr ea te _update_pack ( dest , source , RoutersList ):


lista ={}
flag = False
for i in range ( len ( RoutersList )):
if ( RoutersList [ i ][0]== dest ):
continue

1
li s t o f _ o f _ p l a ce s_t o_ go = RoutersList [ i ][2]
for j in range ( len ( li sto f_ of _pl ac es _to _g o )):
if ( l i s t o f _ o f _ pl ace s_ to _go [ j ][0]== dest ):
flag = True
if ( flag == True ):
flag = False
continue
lista [ RoutersList [ i ][0]] = RoutersList [ i ][1]
lista [ source ] = 0
return { ’ type ’: ’ update ’ , ’ source ’: source , ’ destination ’: dest , ’ distances ’: lista }

4 Balanceamento de cargas
A estrutura da nossa tabela de distâncias RoutersList é a seguinte:

• Endereço do ip alcançável
• Distância até lá
• Lista de rotas com células da forma
• Ip da rota
• Tempo da rota aprendida(usado nas funções flush para retirar rotas desatualizadas).

isto é, para cada célula temos RoutersList = :

[destino1, distancia1, [[rota1, time1], [rota2, time2], . . . , [rotan, timen]]]


[destino2, distancia2, [[rota1, time1], [rota2, time2], . . . , [rotan, timen]]]
..
.
[destinon, distancian, [[rota1, time1], [rota2, time2], . . . , [rotan, timen]]]

Então toda vez que vamos procurar uma rota para algum destino,achamos o destino pelo primeiro campo,
simplesmente mandamos o pacote pela primeira entrada da lista de rotas daquela célula e jogamos essa entrada
para o final da lista, dessa forma garantimos uma divisão perfeita de fluxo.
Usamos a função search path para implementar tal abordagem
def s ea r c h_ p ath_routing ( destIp , RoutersList ):
for i in range ( len ( RoutersList )):
if ( RoutersList [ i ][0]== destIp ): # PROCURAMOS O IP DO DESTINO QUE QUEREMOS CHEGAR
aux = RoutersList [ i ][2] # PEGAMOS A TABELAS DE ROTA DAQUELE DESTINO
if ( len ( aux )==0):
return [ " not found " ," " ]
else :
aux1 = [ " found " , aux [0]]
aux . append ( aux [0]) # AQUI IMPLEMENTAMOS O BALANCEAMENTO
aux . remove ( aux [0]) # AQUI IMPLEMENTAMOS O BALANCEAMENTO
RoutersList [ i ][2]= aux # AQUI IMPLEMENTAMOS O BALANCEAMENTO
return aux1
return [ " not found " ," " ]

5 Reroteamento imediato
A nossa estrutura de vizinhos contém células da seguinte forma:
• Ip do vizinho
• Distância
• Uma lista com células da tabela de distância do vizinho
• Destino que o vizinho pode alcançar
• Distância para aquele destino

2
• Tempo em que descobrimos aquele destino alcançável pelo vizinho

[vizinho1, distancia1, [[destino1, distancia1, time1], . . . , [destinon, distancian, timen]]]


[vizinho2, distancia2, [[destino1, distancia1, time1], . . . , [destinon, distancian, timen]]]
..
.
[vizinhon, distancian, [[destino11, distancia1, time1], . . . , [destinon, distancian, timen]]]

Quanto precisamos achar uma rota alternativa, iteramos sobre todos os vizinhos e em cada vizino

• iteramos sobre sua tabela de distâncias, se acharmos uma pelo campo destino, então guardamos numa lista,
se acharmos novamente por outro vizinho uma rota por tamanho igual, adicionamos à lista novamente
• Se acharmos no passo anterior uma rota com tamanho menor, refazemos a lista apenas com aquele essa
rota menor.
• Ao final retornamos a lista com as rotas com menores distâncias possı́veis achadas. Tal procedimento é
implementado pela função search path rerouting

def s e a r c h _ p at h_re rout ing ( destIp , NeighRouters ):


distance =500000 # seta uma distancia grande
path = " " # colocamos nenhuma rota ainda
state = " not found " # inicialmente no achamos nada
t =0
for i in range ( len ( NeighRouters )): # ITERAMOS SOBRE A LISTA DE VIZINHOS
aux = NeighRouters [ i ][2] # pEGA A TABELA DE DISTANCIAS DO VIZINHO
for j in range ( len ( aux )): # itera sobre os roteadores # PROCURA SE ELE TEM AQUELE DESTINO
if ( aux [ j ][0]== destIp and aux [ j ][1] < distance ): # se acharmos a rota que queremos e a
path = NeighRouters [ i ][0] # distancia for menor , entao atualizamos
distance = aux [ j ][1]
state = " found "
t = aux [ j ][2]
return [ state , path , t ]

6 Remoção de rotas desatualizadas


Conforme foi vista anteriormente, temos dois lugares que precisamos checar para ver se as rotas estão atualizadas
ou não, basicamente seria muito custoso retirar uma rota imediatamente quando ela ficasse desatualizada porque
terı́amos que fazer uma busywait para conseguir chegar em algo próximo, então a estratégia utilizada foi toda
vez que fosse necessário saber quais são as rotas atualizadas para mandar um pacote, utilizamos duas funções
flush que procuram na tabela de distâncias e na tabela de vizinhos as rotas que já estão desatualizadas. A
estrutura da tabela de distancias e da tabela de vizinho foi vistas nos itens acima.
Vamos numa entrada da tabela de vizinhos e remove as rotas da tabela de distancias que já expiraram
def flush_Neighboor ( vizinho , pitime ):
tabela = vizinho [2] # aqui pega a tabela de distancia do no vizinho
i = 0
while ( i < len ( tabela )):
if ( time . time () > tabela [ i ][2]+4* pitime ): # aqui usamos o campo tempo ja explicado anteriormente
tabela . remove ( tabela [ i ]) # e vemos se ja estouramos 4 vezes aquele momento em tempo
else :
i +=1

Depois a lista de vizinhos removendo as rotas da tabela de distancias que já expiraram , utilizando a função
anterior pra remover
def flush_NeighList ( NeighList , pitime ):
for i in range ( len ( NeighList )):
flush_Neighboor ( NeighList [ i ] , pitime )

Já na nossa tabela de distâncias, analogamente à tabela de vizinhos


def flush_router ( router , t ):
tabela = router [2]
i = 0

3
while ( i < len ( tabela )):
if ( time . time () >4* t + tabela [ i ][1]):
tabela . remove ( tabela [ i ])
else :
i +=1

def flush_routerList ( RouterList , t ):


for i in range ( len ( RouterList )):
flush_router ( RouterList [ i ] , t )
i = 0
while ( i < len ( RouterList )):
if ( len ( RouterList [ i ][2])==0):
aux = s e a r c h _ p at h_re rout ing ( RoutersList [ i ][0] , NeighRoters )
if ( aux [0]== " found " ):
RouterList [ i ][2]. append ([ aux [1] , aux [2]])
else :
RouterList . remove ( RouterList [ i ])
i -=1
i +=1

Asssim, sempre que formos enviar um pacote e precisarmos procurar por rotas, damos um flush nas duas tabelas.
Também damos um flush nas duas tabelas no caso de precisarmos contruir um pacote update.

Common questions

Com tecnologia de IA

The 'flush_routerList' function serves to maintain the validity of the routing table by removing entries that are no longer up-to-date. It iteratively checks each route in the RouterList against a predefined time criterion, discarding any entries whose validity has expired. This proactive cleansing is important in the overall network routing strategy as it prevents stale or incorrect data from influencing routing decisions, ensures the accuracy of routing information, and facilitates timely and efficient routing updates across the network. The function therefore plays a crucial role in sustaining network robustness and reliability .

The concept of 'Split Horizon' implemented by the UFMG team involves optimizing routing update packets by excluding routes that should not be advertised back to their originating neighbors. When creating an update packet for a specific neighbor, the algorithm iterates over the RouterList to add distances. If an entry's destination matches the packet's destination, the iteration is skipped using a continue command. Additionally, within each distance list in RouterList[i][2], the routing logic checks if any routes correspond to the update packet's destination. If so, a flag is set, and those routes are not included. This method ensures that routes originating from a node are not included in update packets to that node, maintaining the optimization strategy of split horizon .

The primary challenge faced by the UFMG team was the trade-off between grouping a lot of information into tables used in the code without making it too complicated to manage and detect possible errors. They needed to maintain data synchronization to prevent unexpected situations, such as reading empty structures or duplicating entries due to time constraints in checks. They tackled these challenges by using a Python dictionary structure to simplify packet manipulation, which initially caused some misunderstanding because they initially considered the packet format as a large string with a specific format, leading them to spend time creating encoding and decoding functions unnecessarily .

The UFMG team implemented a periodic update strategy using a dedicated thread that cyclically executed flush and update routines. This approach involved flushing outdated entries from neighbor and routing lists, sending carefully constructed update packets to reflect current routing paths accurately, and leveraging the split horizon principle to prevent routing loops. By maintaining a regular cadence of these operations through timed sleeps (π seconds), the team ensured their routing data stayed current and synchronized across the network, enhancing overall efficiency and reducing redundant or incorrect route advertisements .

The team implemented load balancing by cycling through the list of possible routes for a destination within their distance table (RoutersList). When searching for a path to a destination, the packet is sent through the first entry of the route list. This entry is then moved to the end of the list, ensuring an even distribution of traffic across all possible paths over time. The primary advantage of this approach is that it naturally distributes network load without requiring additional complex algorithms, as each possible path is used in turn .

The UFMG team used a separate thread running an infinite loop to perform periodic updates and clean-ups. They employed two flush functions to remove expired entries from both the distance vector of each neighbor (NeighRouters) and their own routing table (RouterList). This process prevented the transmission of expired information to neighbors and ensured that routing updates were accurate and synchronized. The flush functions were executed before creating and sending update packets to neighbors, and the thread was set to sleep for a specified period (π seconds) to regulate the timing of these updates .

The 'search_path_routing' function serves as a key component in the network's path selection process by finding available routes to a specific destination in the routing table. Once a route is used, the function cycles the selected route to the end of the list, ensuring that subsequent queries distribute traffic across all available routes. This cyclic path selection thus acts as a mechanism for load balancing, as it rotates the usage evenly across multiple routes, preventing any single path from becoming overburdened and optimizing network throughput .

The team handled immediate rerouting by iterating over neighboring routers and examining each neighbor's distance table. The algorithm searched for alternative paths by checking the distance field for each destination. If a route to the desired destination was found with a smaller distance than previously recorded, it updated the path and recorded this as the current best route. This process prioritized routes with the smallest possible distances, ensuring that the most efficient alternative routes were selected for rerouting .

The update packet creation process respects the split horizon optimization strategy by ensuring that update packets exclude any information about routes that would lead back to the source of those routes. This is achieved by iterating through the routing table and skipping any entry where the route destination matches the packet destination, thus adhering to the split horizon rule. By preventing the advertisement of routes back to their origin, this strategy mitigates routing loops and enhances the accuracy of the information shared between routers .

To ensure the removal of outdated routes, the UFMG team used two main strategies: periodic flush operations and threshold-based removal criteria. The flush functions were called before sending packets or creating update packets, checking both the NeighRouters and RouterList to identify expired entries based on recorded timestamps. If the timestamp indicated expiration (exceeding four times a specified period), the route was removed. This process is crucial for network management because it prevents the propagation of outdated and potentially incorrect routing information, improving the accuracy and reliability of routing tables .

Você também pode gostar