← Todos os artigos

A verdade salto a salto

Sua ferramenta de caminhos desenha um corredor. Roteadores encaminham salto a salto. Aqui está a medição dessa diferença em 4.032 pares.

Michel Wijnberg

Quase toda ferramenta de caminho de rede que eu já usei (inclusive a minha, até pouco tempo atrás) funciona assim:

  1. Pega o roteador de origem.
  2. Roda Dijkstra sobre a topologia.
  3. Desenha o caminho mais curto que sair dali.

Isso é um corredor enraizado na origem, e é um modelo sutilmente errado do encaminhamento IP. O encaminhamento real não tem corredor. Cada roteador compara de forma independente o endereço de destino com a própria tabela de roteamento e escolhe um próximo salto. As duas respostas só coincidem enquanto a regra de decisão e o conjunto de entrada de cada roteador intermediário coincidirem com os da origem.

Em OSPF, rotineiramente não coincidem.


Um pacote que nunca chega

Este é um caso do meu laboratório, medido em cada roteador envolvido com show ip route, lido dos equipamentos e não modelado:

RoteadorO que diz sobre o destinoEncaminha para
dfw1-gw2metric 20031, type inter areadfw1-cr1
dfw1-cr1metric 30001, type intra areaord1-cr1não dfw2-cr1
ord1-cr1metric 20001, type intra areajfk1-cr1
jfk1-cr1metric 10001, type intra arealhr1-cr1
lhr1-cr1metric 1, connectedentregue

O corredor enraizado na origem desenhou isto:

dfw1-gw2 → dfw1-cr1 → dfw2-cr1 → iad2-cr1 → ams1-cr1 → lhr1-cr1

O pacote nunca chega a dfw2-cr1. O corredor é um caminho mais barato. Ele só não é um caminho que roteador nenhum vai construir. Duas regras independentes da RFC 2328 fazem dfw1-cr1 recusá-lo:

§16 passo (3) / §16.2 ¶1: o portão do backbone. Um roteador ligado a várias áreas examina apenas os summary-LSAs do backbone. O summary mais barato de dfw2-cr1, de custo 20011, está genuinamente no banco de dados da área 4.6.23.0 de dfw1-cr1 (confirmei com show ip ospf database summary), mas não é um candidato, porque dfw1-cr1 é um ABR e aquele summary não chegou pela área 0. A RFC 3509 §2.1/§2.2 (o comportamento de ABR da Cisco que de fato roda nesses equipamentos) condiciona isso a haver uma conexão ativa com o backbone, que dfw1-cr1 tem.

§16.2 passo (6): intra ganha de inter, ponto final. “If the paths present in the table are intra-area paths, do nothing with the LSA (intra-area paths are always preferred).” dfw1-cr1 já tem um caminho intra-área com métrica 30001. O summary de 20011 perde para ele. A métrica é irrelevante: esta é uma regra sobre o tipo de caminho, e a comparação de custo nunca acontece.

Qualquer uma das duas regras, sozinha, mata o corredor. Uma ferramenta que roda um único SPF a partir da origem não enxerga nenhuma das duas, porque nunca pergunta a dfw1-cr1 o que dfw1-cr1 pensa.


Com que frequência isso importa de verdade?

Esta é a parte com que eu me importo, porque “seu modelo é teoricamente impreciso” é uma afirmação muito mais fraca do que um número.

Então li a tabela de roteamento OSPF completa dos 64 roteadores do AS 200 e comparei cada um dos 4.032 pares ordenados origem/destino:

MediçãoResultado
Pares interárea em que o corredor desenhou ≥1 salto que roteador nenhum tomaria360 de 2.839 (12,68%)
Pares intra-área com o mesmo defeito0 de 1.193
Geral360 de 4.032 (8,93%)

O zero de intra-área é o teste de sanidade. Dentro de uma única área, todo roteador roda SPF sobre um LSDB idêntico, e um caminho mais curto continua sendo o mais curto a partir de qualquer ponto ao longo dele, então os dois modelos têm todos os motivos para coincidir. O ponto é que a coincidência foi medida, e não presumida: 1.193 pares, nenhuma discordância. No instante em que um ABR e um summary-LSA entram em cena, um caminho em cada oito é ficção.

Não “levemente subótimo”. Ficção, contendo um roteador que o pacote comprovadamente nunca visita. Se você está usando esse caminho para planejar uma janela de manutenção ou para explicar um incidente, está raciocinando sobre uma rota que não existe.


A correção: perguntar a cada roteador

O Osprey agora percorre a cadeia. A cada salto ele avalia a rota que aquele roteador instalou em direção ao endereço de destino, usando o LSDB daquele roteador, as próprias associações de área dele, o próprio status de ABR dele e a própria mistura de distâncias administrativas dele; depois segue o próximo salto que ele de fato seleciona, e repete.

Validado contra os mesmos 4.032 pares:

VerificaçãoResultado
Métrica do próprio roteador reproduzida exatamente4.032 / 4.032
Tipo de caminho (intra / inter / externo) exato4.032 / 4.032
Conjunto completo de próximos saltos ECMP instalados idêntico4.032 / 4.032
A cadeia termina em delivered no destino solicitado4.032 / 4.032

Não “perto”. Idêntico, em cada par, incluindo o conjunto completo de próximos saltos de custo igual em vez de um membro escolhido arbitrariamente.

É assim que isso aparece na tela: caminho de ida em laranja, de volta em azul, e tudo que não está no caminho esmaecido até virar um corredor:

