Nombres de puertos
El log del kernel nombra netdevs (eth0, eth5), RouterOS nombra interfaces
(ether1, sfp-sfpplus1) y no coinciden: eth1 en el log no es ether1.
Relaciona un registro del log del kernel con el cable al que se refiere, como
tuvo que hacer el caso del bucle.
Por qué difieren los nombres
Sección titulada «Por qué difieren los nombres»RouterOS no expone ninguna correspondencia, y el contenedor no puede leer una.
Los dispositivos de red están en su namespace, así que /sys/class/net dentro
del contenedor solo muestra lo y la veth, y /sys/class/mdio_bus y
/sys/class/phy tampoco nombran ningún puerto. privileged=yes no cambia eso
(comprobado). Los nombres de RouterOS
viven en la configuración de RouterOS, no en el kernel.
Medir la correspondencia
Sección titulada «Medir la correspondencia»Apaga y enciende un puerto que no lleve nada y lee el nombre que escribe el kernel. Es un paso seguro: un puerto muerto no interrumpe ningún tráfico.
-
Busca un puerto realmente muerto, con cero paquetes en ambos sentidos en toda su vida:
/interface/print stats where name="ether6" or name="ether7" -
Con el agente en marcha, apágalo y enciéndelo:
/interface/ethernet/disable [find name="ether6"]:delay 4s/interface/ethernet/enable [find name="ether6"] -
Lee los registros del kernel de ese momento. Nombran el netdev:
[6] br0: port 7(eth5) entered blocking state[4] eth5: set isolation from 0 to 1[4] eth5: set isolation from 1 to 0Aquí
ether6de RouterOS eseth5del kernel. -
Repítelo en un segundo puerto muerto.
ether7dioeth6: un desfase de −1, visto en dos puntos.
Correspondencias conocidas
Sección titulada «Correspondencias conocidas»La tabla del agente usa como clave la cadena exacta de
/proc/device-tree/model. En la placa de abajo la correspondencia es un
desplazamiento de uno — RouterOS numera los puertos desde 1 y el kernel desde 0,
chip del switch incluido (switch0 es el switch=switch1 que declaran todos
los puertos):
Placa (/proc/device-tree/model) |
RouterOS | kernel | cómo se sabe |
|---|---|---|---|
RB5009 |
ether1 |
eth0 |
deducido |
RB5009 |
ether2 |
eth1 |
medido — el bucle del caso de estudio |
RB5009 |
ether3 … ether5 |
eth2 … eth4 |
deducido |
RB5009 |
ether6 |
eth5 |
medido — apagado y encendido |
RB5009 |
ether7 |
eth6 |
medido — apagado y encendido |
RB5009 |
ether8 |
eth7 |
deducido |
RB5009 |
sfp-sfpplus1 |
eth8 |
deducido, el último de la enumeración |
RB5009 |
switch1 |
switch0 |
deducido |
Desliza en horizontal para ver todas las columnas
Se midieron tres pares, todos con el mismo desplazamiento de uno; los seis
puertos deducidos y el switch se apoyan en él
(cómo se midió cada par). Los pares
deducidos se apoyan en dos observaciones de un /interface/ de
solo lectura: los nueve puertos llevan direcciones MAC consecutivas, de …:55
para ether1 a …:5D para sfp-sfpplus1, en el orden de enumeración del
propio RouterOS; y los nueve declaran switch=switch1 frente al único switch0
del kernel.
Una correspondencia vale solo para su propia placa. El desplazamiento de uno, la
posición de la jaula SFP+ y la reutilización de port 7 no se afirman para
ninguna otra placa, y el agente no los aplica a ninguna
(no probado en otras).
Advertencias
Sección titulada «Advertencias»- El nombre es fiable; el número de puerto del bridge, no. Los dos apagados
dieron
port 7, porque el kernel reutiliza las posiciones de puerto cuando un puerto sale del bridge y vuelve a entrar. Compara coneth5, nunca conport 7. - El desfase es una propiedad del driver de este modelo, no una regla. Vuelve a
medirlo en otro equipo en lugar de suponerlo, y ten cuidado con la intuición de
que el SFP+ tiene que ser
eth0— aquí es el último, no el primero. El device tree tampoco ayuda: muestra elethernet@0del SoC con tres MAC, soloeth0habilitada (el enlace de subida de 10 G) yeth1/eth2deshabilitadas, mientras que los nueve puertos del frontal son netdevs que el driver del switch crea en tiempo de ejecución. Los nombres del log del kernel son los de tiempo de ejecución.
Cómo la usa el agente
Sección titulada «Cómo la usa el agente»El agente lee el modelo de placa de /proc/device-tree/model al arrancar, cosa
que funciona incluso sin privilegios, y, en una placa que está en su tabla,
nombra los puertos sin preguntar a RouterOS:
- todo registro del log del kernel cuyo texto nombra un puerto lleva los dos
nombres y lo que le ha pasado a ese puerto:
iface,ros_ifaceykinden el suceso, etiquetasportykinden las filas de InfluxDB eiface=eth1 ros_iface=ether2 port_en una línea de Loki;event=own-address - el
/metricsdel colector lleva la familiamikroscope_, construida a partir de esos registros, con el nombre de RouterOS comokmsg_ port_ records_ total{port, kind, level} porten una placa que está en la tabla, el nombre del kernel en una placa que no lo está, y ninguna serie de puerto en un equipo cuyo device tree no declara modelo. Es un subconjunto demikroscope_, no una partición: los registros que no nombran ningún puerto no aparecen en él;kmsg_ records_ total - la detección
link-flapdel colector usa el nombre de puerto como clave y lee esa misma clasificación: un parpadeo son registroslink-upylink-downde un puerto, contados, con el mismo clasificador y no releyendo el texto; mikroscope statusmuestra la placa y si tiene correspondencia, por ejemploeth1 (ether2);/healthzy/capabilitiesllevan la placa, y/capabilitiesymikroscope_device_infollevan la cadena de evidencia de la tabla comoports_from, para que nadie tenga que fiarse de la correspondencia a ciegas.
mikroscope doctor, que es la CLI y no el agente, lee esos mismos registros del
anillo del agente en marcha: el anillo entero cuando no guarda más de 10 000 muestras, y si
no las 10 000 más recientes; 60 s por defecto (el BUFFER_S del agente).
Vuelve a clasificar cada registro del log del kernel a partir de su texto, con la
placa que el agente declara en /healthz, en lugar de fiarse del kind del
agente: de lo contrario, un agente que envía registros sin él haría pasar todas
las comprobaciones de puerto sin decir nada. En un equipo cuyo device tree no
declara modelo también clasifica, y nombra el puerto del kernel. Por cada puerto
de RouterOS informa de layer2-loop con tres o más registros own-address en
la ventana, de stp-churn cuando el puerto entró en learning al menos tres veces
más de las que llegó a forwarding, y de link-flap con dos o más registros
link-down; softnet-drops se informa por CPU, no por puerto.
Una placa desconocida no recibe nombres de puerto, ni siquiera adivinados. El
desplazamiento de uno no se aplica a una placa que nadie ha medido, porque un
nombre de puerto equivocado señala el cable equivocado. En una placa así, status lo dice y pide el par: baja un puerto,
mira qué ethN nombra el log y envía ese par junto con la cadena de la placa
en un informe de placa.
Clases de suceso
Sección titulada «Clases de suceso»El nombre del puerto por sí solo no dice qué le ha pasado, así que todo registro
que nombra uno se clasifica también, con procfs.KmsgKind sobre el texto del
registro. Las clases, y los registros que escribe un kernel de RouterOS para
cada una (dónde se vieron):
kind |
el registro |
|---|---|
link-up |
eth8: link up, 1Gbps, full-duplex, eth1: Link is Up - 1Gbps/Full, eth1: phy link up |
link-down |
eth1: link down |
stp-<state> |
br0: port 2(eth1) entered blocking state — blocking, listening, learning, forwarding, disabled |
own-address |
br0: received packet on eth1 with own address as source address (addr:…, vlan:0) — la firma del bucle de nivel 2 |
other |
cualquier otra cosa que nombre un puerto, incluido eth1: link becomes ready, que es la configuración de direcciones IPv6 dándose cuenta de la portadora y no una transición propia |
Desliza en horizontal para ver todas las columnas
El agente clasifica en el momento de leer y envía kind dentro del registro. Un
colector que tiene delante un agente cuyos registros no lo llevan los clasifica
él mismo, con la misma función.
Cuatro registros no son cuatro fallos. A un link-up normal le siguen
stp-blocking, stp-learning y stp-forwarding mientras el bridge devuelve el
puerto al servicio.
Puertos renombrados
Sección titulada «Puertos renombrados»La tabla corresponde a los nombres por defecto de RouterOS. Un puerto
renombrado en el router (ether5 → WAN) tiene un nombre que la tabla no puede
conocer, así que el colector se lo pregunta a la capa de la API. Su inventario de
interfaces —leído una vez antes del primer sondeo del kernel y otra vez cada
--labels-every, cinco minutos por defecto— guarda de cada interfaz su nombre de
fábrica, su nombre actual, su comentario y sus listas de interfaces, y el colector
lo usa en cada registro que nombra un puerto para:
- sustituir el nombre por defecto por el actual, de modo que quien haya
renombrado
ether5comoWANleaWANen el suceso, en la etiquetaportde InfluxDB, en la línea de Loki y en la clave delink-flap; - añadir
label, el comentario del puerto, yrole, sus listas de interfaces — así el parpadeo deeth5llega comoether6, etiquetaUnused, y no como un número de netdev que alguien tiene que buscar.
Sin capa de la API el registro se queda con el nombre por defecto de la placa y sin etiqueta, que es lo que puede sostener.
Sucesos de puerto en dashboards
Sección titulada «Sucesos de puerto en dashboards»Dos paneles de la fila Kernel log de los dashboards son donde se juntan el nombre, la clase y el comentario:
- Port events from the kernel log, per port and kind — barras por intervalo,
una serie por puerto y clase, con
sum by (port, kind) (increase(mikroscope_en Prometheus y con las etiquetaskmsg_ port_ records_ total[$__ interval])) port/kinden InfluxDB; - Port events in the window, per port — una tabla con una fila por puerto que
el log haya nombrado: el puerto, su
labely surole, y una columna por clase (link down, link up, own address (loop), STP blocking, STP disabled, STP learning, STP forwarding, other).
Los dos son paneles que se sabe que pueden salir vacíos —un conjunto de puertos
callado es el estado sano— y la forma de Prometheus de cada uno lee el /metrics
del colector, cuya copia de la familia lleva un kind en todo registro de puerto
venga como venga del agente. En un almacén InfluxDB la
columna kind no existe hasta que se escribe el primer registro de puerto
clasificado por clase; hasta entonces, las dos consultas de InfluxDB fallan al
planificarse.
Junto a ellos se publican dos reglas de alerta, en los ficheros de
aprovisionamiento de InfluxDB y Prometheus; el de PostgreSQL no tiene ninguna,
porque ese almacén guarda cada registro del log del kernel como una fila y no
como un recuento. Las dos leen /dev/kmsg a través del agente y no preguntan
nada a RouterOS:
mikroscope-l2-loop, crítica: cualquier registroown-addressen cinco minutos. Esa firma puede correr durante horas mientras todos los contadores de RouterOS parecen sanos, como en el caso del bucle.mikroscope-port-link-down, aviso: cualquier registrolink-downen cinco minutos — el suceso suelto, ya que de las repeticiones se ocupalink-flap.
La forma de InfluxDB de cada una necesita un almacén que ya haya guardado un registro de puerto clasificado por clase; antes de eso la consulta falla al planificarse.
Las dos tienen umbral 0 con gt. Las consultas de InfluxDB de las dos reglas
devuelven un valor de disparo sobre registros que un router escribió de verdad
(comprobado). Que una regla pase a
pendiente, salte y se resuelva en la evaluación de Grafana no está probado
(Probado en), que es el hueco que
señala Reglas de alerta.