Ir al contenido

Bucle de capa 2

En resumen: un bucle de capa 2 detrás de un puerto de un bridge de MikroTik se ve en el log del kernel de Linux aunque el log de RouterOS y su monitor de puertos sigan limpios, como aquí: received packet on <port> with own address as source address, con las tramas reflejadas separadas 2,00–2,01 s, que es el hello interval de STP. El puerto de esa línea es por donde entró la trama reflejada, no siempre el puerto que el bucle ha dejado aislado, así que compara el rx de cada puerto del bridge con su tx antes de desenchufar un cable. Aquí el flujo bajó de 1,49 /s a 0,03 /s tras actualizar el firmware de los puntos de acceso de la malla, y una semana después el bucle volvió.

Un fallo real, no provocado. Se encontró por casualidad el 2026-09-12, mientras se medía otra cosa, en el RB5009UG+S+ de producción del propietario (RouterOS 7.24.2, kernel 5.6.3), y se diagnosticó y desapareció ese mismo día. Una semana después volvió. Durante toda su vida, el log de RouterOS y su monitor de puertos informaron de un equipo sano.

Los pasos 1 a 6 son el diagnóstico en el orden en que se hizo. Síguelos en el mismo orden en tu propio router.

/snapshot traía un flujo constante de events — la fuente kmsg del agente — a 1,49 /s:

[6] br0: port 2(eth1) entered blocking state
[4] br0: received packet on eth1 with own address as source address (addr:00:00:5e:00:53:5d, vlan:0)
[6] br0: port 2(eth1) entered learning state

La dirección de la segunda línea es la del propio router: la MAC de sfp-sfpplus1, volviendo a entrar en el bridge. Aquí aparece como 00:00:5e:00:53:5d, del bloque que la RFC 9542 reserva para documentación (sustituyó a la RFC 7042 en 2024); en tu equipo será la de tu bridge, y así es como reconoces la línea.

Cuenta sucesos por segundo en una ventana lo bastante larga como para ser estable. Una sola línea de log es una anécdota; una tasa es una medida, y te dice después si una corrección funcionó:

Ventana de terminal
curl -s "http://172.30.10.2:9123/snapshot?seconds=120" \
| python3 -c '
import sys, json, collections
rows=[json.loads(l) for l in sys.stdin if l.strip()]
secs=sum(r["dt_ns"] for r in rows)/1e9
ev=[e for r in rows for e in r.get("events",[])]
print(f"{len(ev)/secs:.2f} events/s over {secs:.0f}s")
c=collections.Counter(e["msg"].split("(")[0][:60] for e in ev)
for k,v in c.most_common(): print(f" {v:5d} {k}")'

?seconds= admite de 1 a 3600, y el agente solo puede devolver lo que su anillo aún guarda — 60 s con el BUFFER_S por defecto. La longitud de la ventana sale de sumar el dt_ns de cada muestra, no del número que pediste.

Toma los intervalos entre apariciones consecutivas de un mismo mensaje:

Ventana de terminal
# intervalos entre apariciones consecutivas de un mismo mensaje
... | python3 -c '
import sys, json
ts=sorted(e["us"]/1e6 for l in sys.stdin if l.strip()
for e in json.loads(l).get("events",[]) if "own address" in e["msg"])
print([round(ts[i+1]-ts[i],2) for i in range(len(ts)-1)][:12])'

us es la marca de tiempo del propio kernel para el registro, en microsegundos desde el arranque sobre el reloj monótono, no el momento en que el agente lo leyó, así que los intervalos son los del kernel, no los del muestreador.

Los intervalos entre las tramas reflejadas eran de 2,00–2,01 s, siempre. 2 s es el hello interval de STP, el HelloTime por defecto de RouterOS. Así que el router enviaba una BPDU y recibía de vuelta su propia BPDU: un bucle, no un cliente que se porta mal.