Um caminho OSPF desenhado sobre a topologia com sobreposições de ida e volta e quatro caminhos de custo igual
Um caminho OSPF desenhado sobre a topologia com sobreposições de ida e volta e quatro caminhos de custo igual

Repare no seletor 4 equal-cost paths e no rótulo per-flow hash. O Osprey enumera o conjunto ECMP completo em vez de escolher um membro e apresentá-lo como o caminho, porque seu tráfego é distribuído por hash entre os quatro, e uma sessão de diagnóstico que examine apenas um deles não vai achar nada de errado em três de cada quatro vezes.

E aqui está o mesmo caminho aberto:

Um caminho OSPF de 10 saltos com tabela por salto, selos de ABR, portas de entrada e saída e a explicação numerada
Um caminho OSPF de 10 saltos com tabela por salto, selos de ABR, portas de entrada e saída e a explicação numerada

Cada salto carrega o roteador que tomou a decisão, a área em que a tomou, as interfaces físicas de entrada e saída com seus endereços, e o custo. Os selos ABR são derivados dos LSDBs, e não de nomes de host. A faixa de áreas embaixo mostra o caminho cruzando 12.1.24.00.0.0.06.18.1.0, que é o trânsito pelo backbone exigido pela RFC 2328 para tráfego interárea.

E o custo total exibido, 30061, é a métrica que a própria origem tem instalada. É literalmente o número que o show ip route imprime em lax1-gw1, custo de stub incluído, e não uma soma que o Osprey calculou juntando os enlaces de que gostou.

A explicação é gerada, não decorativa:

  1. Route type: O IA (inter-area): Source 172.16.2.33 and destination 172.16.5.23 have no shared area, routing via backbone (area 0.0.0.0)
  2. Path traverses: area 12.1.24.0 (cost 10) → area 0.0.0.0 (cost 30040) → area 6.18.1.0 (cost 10)
  3. Total cost: 30061 via 10 hops
  4. ECMP: 4 equal-cost paths available

Atravessando a fronteira do AS

Dentro de um IGP a cadeia é computável porque o LSDB é completo. Atravessando uma fronteira de AS, nada é. Não há banco de dados compartilhado, não há espaço métrico compartilhado e não há política de distância administrativa compartilhada.

A resposta honesta não é desistir, e definitivamente não é fingir que as métricas se compõem. É emendar evidências.

Um caminho de 15 saltos cruzando do AS 200 para o AS 300, com custos por segmento e uma transição eBGP
Um caminho de 15 saltos cruzando do AS 200 para o AS 300, com custos por segmento e uma transição eBGP

Quinze saltos de lax1-gw1 no AS 200 (locatário Harrier-Broadband, OSPF) até i-sin1-gw1 no AS 300 (locatário Merlin-Carrier, IS-IS). Leia o que ele faz:

  • O salto 8, jfk1-gw1, traz um selo BGP: é aqui que o IGP para e a decisão do BGP assume.
  • O salto 9, i-jfk1-gw1, traz um selo IS-IS: um protocolo completamente diferente, outro plano de endereçamento, outro locatário.
  • O rodapé diz “Per-segment costs (never summed) | 15 hops”. Um custo OSPF de 20051 e um custo IS-IS de 1320 são números em espaços métricos sem relação entre si. Somá-los daria 21371, que não é uma quantidade existente. O Osprey se recusa a imprimir isso.

A explicação gerada nomeia suas evidências a cada passo:

  1. BGP border selection: jfk1-gw1 holds 10.66.0.0/15 for 10.66.15.3 (AS path: 300)
  2. AS 200: IGP segment: lax1-gw1jfk1-gw1, cost 20051
  3. eBGP transition 200 → 300: jfk1-gw1 Et1/1 → i-jfk1-gw1 Et1/2 (bmp-peer+l2; ip-bound)
  4. AS 300: IGP segment: i-jfk1-gw1i-sin1-gw1, cost 1320

O passo 3 é a minha linha favorita do produto. Ele não diz “esses dois roteadores provavelmente estão conectados de algum jeito”. Ele nomeia portas físicas nas duas pontas, e depois mostra o raciocínio dentro daquele parêntese:

  • bmp-peer: uma sessão eBGP estabelecida entre eles, vista via BMP
  • +l2: o lado remoto foi casado através da adjacência LLDP/CDP dos roteadores de fronteira
  • ip-bound: os dois endereços da sessão resolveram para aquelas portas específicas pelos vínculos da IP-MIB dos dispositivos

Três evidências independentes concordando. Quando elas não concordam, o produto diz isso, e esse é justamente o assunto do próximo texto.


Por que eu me importo mais com isso do que com recursos

Um desenho de caminho é uma afirmação sobre o que sua rede vai fazer com um pacote. Se a afirmação está errada uma vez em cada oito e nada na tela distingue as erradas das certas, o desenho é pior do que inútil. Ele é confiantemente inútil, e será acreditado exatamente no momento em que estar errado sai caro.

Sair de “plausível” para “reproduz exatamente as 64 tabelas de roteamento, 4.032 de 4.032” exigiu um arcabouço de validação, um laboratório do qual eu consigo ler a verdade de referência, e disposição para descobrir que a minha própria ferramenta vinha desenhando ficção 360 vezes.

É para isso que serve o laboratório.


A seguir, o outro lado da mesma moeda: os lugares onde o Osprey não consegue calcular a resposta, e diz isso: O que o Osprey se recusa a adivinhar.