# Nombres de puertos

El log del kernel dice eth5 donde RouterOS dice ether6: mide la correspondencia en un puerto muerto, consulta las correspondencias conocidas y mira cómo las usan el agente, el colector y los dashboards.

Source: https://docs.jmrp.io/mikroscope/es/reference/port-names/

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](https://docs.jmrp.io/mikroscope/es/playbooks/loop/).

## 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](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-netns-2026-09-12)). Los nombres de RouterOS
viven en la configuración de RouterOS, no en el kernel.

## 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.

1. Busca un puerto realmente muerto, con cero paquetes en ambos sentidos en toda
   su vida:

   ```routeros
   /interface/print stats where name="ether6" or name="ether7"
   ```

2. Con el agente en marcha, apágalo y enciéndelo:

   ```routeros
   /interface/ethernet/disable [find name="ether6"]
   :delay 4s
   /interface/ethernet/enable  [find name="ether6"]
   ```

3. Lee los registros del kernel de ese momento. Nombran el netdev:

   ```text
   [6] br0: port 7(eth5) entered blocking state
   [4] eth5: set isolation from 0 to 1
   [4] eth5: set isolation from 1 to 0
   ```

   Aquí `ether6` de RouterOS es `eth5` del kernel.

4. Repítelo en un segundo puerto muerto. `ether7` dio `eth6`: un **desfase de
   −1**, visto en dos puntos.

## 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                              |

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](https://docs.jmrp.io/mikroscope/es/about/status/#reference-hardware)). Los pares
deducidos se apoyan en dos observaciones de un `/interface/ethernet/print` 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](https://docs.jmrp.io/mikroscope/es/about/status/#not-tested)).

## 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 con `eth5`, nunca con
  `port 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 el `ethernet@0` del SoC con tres MAC, solo `eth0`
  habilitada (el enlace de subida de 10 G) y `eth1`/`eth2` deshabilitadas,
  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

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_iface` y `kind` en el
  suceso, etiquetas `port` y `kind` en las filas de InfluxDB e
  `iface=eth1 ros_iface=ether2 port_event=own-address` en una línea de Loki;
- el `/metrics` del colector lleva la familia
  `mikroscope_kmsg_port_records_total{port,kind,level}`, construida a partir de
  esos registros, con el nombre de RouterOS como `port` en 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 de
  `mikroscope_kmsg_records_total`, no una partición: los registros que no nombran
  ningún puerto no aparecen en él;
- la detección `link-flap` del colector usa el nombre de puerto como clave y lee
  esa misma clasificación: un parpadeo son registros `link-up` y `link-down` de un
  puerto, contados, con el mismo clasificador y no releyendo el texto;
- `mikroscope status` muestra la placa y si tiene correspondencia, por ejemplo
  `eth1 (ether2)`; `/healthz` y `/capabilities` llevan la placa, y
  `/capabilities` y `mikroscope_device_info` llevan la cadena de evidencia de la
  tabla como `ports_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](https://github.com/jmrplens/mikroscope/issues/new?template=2-board-report.yml).

## 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](https://docs.jmrp.io/mikroscope/es/about/status/#reference-hardware)):

| `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 |

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

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 `ether5` como `WAN` lea `WAN` en el suceso, en la etiqueta `port` de
  InfluxDB, en la línea de Loki y en la clave de `link-flap`;
- añadir `label`, el comentario del puerto, y `role`, sus listas de interfaces —
  así el parpadeo de `eth5` llega como `ether6`, etiqueta `Unused`, 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

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_kmsg_port_records_total[$__interval]))`
  en Prometheus y con las etiquetas `port`/`kind` en InfluxDB;
- **Port events in the window, per port** — una tabla con una fila por puerto que
  el log haya nombrado: el puerto, su `label` y su `role`, 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 registro `own-address` en cinco
  minutos. Esa firma puede correr durante horas mientras todos los contadores de
  RouterOS parecen sanos, como en [el caso del bucle](https://docs.jmrp.io/mikroscope/es/playbooks/loop/).
- `mikroscope-port-link-down`, aviso: cualquier registro `link-down` en cinco
  minutos — el suceso suelto, ya que de las repeticiones se ocupa `link-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](https://docs.jmrp.io/mikroscope/es/about/status/#qué-funciona-de-extremo-a-extremo)). Que una regla pase a
pendiente, salte y se resuelva en la evaluación de Grafana no está probado
([Probado en](https://docs.jmrp.io/mikroscope/es/about/status/#not-tested)), que es el hueco que
señala [Reglas de alerta](https://docs.jmrp.io/mikroscope/es/dashboards/alerts/).

## Véase también

- [Bucle de capa 2](https://docs.jmrp.io/mikroscope/es/playbooks/loop/): el fallo que hizo que mereciera la pena medir
  esta correspondencia.
- [Datos del equipo](https://docs.jmrp.io/mikroscope/es/sinks/device-info/): por dónde viajan la placa y
  `ports_from`.
- [Reglas de detección](https://docs.jmrp.io/mikroscope/es/sinks/detections/): la regla `link-flap`, que usa estos nombres como
  clave.
- [Capa de la API de RouterOS](https://docs.jmrp.io/mikroscope/es/sinks/api-tier/): el inventario de interfaces que
  convierte un nombre por defecto en el actual, con su comentario y sus listas.
- [Reglas de alerta](https://docs.jmrp.io/mikroscope/es/dashboards/alerts/): las reglas de bucle y de caída de enlace que
  disparan estos registros.