mikroscope doctor, ejecutado por sí solo, hace este recuento por ti (internal/health/health.go). Lee una vez el anillo del agente en marcha e informa de:

  • WARN layer2-loop, con el puerto, cuando en la ventana han vuelto tres o más tramas con la propia dirección del bridge;
  • stp-churn para un puerto que STP ha pasado a learning al menos tres veces más de las que lo ha dejado reenviar, salvo que ese puerto tenga ya el hallazgo de dirección propia.

Dos reglas de alerta de internal/dashboards/alerts.go vigilan el mismo fallo a lo largo del tiempo:

  • mikroscope-l2-loop salta con el primer registro de dirección propia, desde el log del kernel que lee el agente;
  • mikroscope-bridge-port-dark salta con un puerto del bridge que lleva diez minutos recibiendo sin que el bridge le envíe nada. Necesita el tier de API.

Véase Comprobaciones de salud y Reglas de alerta.

Revisa de forma explícita el log y el monitor de puertos de RouterOS; la respuesta decide dónde miras después:

/log/print where topics~"bridge" or topics~"stp" or topics~"interface"
/interface/bridge/port/monitor [find] once

Las dos volvieron limpias: cero filas de log en esos temas, todos los puertos designated-port / in-bridge. RouterOS no estaba ocultando el fallo; no muestra esta clase de sucesos del kernel.

Eso vale para el log y el monitor de puertos, no para todos los contadores que ofrece la API. Cuando el bucle volvió, del 2026-09-19 al 23, los contadores rx/tx por puerto que lee el tier de API sí lo mostraron, como un puerto del bridge que recibe mientras el bridge no le envía nada. Es la regla mikroscope-bridge-port-dark, contrastada con esos cuatro días. No se comprobó contra el episodio del 2026-09-12.

La línea que habría traído el tema interface es la que se busca cuando uno se topa con este fallo. RouterOS la ha escrito en su propio log, con los temas interface,warning, de esta forma:

<port>: bridge port received packet with own address as source address (<MAC>), probably loop

Esa forma sale del log de RouterOS de un usuario, publicado en el foro de MikroTik el 2017-12-10, con el puerto y la dirección sustituidos; qué versiones de RouterOS la siguen escribiendo no está establecido aquí. En el router de referencia, con RouterOS 7.24.2, no apareció ninguna línea así, mientras la del propio kernel, received packet on eth1 with own address, llegaba cada 2 s.

Además de STP, la defensa de RouterOS contra un bucle es Loop Protect, que envía sus propios paquetes por una interfaz, la desactiva cuando uno de ellos vuelve y lo deja en el log. La página de MikroTik recomienda (R/M)STP antes que Loop Protect en los puertos de un bridge. No intervino en este diagnóstico, y no se afirma que hubiera detectado este bucle.

Busca una segunda observación, independiente, fuera del log del kernel. La MAC del mensaje pertenecía a sfp-sfpplus1, lo que apuntaba al segmento SFP+; las propias tablas del bridge apuntaban a otro sitio. Cuenta los hosts aprendidos en cada puerto:

# hosts aprendidos por puerto
:foreach p in=[/interface/bridge/port/find] do={ \
:local n [/interface/bridge/port/get $p interface]; \
:put ($n . " hosts=" . [:len [/interface/bridge/host/find interface=$n]]) }
Puerto MAC aprendidas Tráfico edge de RSTP
sfp-sfpplus1 60 23,8 GB rx true
ether2 0 9,15 GB rx / 22,4 M paquetes false
el resto 0–2 — true

ether2 estaba pasando 22 millones de paquetes por un enlace sano de 1 Gbps y el bridge no había aprendido nada detrás de él, que es lo que hace un bridge en un puerto por el que no deja de ver sus propias direcciones. Era además el único puerto que recibía BPDU: las dos anomalías, en el mismo puerto.

El log del kernel había dicho eth1, no ether2: el kernel y RouterOS llaman de forma distinta al mismo puerto. Nombres de puertos relaciona unos con otros en un solo paso seguro, y explica por qué el agente lo hace por ti en esta placa.

