1. Como este manual funciona
Para cada exercicio: faca uma mudanca, preveja o resultado IS-IS, observe o evento do Watcher e entao encontre o mesmo fato no Topolograph Monitoring, no SDK e - no exercicio de correlacao - na resposta do agente. Restaure o laboratorio antes do proximo exercicio independente.
isis01 e um dominio FRR de seis roteadores em uma area (49.0001, AS 65100). router2-router3 opera em Level-1-2; router3 ate router6 e a perna de router3 ate a LAN router4/router5 sao somente Level-2. O Watcher usa uma adjacencia Level-2 em router1 e resolve cada System ID para seu hostname pelo TLV de hostname dinamico do IS-IS, entao os eventos nomeiam router2, router3, router6 em vez de 0100.1001.000x.
- A linha CSV do Watcher e o evento de origem deterministico.
- O Monitoring e o SDK provam que o evento foi ingerido e pode ser consultado.
- O agente e usado apenas para correlacionar varios eventos em um incidente, nunca como substituto da linha de origem.
2. Subida e validação do laboratório de seis roteadores
Execute a topologia publica isis01 baseada em GRE do repositorio do IS-IS Watcher. prepare.sh tambem cria a bridge isis-br-dr e carrega os modulos de kernel MPLS de que o IS-IS TE precisa.
Primeiro verifique se ja ha um laboratorio em execucao com sudo clab inspect --all. Se um isis01 obsoleto aparecer, derrube-o com sudo clab destroy --topo isis01.clab.yml --cleanup a partir de containerlab/isis01/ antes de implantar de novo - nomeie o arquivo de topologia para nao tocar em nenhum outro laboratorio.
Comando
cd containerlab/isis01
sudo clab inspect --all
sudo clab destroy --topo isis01.clab.yml --cleanup # only if a stale isis01 is listed
sudo ./prepare.sh
sudo clab deploy --topo isis01.clab.yml
sudo docker logs clab-isis01-isis-watcher
sudo tail -f watcher/logs/watcher1.isis.log
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Seis conteineres de roteador mais o watcher estao ativos:
docker ps --filter name=clab-isis01listaclab-isis01-router1..6eclab-isis01-isis-watcher, todos comState=Up. - O watcher tem a LSDB e esta capturando:
docker logs clab-isis01-isis-watchermostraISIS LSDB has been receivedeSniffing packets on interface: eth1. - As adjacencias estao Up:
docker exec clab-isis01-router1 vtysh -c 'show isis neighbor'listarouter3no estadoUp; o primeiro grafo do Topolograph contem entao seis roteadores.
Reversao: Ao terminar o manual, remova o laboratorio com sudo clab destroy --topo isis01.clab.yml --cleanup a partir de containerlab/isis01/.
3. Formato do registro de evento de rede
O manual usa tres familias de eventos: host, metric e network. Leia event_object como o objeto alterado, event_status como a transicao e event_detected_by como o roteador que anuncia ou detecta. graph_time e a etiqueta propria do watcher para a execucao e seleciona o grafo do Topolograph.
As linhas IS-IS carregam um campo level (1 ou 2) que as linhas OSPF nao tem - e o terceiro campo, logo apos watcher_name. Leia a linha metric acima como uma frase: em 2026-09-07T06:55:14Z o watcher lab-isis01 viu router3 reanunciar seu enlace Level-1 em direcao a router2 com a metrica mudada de 10 para -1 (adjacencia perdida), na interface enderecada 192.168.23.2 na area 49.0001 / AS 65100. A identidade por tras de router2 e seu NET / System ID 49.0001.0100.1001.0002.00; o watcher imprime o hostname porque cada roteador anuncia o TLV de hostname dinamico.
Uma linha host ou network up/down simples nao carrega campos de custo, entao o Fluent Bit encaminha apenas a linha changed emparelhada. O Topolograph deduz que uma adjacencia cai pela linha metric cujo new_cost e -1, e que volta pela linha cujo old_cost e -1.
- Campos em ordem:
watcher_time,watcher_name,level,event_name,event_object,event_status, [campos de custo],event_detected_by,graph_time,area_num,asn, [local_ip,remote_ip|subnet_type,int_ext_subtype],sesid,srcid. area_num49.0001easn65100identificam o dominio de roteamento;seside a sessao do watcher,srcido System ID do roteador de origem (router1,0100.1001.0001).
CSV do Watcher
host: 2026-09-07T06:55:14.754Z,lab-isis01,1,host,router2,down,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.23.2,192.168.23.1,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
metric: 2026-09-07T06:55:14.756Z,lab-isis01,1,metric,router2,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.23.2,192.168.23.1,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
network: 2026-09-07T06:55:14.761Z,lab-isis01,1,network,192.168.23.0/24,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
4. De onde vêm os eventos
Uma mudanca IS-IS produz uma linha CSV do Watcher por nivel. O Fluent Bit a encaminha ao Topolograph, que a armazena e a expoe pela pagina de Monitoring, pela API de eventos e pelo SDK. Cada exercicio abaixo verifica o mesmo fato em cada nivel disponivel para voce.
- Log do Watcher isis01 -> parser CSV do Fluent Bit -> ingestao do Topolograph -> pagina de Monitoring + API de eventos -> SDK do Topolograph
- Pagina de Monitoring: OSPF/IS-IS Real-Time Monitoring. Escolha o grafo pelo carimbo de tempo em
Choose the graph, defina a janelaFrom/Toem UTC, ligue os botoesL1eL2, clique emFind logs; os botoesNew/Old Subnets,Up/Down LinkseChanged metricfiltram o que e listado. - O seletor de grafo lista cada instantâneo de topologia que o watcher reportou - essa é a topologia que o watcher enviou.
Requisicao do SDK
from topolograph import Topolograph
topo = Topolograph(url="http://<your-topolograph>:8080",
username="<email>", password="<password>")
graph = topo.graphs.get(latest=True)
print(graph.graph_time, graph.protocol, graph.hosts)
Saida do SDK
07Sep2026_06h49m43s_6_hosts isis {'count': 6}
5. Mudança de custo em um enlace ponto a ponto
Altere router2 eth1 em direcao a router3. As metricas IS-IS sao dirigidas, entao a metrica inversa de router3 para router2 nao deve ser descrita como o mesmo escalar. router2 eth1 nao tem um isis metric explicito, entao parte do padrao de wide-metric, 10. router2-router3 e um circuito Level-1-2, entao a mudanca e anunciada em ambos os niveis.
Comando
sudo docker exec clab-isis01-router2 vtysh \
-c 'conf t' -c 'interface eth1' -c 'isis metric 222'
Verifique a mudanca. Abra cada fonte disponível no seu ambiente e confira com os exemplos abaixo.
Log do Watcher As linhas metric e network da mudanca e de sua reversao, em L1 e L2 L1 + L2
CSV do Watcher
# router2: interface eth1 / isis metric 222
2026-09-07T06:52:15.035Z,lab-isis01,1,metric,router3,changed,old_cost:10,new_cost:222,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:52:15.037Z,lab-isis01,1,network,192.168.23.0/24,changed,old_cost:10,new_cost:222,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:52:15.045Z,lab-isis01,2,metric,router3,changed,old_cost:10,new_cost:222,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# rollback (isis metric 10):
2026-09-07T06:52:37.514Z,lab-isis01,1,metric,router3,changed,old_cost:222,new_cost:10,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:52:37.526Z,lab-isis01,2,metric,router3,changed,old_cost:222,new_cost:10,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
Monitoramento A mudanca de metrica 10 -> 222 no fluxo de eventos
No OSPF/IS-IS Real-Time Monitoring, escolha 07Sep2026_06h49m43s_6_hosts em Choose the graph, defina a janela From/To em torno de 06:52 UTC, ligue L1 e L2 e clique em Find logs. Com Changed metric ligado, o fluxo mostra object router3, detected by router2, 10 -> 222 - apenas a direcao router2 -> router3, uma vez para L1 e uma para L2. A direcao inversa nao e listada.
Verificacao via SDK get_adjacency_events e get_network_events retornam o mesmo objeto e os mesmos custos 2 eventos
Requisicao do SDK
adj = graph.events.get_adjacency_events(
start_time="2026-09-07T06:52:14Z", end_time="2026-09-07T06:52:20Z")
net = graph.events.get_network_events(
start_time="2026-09-07T06:52:14Z", end_time="2026-09-07T06:52:20Z")
for e in adj["adjacency_cost_change_events"]:
print(e.event_object, e.event_detected_by, e.old_cost, "->", e.new_cost, "L" + str(e.level_number))
for e in net["network_cost_change_events"]:
print(e.event_object, e.old_cost, "->", e.new_cost, "L" + str(e.level_number))
Saida do SDK
router3 router2 10 -> 222 L1
router3 router2 10 -> 222 L2
3ffe::192:168:23:2/127 10 -> 222 L1
192.168.23.0/24 10 -> 222 L1
3ffe::192:168:23:2/127 10 -> 222 L2
192.168.23.0/24 10 -> 222 L2
O evento metric nomeia a direcao router2 -> router3 (event_object router3, event_detected_by router2), 10 -> 222, em ambos os niveis; as sub-redes conectadas IPv4 e IPv6 carregam a mesma mudanca. A direcao inversa esta ausente.
Pergunte ao agente Uma pergunta generica de incidente sobre router2
Prompt: What happened with router2 in the last 10 minutes?
Uma resposta valida nomeia a direcao router2 -> router3 e ambos os valores de metrica (10 e 222) sem que a pergunta mencione custo ou metrica, e nao afirma que a direcao inversa router3 -> router2 mudou.
Reversao: Execute isis metric 10 (ou no isis metric) em router2 eth1 e confirme os eventos inversos 222 -> 10 metric e network.
6. Detecção de eventos de prefixos internos e externos
Execute cada experimento de prefixo separadamente. Ao contrario do OSPF, o IS-IS anuncia um loopback com a mascara com que esta configurado e o custeia pela metrica da interface - um /24 permanece /24 com custo 10, nao e reduzido a uma rota host /32. router6 e somente Level-2, entao seus prefixos aparecem apenas em L2.
- 6a. Em
router2,interface lo/ip address 192.168.123.1/24; observe192.168.123.0/24up e custo-1->10em L1 e L2. - 6b. Em
router6,interface lo/ip address 10.10.36.6/24; observe10.10.36.0/24up e custo-1->10em L2. - 6c. Em
router6,no ip route 6.6.6.6/32 192.168.36.3; observe6.6.6.6/32down e custo11->-1em L2. O FRR a redistribui no IS-IS sem o bit external, entao o watcher a marca comointernal.
Comando
sudo docker exec clab-isis01-router2 vtysh \
-c 'conf t' -c 'interface lo' -c 'ip address 192.168.123.1/24'
Verifique a mudanca. Abra cada fonte disponível no seu ambiente e confira com os exemplos abaixo.
Log do Watcher Uma linha up/down e uma linha changed por sub-exercicio 3 prefixos
CSV do Watcher
# 6a router2: interface lo / ip address 192.168.123.1/24
2026-09-07T06:52:52.074Z,lab-isis01,1,network,192.168.123.0/24,up,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:52:52.075Z,lab-isis01,1,network,192.168.123.0/24,changed,old_cost:-1,new_cost:10,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# 6b router6: interface lo / ip address 10.10.36.6/24
2026-09-07T06:53:39.099Z,lab-isis01,2,network,10.10.36.0/24,up,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:53:39.099Z,lab-isis01,2,network,10.10.36.0/24,changed,old_cost:-1,new_cost:10,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# 6c router6: no ip route 6.6.6.6/32 192.168.36.3
2026-09-07T06:54:14.533Z,lab-isis01,2,network,6.6.6.6/32,down,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:54:14.533Z,lab-isis01,2,network,6.6.6.6/32,changed,old_cost:11,new_cost:-1,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
Monitoramento Os prefixos novos e retirados no fluxo
No OSPF/IS-IS Real-Time Monitoring, escolha este grafo, defina a janela em torno de 06:52-06:55 UTC, ligue L1 e L2 e clique em Find logs. Com New/Old Subnets ligado, 192.168.123.0/24 e 10.10.36.0/24 aparecem como adicionados e 6.6.6.6/32 como retirado.
Verificacao via SDK get_network_events, um evento changed por sub-exercicio 3 eventos
Requisicao do SDK
for start, end in [("2026-09-07T06:52:50Z", "2026-09-07T06:52:55Z"),
("2026-09-07T06:53:37Z", "2026-09-07T06:53:42Z"),
("2026-09-07T06:54:12Z", "2026-09-07T06:54:17Z")]:
net = graph.events.get_network_events(start_time=start, end_time=end)
for e in net["network_up_down_events"]:
print(e.event_object, e.event_status, e.event_detected_by,
f"{e.old_cost} -> {e.new_cost}", "L" + str(e.level_number), e.subnet_type)
Saida do SDK
192.168.123.0/24 changed router2 -1 -> 10 L1 internal
192.168.123.0/24 changed router2 -1 -> 10 L2 internal
10.10.36.0/24 changed router6 -1 -> 10 L2 internal
6.6.6.6/32 changed router6 11 -> -1 L2 internal
O /24 mantem sua mascara - sem colapso para /32. A disponibilidade e uma linha up/down que o forwarder descarta; a mudanca de custo e o evento changed que o SDK retorna. O loopback de router2 e visto em L1 e L2, o de router6 apenas em L2, e o 6.6.6.6/32 redistribuido e marcado como internal.
Reversao: 6a: no ip address 192.168.123.1/24 em router2 interface lo. 6b: no ip address 10.10.36.6/24 em router6 interface lo. 6c: ip route 6.6.6.6/32 192.168.36.3 em router6. Confirme o evento inverso apos cada um.
7. Detecção de uma perda de conectividade e sua recuperação
Desative router2 eth1, inspecione o conjunto de eventos correlacionados e entao restaure a interface com no shutdown. Como router2-router3 e Level-1-2, cada linha aparece uma vez para L1 e uma para L2.
Comando
# down
sudo docker exec clab-isis01-router2 vtysh \
-c 'conf t' -c 'interface eth1' -c 'shutdown'
# recovery
sudo docker exec clab-isis01-router2 vtysh \
-c 'conf t' -c 'interface eth1' -c 'no shutdown'
Verifique a mudanca. Abra cada fonte disponível no seu ambiente e confira com os exemplos abaixo.
Log do Watcher O conjunto down de L1 e o conjunto de recuperacao de L1 para o enlace router2-router3 down + up
CSV do Watcher
# router2: interface eth1 / shutdown
2026-09-07T06:55:14.754Z,lab-isis01,1,host,router2,down,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.23.2,192.168.23.1,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:55:14.756Z,lab-isis01,1,metric,router2,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.23.2,192.168.23.1,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:55:14.760Z,lab-isis01,1,metric,router3,changed,old_cost:10,new_cost:-1,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:55:14.761Z,lab-isis01,1,network,192.168.23.0/24,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# router2: interface eth1 / no shutdown
2026-09-07T06:55:39.545Z,lab-isis01,1,metric,router3,changed,old_cost:-1,new_cost:10,router2,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:55:39.607Z,lab-isis01,1,metric,router2,changed,old_cost:-1,new_cost:10,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.23.2,192.168.23.1,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
Monitoramento A queda como uma unica onda no fluxo
No OSPF/IS-IS Real-Time Monitoring, escolha este grafo, defina a janela em torno de 06:55 UTC, ligue L1 e L2 e clique em Find logs. Com Up/Down Links ligado, router2 e router3 mostram cada um o seu lado do enlace indo para -1 e voltando, e 192.168.23.0/24 fica inalcancavel e retorna - duas vezes, uma por nivel.
Verificacao via SDK get_adjacency_events retorna os movimentos down/up emparelhados 4 movimentos
Requisicao do SDK
down = graph.events.get_adjacency_events(
start_time="2026-09-07T06:55:14Z", end_time="2026-09-07T06:55:16Z")
for e in down["all_host_up_down_events"]:
print(e.event_object, "detected_by", e.event_detected_by,
f"{e.old_cost} -> {e.new_cost}", "L" + str(e.level_number))
Saida do SDK
router2 detected_by router3 10 -> -1 L1
router3 detected_by router2 10 -> -1 L1
router2 detected_by router3 10 -> -1 L2
router3 detected_by router2 10 -> -1 L2
host router2 down detectado por router3, ambas as metricas dirigidas a -1, 192.168.23.0/24 down - em L1 e L2; depois a recuperacao espelhada. Na recuperacao o watcher tambem registra um flap node attr:attached em router2, que o Topolograph ainda nao ingere.
Pergunte ao agente Uma pergunta generica de incidente sobre a rede
Prompt: What happened in the network in the last 30 minutes?
Resposta capturada (Qwen; a redacao varia entre execucoes)
In the last 30 minutes the IS-IS domain (area 49.0001, AS 65100) had 7 event waves detected by watcher lab-isis01, starting at 06:55:15 UTC. Every device that went down recovered within the window.
06:55:15 - router2 and router3 each lost the adjacency between them, at L1 and L2 (router2 detected by router3, router3 detected by router2).
06:55:40 - both routers restored that adjacency at L1 and L2, followed by a few repeated up notifications through 06:56:33.
06:57:23 - router6 lost its L2 adjacency to router3; 06:57:56 - router6 and router3 restored it.
In short: the router2-router3 link dropped at 06:55:15 and came back at 06:55:40; the router3-router6 link dropped at 06:57:23 and recovered at 06:57:56 - both fully converged.
A resposta nomeia a adjacencia caida (router2 - router3), que router3 detectou a perda de router2 e vice-versa, ambas as metricas em -1 e a recuperacao - os mesmos fatos das linhas CSV acima, a partir de uma pergunta que nunca diz "adjacency" ou "failure". As linhas de router6 sao o exercicio de transito abaixo, capturado pela mesma janela de 30 minutos.
Reversao: no shutdown em router2 eth1 restaura a interface; aguarde os eventos de recuperacao host, network e metric em ambos os niveis.
8. Relato de um segmento de trânsito de difusão
router6 eth1 encara router3 em um circuito broadcast (LAN). router6 tem isis priority 100 contra 64 de router3, entao router6 e o DIS e origina o LSP de pseudonode. O circuito e somente Level-2, entao cada linha e L2. router6 eth1 nao tem um isis metric explicito, entao a base e o padrao 10.
Comando
# cost
sudo docker exec clab-isis01-router6 vtysh \
-c 'conf t' -c 'interface eth1' -c 'isis metric 66'
# then, separately: shutdown, then no shutdown
sudo docker exec clab-isis01-router6 vtysh \
-c 'conf t' -c 'interface eth1' -c 'shutdown'
sudo docker exec clab-isis01-router6 vtysh \
-c 'conf t' -c 'interface eth1' -c 'no shutdown'
Verifique a mudanca. Abra cada fonte disponível no seu ambiente e confira com os exemplos abaixo.
Log do Watcher A mudanca de custo L2 com seus efeitos colaterais em network, mais o par shutdown/recuperacao custo + up/down
CSV do Watcher
# router6: interface eth1 / isis metric 66 (rollback: isis metric 10)
2026-09-07T06:56:47.139Z,lab-isis01,2,network,192.168.36.0/24,changed,old_cost:10,new_cost:66,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:56:47.140Z,lab-isis01,2,metric,router3,changed,old_cost:10,new_cost:66,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:57:04.561Z,lab-isis01,2,metric,router3,changed,old_cost:66,new_cost:10,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# router6: interface eth1 / shutdown
2026-09-07T06:57:22.037Z,lab-isis01,2,network,192.168.36.0/24,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,internal,0,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:57:22.055Z,lab-isis01,2,host,router6,down,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.36.3,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:57:22.055Z,lab-isis01,2,metric,router6,changed,old_cost:10,new_cost:-1,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.36.3,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
# router6: interface eth1 / no shutdown
2026-09-07T06:57:55.962Z,lab-isis01,2,host,router6,up,router3,07Sep2026_06h49m43s_6_hosts,49.0001,65100,192.168.36.3,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
2026-09-07T06:57:55.973Z,lab-isis01,2,metric,router3,changed,old_cost:-1,new_cost:66,router6,07Sep2026_06h49m43s_6_hosts,49.0001,65100,,,e50b9d98-aa86-11f1-92b0-46ed252a638b,0100.1001.0001
Monitoramento A mudanca de custo de transito e a queda de router6, apenas L2
No OSPF/IS-IS Real-Time Monitoring, escolha este grafo, defina a janela em torno de 06:56-06:58 UTC, ligue L2 e clique em Find logs. O object do evento metric e router3 com event_detected_by router6, e a mudanca e apenas L2 - o circuito e level-2-only. No shutdown o fluxo mostra host router6 down e 192.168.36.0/24 inalcancavel, depois a recuperacao.
Verificacao via SDK get_adjacency_events para o custo de transito e o shutdown/recuperacao apenas L2
Requisicao do SDK
cost = graph.events.get_adjacency_events(
start_time="2026-09-07T06:56:46Z", end_time="2026-09-07T06:56:49Z")
for e in cost["adjacency_cost_change_events"]:
print("cost", e.event_object, e.event_detected_by, f"{e.old_cost} -> {e.new_cost}", "L" + str(e.level_number))
flap = graph.events.get_adjacency_events(
start_time="2026-09-07T06:57:21Z", end_time="2026-09-07T06:58:00Z")
for e in flap["all_host_up_down_events"]:
print("updown", e.event_object, e.event_detected_by, f"{e.old_cost} -> {e.new_cost}", "L" + str(e.level_number))
Saida do SDK
cost router3 router6 10 -> 66 L2
updown router6 router3 10 -> -1 L2
updown router6 router3 -1 -> 10 L2
updown router3 router6 -1 -> 10 L2
No segmento broadcast o evento metric ainda nomeia o vizinho (router3), detectado por router6, e apenas em L2; a mudanca de metrica tambem move 192.168.36.0/24 e as duas /127 IPv6. O shutdown e host router6 down em L2, depois a recuperacao.
Pergunte ao agente Uma pergunta generica de incidente sobre router6
Prompt: What happened on router6 in the last 20 minutes?
Uma resposta valida nomeia a metrica de transito router6 -> router3 movendo-se 10 -> 66 e de volta, depois a conexao de router6 caindo (metrica -1 em L2) e recuperando, sem que a pergunta mencione custo, DIS ou shutdown.
Reversao: isis metric 10 (ou no isis metric) em router6 eth1 restaura a base 10; no shutdown restaura a adjacencia. Confirme os eventos metric inversos.
9. Carregar o laboratório IS-IS de 13 roteadores
O laboratório de seis roteadores permite examinar eventos do Watcher e atributos TE, mas não oferece caminhos alternativos suficientes para exercícios úteis de CSPF. Use o laboratório 13-hosts-demo-isis: implante-o ou dispense a implantação e baixe a LSDB pronta demo_isis_LSDB.txt.
Envie a LSDB ao Topolograph como arquivo FRR IS-IS: a capturada em r30 ou o demo_isis_LSDB.txt baixado. O grafo resultante tem 13 nós e 52 arestas direcionadas: 12 no nível 1 e 40 no nível 2. Cinquenta arestas possuem atributos TE; as duas direções de r110-r111 não possuem.
Comando
cd containerlab/13-hosts-demo-isis
sudo clab deploy --topo 13-hosts-demo-isis.clab.yml
sudo docker exec clab-13-hosts-demo-isis-r30 vtysh -c 'show isis database detail'
Requisicao do SDK
from topolograph import Topolograph
topo = Topolograph(url="http://<your-topolograph>:8080", username="<email>", password="<password>")
graph = topo.graphs.upload(open("demo_isis_LSDB.txt").read(), vendor="FRR", protocol="isis")
print(graph.graph_time, graph.hosts)
print(graph.edges_list(per_page=200)["pagination"]["total"])
print(graph.edges_list(is_te_link=True, per_page=200)["pagination"]["total"])
print(graph.edges_list(is_te_link=False, per_page=200)["pagination"]["total"])
Saida do SDK
<new graph time> {'count': 13}
52
50
2
Observacoes obrigatorias Fatos a confirmar antes de continuar
- O campo
hostsdo grafo carregado contém{'count': 13}e o número total de arestas é 52. edges_list(is_te_link=True)retorna 50 arestas;edges_list(is_te_link=False)retorna as duas direções der110-r111.
10. Ler valores TE antes do cálculo
Examine os atributos TE antes de aplicar uma restrição. Identifique os grupos administrativos gold e red, métricas TE altas, o pequeno pool de banda da prioridade 7, enlaces com SRLG e enlaces sem TE. Um cálculo comum de caminho mínimo não informa se um enlace é adequado para um túnel.
Neste grafo, gold (0x00000002) corresponde a 10 arestas direcionadas, red (0x00000004) a 2, temetric__gt=30 a 4, unreserved_bw_7__lt=1000000 a 2, e is_te_link=False retorna as duas direções de r110-r111.
Comando
# Execute estes filtros do SDK no grafo da etapa 1
Requisicao do SDK
for query in (
{'admin_group': '0x00000002'},
{'admin_group': '0x00000004'},
{'temetric__gt': 30},
{'unreserved_bw_7__lt': 1_000_000},
{'is_te_link': False},
):
result = graph.edges_list(per_page=200, **query)
print(query, result['pagination']['total'])
Saida do SDK
{'admin_group': '0x00000002'} 10
{'admin_group': '0x00000004'} 2
{'temetric__gt': 30} 4
{'unreserved_bw_7__lt': 1000000} 2
{'is_te_link': False} 2
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Oito arestas em
r10-r100,r100-r110er100-r111possuem dados SRLG; os dois enlaces paralelosr10-r100mantêm seus próprios grupos. - O valor de texto
is_te_link='yes'é rejeitado com HTTP 400:Wrong type, expected 'boolean'.
11. Registrar a rota sem restrições
Calcule o caminho sem restrições de r10 para r14 e mantenha-o como referência para os exercícios seguintes. Assim, cada nova restrição poderá ser comparada com um caminho conhecido.
O caminho de referência é r10 r100 r110 r14, com custo 30. Ele usa o enlace paralelo eth2 entre r10 e r100.
Comando
Não altere roteadores; execute a consulta CSPF de referência.
Requisicao do SDK
print(graph.cspf_path('r10', 'r14'))
Saida do SDK
{'cost': 30, 'path': ['r10', 'r100', 'r110', 'r14'], 'reason': ''}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Os quatro passos seguintes moverão a rota usando uma restrição por vez.
12. Evitar grupos de risco compartilhado
Use srlg_exclude para contornar um enlace ou duto compartilhado em manutenção. O caminho de referência r10 r100 r110 r14 custa 30: seu primeiro salto pertence ao SRLG 300 e os dois primeiros saltos paralelos compartilham o SRLG 100.
Excluir 300 mantém os mesmos roteadores, mas seleciona eth1 e aumenta o custo para 35. Excluir 100 produz r10 r11 r100 r110 r14, custo 40; excluir 200 produz r10 r100 r101 r111 r14, custo 45; excluir 100 e 200 produz r10 r11 r101 r111 r14, custo 50.
Comando
Altere somente a lista `srlg_exclude`.
Requisicao do SDK
for groups in ([300], [100], [200], [100, 200]):
print(groups, graph.cspf_path('r10', 'r14', srlg_exclude=groups))
Saida do SDK
[300] {'cost': 35, 'path': ['r10', 'r100', 'r110', 'r14'], 'reason': ''}
[100] {'cost': 40, 'path': ['r10', 'r11', 'r100', 'r110', 'r14'], 'reason': ''}
[200] {'cost': 45, 'path': ['r10', 'r100', 'r101', 'r111', 'r14'], 'reason': ''}
[100, 200] {'cost': 50, 'path': ['r10', 'r11', 'r101', 'r111', 'r14'], 'reason': ''}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- A restrição remove enlaces; ela não altera a métrica IGP.
13. Escolher a rota por banda e prioridade
Solicite um túnel de 8 Mbit com diferentes prioridades de estabelecimento. O caminho de referência r10 r100 r110 r14 custa 30, mas r100-r110 anuncia apenas 4 Mbit no pool da prioridade 7 e 10 Mbit nas prioridades 0 a 3.
Na prioridade 7, o CSPF move o túnel para r10 r100 r111 r14, custo 40. Na prioridade 0, mantém r10 r100 r110 r14, custo 30. Uma solicitação de 20 Mbit não cabe em nenhum caminho disponível e retorna uma recusa de restrição.
Comando
Altere `bandwidth` e `setup_priority` na consulta CSPF.
Requisicao do SDK
for priority in (7, 0):
print(priority, graph.cspf_path('r10', 'r14', bandwidth='8M', setup_priority=priority))
print(graph.cspf_path('r10', 'r14', bandwidth='20M'))
Saida do SDK
7 {'cost': 40, 'path': ['r10', 'r100', 'r111', 'r14'], 'reason': ''}
0 {'cost': 30, 'path': ['r10', 'r100', 'r110', 'r14'], 'reason': ''}
{'cost': None, 'path': [], 'reason': 'no path satisfies the requested constraints'}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- A prioridade escolhe o pool de banda anunciado, mas não altera o custo IGP.
14. Calcular usando a métrica TE
Recalcule o caminho com metric_type='te' após confirmar que cada enlace candidato possui uma métrica TE. O caminho IGP r10 r100 r110 r14 custa 30, mas r100-r110 tem métrica TE 100 e r100-r111 tem métrica TE 10.
O CSPF seleciona r10 r100 r111 r14 com custo TE 30. O mesmo caminho tem custo IGP 40, mostrando o efeito da métrica escolhida.
Comando
Use `metric_type='te'`; não altere roteadores.
Requisicao do SDK
print(graph.cspf_path('r10', 'r14', metric_type='te'))
Saida do SDK
{'cost': 30, 'path': ['r10', 'r100', 'r111', 'r14'], 'reason': ''}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Sem métrica TE, o cálculo usa a métrica IGP daquele enlace.
15. Incluir ou excluir bits de admin group
Use os bits de grupos administrativos para exigir ou evitar classes de enlaces. O bit 1 é gold e o bit 2 é red. O caminho sem restrições de r13 para r15 é r13 r100 r110 r15, custo 30.
Exigir gold com admin_include_all=['1'] muda esse caminho para r13 r101 r111 r15, custo 45; de r10 para r14, produz r10 r101 r111 r14, custo 55. Evitar red com admin_exclude_any=['2'] produz r13 r100 r111 r15, custo 40.
Comando
Envie números de bits, não máscaras hexadecimais.
Requisicao do SDK
print(graph.cspf_path('r13', 'r15', admin_include_all=['1']))
print(graph.cspf_path('r10', 'r14', admin_include_all=['1']))
print(graph.cspf_path('r13', 'r15', admin_exclude_any=['2']))
Saida do SDK
{'cost': 45, 'path': ['r13', 'r101', 'r111', 'r15'], 'reason': ''}
{'cost': 55, 'path': ['r10', 'r101', 'r111', 'r14'], 'reason': ''}
{'cost': 40, 'path': ['r13', 'r100', 'r111', 'r15'], 'reason': ''}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Bit 1 é
0x00000002, bit 2 é0x00000004; bit 0 é o menos significativo.
16. Restringir CSPF a um nível IS-IS
Defina level=1 ou level=2 para calcular dentro de uma única topologia IS-IS e confirme que ambas as extremidades pertencem a ela. Entre r30 e r31, o caminho direto do nível 1 custa 10, enquanto o caminho do nível 2 r30 r10 r11 r31 custa 40.
O caminho r130-r131 custa 10 no nível 1, mas retorna src/dst not found no nível 2. A topologia combinada contém um caminho r130-r15 de custo 50, mas nenhum nível individual o contém porque ele cruza a fronteira entre níveis.
Comando
Adicione `level=1` ou `level=2` à consulta CSPF.
Requisicao do SDK
for level in (None, 1, 2):
print(level, graph.cspf_path('r30', 'r31', level=level))
print(graph.cspf_path('r130', 'r131', level=2))
Saida do SDK
None {'cost': 10, 'path': ['r30', 'r31'], 'reason': ''}
1 {'cost': 10, 'path': ['r30', 'r31'], 'reason': ''}
2 {'cost': 40, 'path': ['r30', 'r10', 'r11', 'r31'], 'reason': ''}
{'cost': None, 'path': [], 'reason': 'src/dst not found'}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Um grafo antigo sem dados por nível retorna HTTP 422 e
isis_level_calculation_unavailable; faça upload novamente.
17. Distinguir restrição impossível de endpoint ausente
Leia reason quando o CSPF retornar um path vazio. A solicitação de 20 Mbit da etapa 5 tem extremidades válidas, mas nenhum caminho possui banda suficiente; uma solicitação de nível 1 entre r130 e r15 não tem uma topologia de nível único que contenha ambas as extremidades.
A solicitação de banda retorna no path satisfies the requested constraints; a solicitação no nível errado retorna src/dst not found. Essas falhas exigem correções diferentes.
Comando
Repita os pedidos recusados das etapas 5 e 8.
Requisicao do SDK
print(graph.cspf_path('r10', 'r14', bandwidth='20M'))
print(graph.cspf_path('r130', 'r15', level=1))
Saida do SDK
{'cost': None, 'path': [], 'reason': 'no path satisfies the requested constraints'}
{'cost': None, 'path': [], 'reason': 'src/dst not found'}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- A primeira mensagem pede relaxar bandwidth, affinity ou SRLG; a segunda indica endpoints ausentes.
18. Editar um enlace e recalcular
Modele a manutenção de r100-r110 sem alterar os roteadores. Em uma cópia descartável do grafo, use update_edge para adicionar o SRLG 999 à aresta do nível 2, recalcule excluindo esse grupo e depois limpe o SRLG.
Excluir 999 troca r10 r100 r110 r14, custo 30, por r10 r100 r111 r14, custo 40; limpar o SRLG restaura o caminho de referência. Uma aresta exclusiva do nível 2 rejeita isis_level=1. Como replace_edge remove os dados por nível, uma solicitação CSPF com nível explícito retorna HTTP 422 após uma substituição completa.
Comando
# Use um grafo descartável: a edição é persistente
# Primeiro encontre o id da aresta com edges_list(include=['edge_key'])
Requisicao do SDK
edge = next(e for e in graph.edges_list(include=['edge_key'], per_page=200)['items']
if e['src'] == 'r100' and e['dst'] == 'r110')
print(graph.update_edge(edge['id'], isis_level=2, srlg=[999]))
print(graph.cspf_path('r10', 'r14', srlg_exclude=[999]))
print(graph.update_edge(edge['id'], isis_level=2, srlg=[]))
print(graph.cspf_path('r10', 'r14'))
Saida do SDK
... srlg: [999] ...
{'cost': 40, 'path': ['r10', 'r100', 'r111', 'r14'], 'reason': ''}
... srlg: [] ...
{'cost': 30, 'path': ['r10', 'r100', 'r110', 'r14'], 'reason': ''}
Observacoes obrigatorias Fatos a confirmar antes de continuar
update_edgealtera apenas os campos fornecidos;replace_edgereescreve a aresta inteira. Não use nenhum deles no grafo de referência que deve ser preservado.
19. Colocar LSP e conferir a banda restante
Adicione quatro túneis de 4 Mbit de r10 para r14, um por vez, e examine a banda residual e o caminho escolhido após cada colocação. Antes da primeira colocação, o pool de prioridade 7 de 4 Mbit do caminho de referência r10 r100 r110 r14 está disponível.
T1 usa r10 r100 r110 r14, custo 30; T2 usa r10 r100 r111 r14, custo 40; T3 usa o outro enlace r10-r100, custo 45; e T4 usa r10 r11 r101 r110 r14, custo 55. Remova todos os LSP de teste ao concluir o exercício.
Comando
# Não altere os roteadores: crie quatro túneis RSVP-TE de 4 Mbit com o SDK
Requisicao do SDK
for name in ('T1', 'T2', 'T3', 'T4'):
lsp = graph.add_lsp({
'name': name, 'src': 'r10', 'dst': 'r14', 'bandwidth': '4M',
'paths': {'primary': {'role': 'primary', 'bandwidth': '4M'}},
})
primary = lsp['paths']['primary']
print(name, primary['path'], primary['cost'])
print(graph.edges_list(include=['lsp_left_bw', 'lsps'], per_page=200)['items'])
graph.delete_lsps()
Saida do SDK
T1 ['r10', 'r100', 'r110', 'r14'] 30
T2 ['r10', 'r100', 'r111', 'r14'] 40
T3 ['r10', 'r100', 'r110', 'r14'] 45
T4 ['r10', 'r11', 'r101', 'r110', 'r14'] 55
... lsp_left_bw_7 e lsps para cada aresta ...
{'deleted': 4}
Observacoes obrigatorias Fatos a confirmar antes de continuar
- Após cada colocação, use
edges_list(include=['lsp_left_bw', 'lsps'])para ver qual pool causou a próxima mudança de caminho. - Sempre chame
delete_lsps()durante a limpeza; a colocação de LSP altera o grafo armazenado.