La hipótesis: el equipo de ether2 tiene un segundo camino hasta el router a través de los otros AP, que cuelgan del switch. Primero se hicieron dos cambios en el switch, y ninguno movió la tasa:

Cambio Tasa de sucesos
línea base 1,49 /s
cambio en el switch 1 1,67 /s
cambio en el switch 2 1,47 /s
(banda de ruido) ±0,2 /s

Una lectura más de la misma serie, 1,50 /s, también quedó dentro de esa banda.

Eso descartó el switch con evidencia. Vuelve a medir después de cada cambio, incluso uno que esperas que funcione, y conoce tu banda de ruido antes de interpretar una diferencia.

Se actualizó el firmware de los AP de la malla (unidades Deco); el cableado no se tocó. Después:

events 9 -> 0.03/s (baseline 1.49/s)

y de esos nueve, ninguno era el mensaje del bucle: eran los AP volviendo (eth1: phy link up, eth1: set isolation from 0 to 1). El mensaje del bucle, que había aparecido cada 2 s (30 veces por minuto, rodeado del doble de registros de blocking/learning), apareció cero veces en 300 s.

Confirma con una segunda medida, independiente. Aquí la visión del bridge se volvió coherente:

Antes Después
MAC en ether2 0 24
MAC en sfp-sfpplus1 60 36
edge de ether2 false true

Los mismos 60 equipos, repartidos 36/24 en lugar de 60/0. Mientras existió el bucle, el router aprendía casi todos los equipos en el puerto equivocado; el coordinador Zigbee 00:4B:12:96:80:33, por ejemplo, pasó del SFP+ a ether2, donde está. Que encaje una segunda medida no relacionada es lo que hace de una corrección algo más que una coincidencia en el tiempo. Confirma que el fallo había desaparecido cuando se midió, no que siga sin aparecer: una semana después volvió.

La misma firma reapareció el 2026-09-19, con RouterOS 7.24.4, de nuevo un bucle de capa 2 por un segundo camino a través de un punto de acceso de la malla, y duró hasta que ese camino se cortó el 2026-09-23. Durante sus primeras 34 h el puerto al que el bridge había dejado de entregar tráfico fue sfp-sfpplus1, y después ether2 durante 62 h. Entre las 12:07 y las 18:55 UTC del 2026-09-21 y del 22, ether2 recibió 12 y 13 paquetes por segundo y envió 1; en esas mismas horas del 2026-09-23, tras desaparecer el segundo camino a las 12:06, recibió 192 y envió 178.

La segunda vez hubo dos diferencias:

  • Durante la mayor parte de la primera fase, los registros de dirección propia del log del kernel nombraban ether2, mientras que el puerto que recibía sin obtener nada de vuelta era sfp-sfpplus1: el mensaje nombra el puerto por el que entró la trama reflejada, no el puerto que el bucle había dejado aislado.
  • Los contadores por puerto de RouterOS sí lo mostraron, leídos como recepción sin transmisión. El contraste de mikroscope-bridge-port-dark con los datos del 2026-09-19 11:13 al 2026-09-23 22:44 UTC marca esos dos puertos en esos dos tramos y ningún otro.

El almacén InfluxDB de referencia guardó las dos mitades, y el gráfico de abajo sale de él, hora a hora: arriba los registros de dirección propia del kernel, y debajo lo que cada uno de los dos puertos recibió y se le envió. Mientras el puerto aislado era sfp-sfpplus1, los registros llegaban de pocos en pocos cada hora; en cuanto lo fue ether2, llegaban cada 2 s, como el 2026-09-12.

La vuelta del bucle, hora a hora Por horas, del 2026-09-19 11:00 al 2026-09-24 11:00 UTC, del almacén InfluxDB de referencia (RB5009UG+S+, RouterOS 7.24.4, Linux 5.6.3). Hasta el 2026-09-20 21:00 el kernel anotó como mucho 12 registros de dirección propia por hora, mientras el bridge no enviaba nada a sfp-sfpplus1 en ninguna hora y recibía 6,5 por segundo de él. Desde entonces y hasta el último registro, el 2026-09-23 12:06:46, registró una mediana de 1 798 por hora, uno cada 2,0 s, y el bridge envió a ether2 0,6 paquetes por segundo frente a 13 recibidos. Después, ether2 recibió 183 y se le enviaron 144. Las tasas son medianas de las medias horarias. RB5009UG+S+ · RouterOS 7.24.4 · Linux 5.6.3 · del 2026-09-19 11:00 al 2026-09-24 11:00 UTC por horas, del almacén InfluxDB de referencia sfp-sfpplus1 aislado ether2 aislado sin bucle Registros de dirección propia en el log del kernel, por hora como mucho 12 por hora antes del 09-20 21:00, después una mediana de 1 798 0 1 000 2 000 ether2: paquetes por segundo, media horaria, escala logarítmica recibidos enviados por el bridge ≤0,1 1 10 100 1 000 sfp-sfpplus1: paquetes por segundo, media horaria, escala logarítmica recibidos enviados por el bridge ≤0,1 1 10 100 1 000 09-20 09-21 09-22 09-23 09-24
La vuelta del bucle, hora a hora Por horas, del 2026-09-19 11:00 al 2026-09-24 11:00 UTC, del almacén InfluxDB de referencia (RB5009UG+S+, RouterOS 7.24.4, Linux 5.6.3). Hasta el 2026-09-20 21:00 el kernel anotó como mucho 12 registros de dirección propia por hora, mientras el bridge no enviaba nada a sfp-sfpplus1 en ninguna hora y recibía 6,5 por segundo de él. Desde entonces y hasta el último registro, el 2026-09-23 12:06:46, registró una mediana de 1 798 por hora, uno cada 2,0 s, y el bridge envió a ether2 0,6 paquetes por segundo frente a 13 recibidos. Después, ether2 recibió 183 y se le enviaron 144. Las tasas son medianas de las medias horarias. RB5009UG+S+ · RouterOS 7.24.4 · Linux 5.6.3 del 2026-09-19 11:00 al 2026-09-24 11:00 UTC por horas, del almacén InfluxDB de referencia sfp-sfpplus1 aislado ether2 aislado sin bucle Registros de dirección propia en el log del kernel, por hora como mucho 12 por hora antes del 09-20 21:00, después una mediana de 1 798 0 1 000 2 000 ether2: paquetes por segundo, media horaria, escala logarítmica recibidos enviados por el bridge ≤0,1 1 10 100 1 000 sfp-sfpplus1: paquetes por segundo, media horaria, escala logarítmica recibidos enviados por el bridge ≤0,1 1 10 100 1 000 09-20 09-21 09-22 09-23 09-24

Un fallo real, no provocado ·

  • Un flujo constante y periódico de events del kernel en reposo, donde el estado sano es cero.
  • received packet on <port> with own address as source address, con la propia MAC del router dentro.
  • El puerto de ese mensaje es por donde entró la trama reflejada, no necesariamente el puerto que el bucle ha dejado aislado. Del 2026-09-19 al 20 nombraba ether2 mientras sfp-sfpplus1 era el puerto que recibía y no enviaba nada. Compara el rx de cada puerto del bridge con su tx antes de desenchufar un cable.
  • Tiempos entre llegadas de 2,00–2,01 s: el hello interval de STP.
  • Un puerto con mucho tráfico en el que el bridge no ha aprendido ningún host, con edge=false mientras sus vecinos están a true.
  • /log/print y /interface/bridge/port/monitor, ambos limpios.
  • Un texto alarmante es una pista; una tasa es evidencia; una tasa antes y después es una conclusión.
  • Lee los tiempos entre llegadas. A menudo te nombran el protocolo.
  • Prefiere un cambio que discrimine entre hipótesis a un cambio que tal vez lo arregle.
  • Desconfía de una corrección que solo tu instrumento principal puede confirmar.
  • Sigue vigilando después de la corrección. Una corrección confirmada dice que el fallo no estaba cuando mediste, y este volvió una semana después.