La pérdida de paquetes intermitente es el peor tipo de incidencia: evade las gráficas, se oculta durante las llamadas de incidente y solo aparece cuando el CEO se une al vídeo de la reunión general. El equipo de aplicaciones dice “la red”. El equipo de red dice “los servidores”. Alguien sugiere reiniciar “solo para arreglarlo”.
Aquí tienes el flujo de trabajo de producción que acaba con la discusión: demuestras dónde se están perdiendo los paquetes, usando contadores específicos de Linux y capturas, y luego solucionas el cuello de botella que realmente causa la pérdida. No teorías. Evidencia.
Un modelo mental implacable: dónde ocurren las pérdidas
“Pérdida de paquetes” es un síntoma, no una ubicación. Un paquete puede perderse en muchos sitios, y Linux te da contadores para la mayoría de ellos. El truco está en saber qué contadores están adyacentes al dominio de pérdida que estás investigando.
Piense en dominios de pérdida, no en herramientas
Cuando la gente se atasca, suele elegir una herramienta (ping, traceroute, tcpdump) y seguir ejecutándola más fuerte. Las herramientas están bien. Pero el flujo correcto es: identifica el dominio y luego elige el conjunto mínimo de herramientas para probarlo.
Dominios de pérdida comunes en un sistema Linux de producción:
- Pérdidas remotas: el paquete sale correctamente de tu host, pero muere en otro sitio (switch, router, firewall, cola de entrada del host remoto, CPU remota, política remota).
- Problemas a nivel de enlace: cableado, óptica, inestabilidades, FEC, errores PCS. Esto es “físico”, pero aparece como contadores MAC/PHY y a veces logs del controlador.
- Pérdidas en la ruta de recepción del NIC: desbordamiento del ring buffer, agotamiento de descriptores, bugs del driver o interacciones con offloads.
- Pérdidas en el backlog del kernel: NAPI/softirq backlog (la clásica historia de
softnet_stat), agotamiento de CPU, enrutamiento de interrupciones. - Netfilter/conntrack: presión en la tabla de estados, estados inválidos, timeouts agresivos o reglas que descartan bajo carga.
- qdisc/control de tráfico: shaping/policing, comportamiento de fq_codel o una qdisc bienintencionada que descarta silenciosamente.
- Pérdidas a nivel de socket: la aplicación no lee, buffer de recepción demasiado pequeño, overflow de cola de accept, problemas con backlog de SYN.
- Virtualización/overlay: colas veth, descartes en bridge, overhead VXLAN/Geneve, desajuste de MTU por encapsulación.
- “Pérdida de red” causada por almacenamiento: no es broma. Si la app se bloquea por disco, deja de leer sockets y verás “pérdidas” como retransmisiones y timeouts.
El objetivo no es recopilar cada métrica conocida por la humanidad. El objetivo es correlacionar un síntoma observado (retransmisiones, huecos, latencia cola, timeouts) con un contador específico que aumente en un lugar.
Dos tipos de “solo a veces”
La pérdida intermitente suele caer en uno de dos patrones:
- Pérdidas en ráfagas (microbursts): todo está bien hasta que no lo está, y entonces una pequeña cola se desborda. Las gráficas parecen limpias porque los promedios ocultan los picos.
- Pérdidas condicionales: solo cierto tráfico se ve afectado (cierto MTU, DSCP, flujos hasheados a un miembro LACP defectuoso, una IRQ fijada a una CPU ocupada, un bucket de conntrack bajo ataque).
Si no distingues esto, depurarás lo equivocado durante días. Las pérdidas en ráfagas exigen trabajo sobre colas/capacidad. Las pérdidas condicionales exigen inspección por flujo, hashing, MTU y políticas.
Una cita para poner en una nota adhesiva: “La esperanza no es una estrategia.”
— idea parafraseada atribuida a muchos líderes de ingeniería en cultura de operaciones.
Broma #1: La pérdida de paquetes es como un niño pequeño con un rotulador. Si no lo atrapas en el acto, todo lo que obtienes es una pared llena de “eh, qué raro”.
Guía rápida de diagnóstico (primero/segundo/tercero)
Este es el orden de triaje que te lleva rápidamente al cuello de botella, incluso cuando el problema es intermitente y tus dashboards mienten por promediar.
Primero: demuestra si la pérdida es local o remota
- Comprueba las retransmisiones TCP y los contadores de drops del kernel en el host afectado. Si las retransmisiones suben pero las pérdidas locales RX/TX no, sospecha de upstream, remoto o middleboxes.
- Captura en ambos lados de un límite de interfaz. Por ejemplo: captura en
eth0y enbond0, o eneth0y dentro del namespace. Si el paquete aparece en un lado y no en el otro, encontraste el límite de la caída. - Compara los contadores de error en NIC/PHY. CRC, FCS, errores de símbolo e inestabilidades de enlace no son “problemas de la app”.
Segundo: revisa las tres colas que más se desbordan
- Ring RX del NIC / drops del driver:
ethtool -Ssuele mostrar “missed”, “no_buffer”, “rx_missed_errors”, etc. - Backlog del kernel: los drops en
/proc/net/softnet_statson la prueba evidente de starving de CPU/softirq. - qdisc:
tc -s qdiscmuestra drops en la cola de salida; el policing también aparece como drops.
Tercero: aísla los patrones condicionales
- MTU/fragmentación: revisa PMTUD blackholes, overhead de overlays y filtrado de ICMP.
- Hashing/LACP: ¿tiene errores un miembro? ¿Algún path tiene enrutamiento asimétrico o policing?
- conntrack: tabla llena o churn; las pérdidas aparecen “solo en picos”.
- IRQ/afinidad de CPU: un núcleo ocupado manejando todas las interrupciones RX implica pérdidas intermitentes bajo carga.
Si haces esto en orden, dejas de adivinar. También dejas de “arreglar” cosas que no estaban rotas.
Datos interesantes y contexto histórico
- Ethernet siempre ha perdido tramas bajo congestión; el Ethernet compartido temprano dependía de detección de colisiones. Las redes conmutadas modernas trasladaron el dolor a buffers y colas.
- Linux NAPI se introdujo para reducir tormentas de interrupciones cambiando a polling bajo carga; por eso el tiempo de CPU en softirq importa tanto en NICs ocupadas.
- Bufferbloat se volvió un término común a finales de los 2000; los buffers grandes reducen pérdidas pero pueden destruir la latencia. Ese trade-off sigue vivo en tu NIC y switch.
- El control de congestión TCP asume que la pérdida significa congestión. Cuando la pérdida es causada por óptica mala o una cola rota, TCP aun así reduce la ventana y tu app “misteriosamente se ralentiza”.
- Los offloads GRO/LRO se crearon para reducir la carga de CPU agrupando paquetes, pero pueden complicar capturas y análisis de temporización.
- fq_codel y qdiscs relacionadas se popularizaron porque combaten la latencia bajo carga gestionando colas mejor que FIFO.
- Conntrack existe porque los firewalls stateful y NAT necesitaban tracking; a escala, conntrack se convierte en un recurso kernel compartido que puede fallar como una base de datos.
- RSS/RPS/XPS (Receive/Transmit packet steering) son décadas de trabajo acumulado para mantener alimentadas las CPUs multinúcleo; una mala configuración aún causa “un núcleo se derrite y los paquetes se pierden”.
- Jumbo frames no son nuevos, pero los overlays hicieron los errores de MTU más probables: el overhead VXLAN/Geneve convierte “funciona en laboratorio” en “cae solo para cargas grandes”.
Tareas prácticas: comandos, salidas, decisiones
A continuación hay tareas reales que puedes ejecutar durante un incidente. Cada una incluye: comando, qué significa la salida y qué decisión tomar a partir de ella. Ejecútalas en ambos extremos cuando puedas. Si solo las ejecutas en un host, aún aprenderás mucho, pero no lo suficiente para ganar debates.
Tarea 1: Confirma que el síntoma es real (y qué protocolo lo muestra)
cr0x@server:~$ ping -c 20 -i 0.2 -s 56 10.10.5.20
PING 10.10.5.20 (10.10.5.20) 56(84) bytes of data.
64 bytes from 10.10.5.20: icmp_seq=1 ttl=62 time=0.611 ms
64 bytes from 10.10.5.20: icmp_seq=2 ttl=62 time=0.623 ms
Request timeout for icmp_seq 7
64 bytes from 10.10.5.20: icmp_seq=8 ttl=62 time=0.640 ms
--- 10.10.5.20 ping statistics ---
20 packets transmitted, 19 received, 5% packet loss, time 3805ms
rtt min/avg/max/mdev = 0.611/0.655/0.812/0.052 ms
Significado: Existe pérdida ICMP, pero ICMP puede ser despriorizado o rate-limited por dispositivos. No concluyas “la red está rota” solo por ping.
Decisión: Comprueba inmediatamente señales a nivel TCP (retransmisiones) para las cargas reales. Si solo ICMP cae, sospecha de policing/limitación de tasa.
Tarea 2: Revisa retransmisiones TCP y resets en el host
cr0x@server:~$ netstat -s | egrep -i 'retran|reset|timeout' | head
1823 segments retransmitted
17 bad segments received
42 resets received for embryonic SYN_RECV sockets
9 connections reset due to unexpected data
Significado: Las retransmisiones indican pérdida en algún punto del camino (o reordenamiento tan severo que parece pérdida). Los resets en SYN_RECV sugieren presión en el backlog o problemas en el manejo de SYN.
Decisión: Si las retransmisiones suben durante la ventana del incidente, trátalo como pérdida real de paquetes o jitter extremo. Pasa a contadores y capturas.
Tarea 3: Identifica la ruta y si PMTUD debería funcionar
cr0x@server:~$ ip route get 10.10.5.20
10.10.5.20 via 10.10.4.1 dev eth0 src 10.10.4.55 uid 0
cache
Significado: Ahora sabes la interfaz de salida y el siguiente salto. Esto es tu ancla para cada contador y captura subsiguiente.
Decisión: Ejecuta estadísticas a nivel de interfaz en eth0. Si la ruta cambia durante el problema (ECMP), tendrás que correlacionar comportamiento por camino.
Tarea 4: Revisa estado del enlace, velocidad/duplex y problemas físicos obvios
cr0x@server:~$ ethtool eth0
Settings for eth0:
Supported ports: [ FIBRE ]
Supported link modes: 10000baseSR/Full
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: off
Link detected: yes
Significado: El enlace está arriba a la velocidad esperada. Eso no descarta la óptica o el cable, pero quita de la lista “mismatch de duplex” y “en realidad es 1G”.
Decisión: Si el enlace está flapeando o negociando a una tasa inesperada, detente y arregla lo físico. Si parece estable, avanza a contadores de error.
Tarea 5: Lee contadores NIC/driver para drops y errores RX/TX
cr0x@server:~$ ethtool -S eth0 | egrep -i 'drop|error|miss|no_buffer|timeout' | head -n 20
rx_missed_errors: 1249
rx_no_buffer_count: 1180
rx_errors: 0
tx_errors: 0
tx_timeout_count: 0
Significado: rx_missed_errors / rx_no_buffer_count usualmente significa que la NIC no pudo pasar paquetes al kernel lo suficientemente rápido (agotamiento de ring, starving de CPU, o problemas del driver). Eso es pérdida local.
Decisión: Si estos aumentan durante el incidente, estás viendo presión en la ruta de recepción. Pasa a softnet stats, distribución de IRQ y tamaños de ring.
Tarea 6: Revisa drops genéricos de la interfaz (menos precisos, aún útiles)
cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 3c:fd:fe:aa:bb:cc brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
9132299123 9023123 0 431 0 12213
TX: bytes packets errors dropped carrier collsns
8023312288 8112231 0 0 0 0
Significado: El campo dropped es un agregado grueso; puede incluir drops a nivel kernel, no estrictamente drops del NIC. Aun así: si crece con tu problema, es una gran pista.
Decisión: Si RX dropped crece pero ethtool -S no muestra misses, sospecha backlog del kernel, netfilter o capas de qdisc/virtualización.
Tarea 7: Revisa drops en backlog del kernel con softnet_stat
cr0x@server:~$ awk '{d+=$2; t+=$1} END{print "total_processed="t, "total_dropped="d}' /proc/net/softnet_stat
total_processed=140338812 total_dropped=92841
Significado: La segunda columna son los paquetes descartados en el backlog por CPU. Si ese número aumenta rápidamente durante el incidente, el kernel está descartando antes de que el paquete llegue a tu socket.
Decisión: Revisa saturación de CPU, afinidad de interrupciones y si tu NIC está alimentando un solo core. Arreglar lo físico no ayudará; necesitas corregir CPU/interrupciones/colas.
Tarea 8: Identifica si las IRQs están concentradas en una CPU
cr0x@server:~$ grep -E 'eth0|mlx|ixgbe|i40e' /proc/interrupts | head
86: 9833221 12 4 9 IR-PCI-MSI 524288-edge eth0-TxRx-0
87: 31 9123312 8 11 IR-PCI-MSI 524289-edge eth0-TxRx-1
88: 25 18 9011123 13 IR-PCI-MSI 524290-edge eth0-TxRx-2
89: 22 15 10 8832212 IR-PCI-MSI 524291-edge eth0-TxRx-3
Significado: Si una línea IRQ tiene casi todas las interrupciones en una CPU, obtendrás drops locales bajo carga. La distribución uniforme es el objetivo, pero “uniforme” depende de NUMA y la carga.
Decisión: Si hay sesgo, ajusta la afinidad de IRQ (con cuidado), habilita/verifica RSS y confirma RPS/XPS donde proceda.
Tarea 9: Revisa tiempo de CPU en softirq (procesamiento de red)
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0-18-generic (server) 02/04/2026 _x86_64_ (32 CPU)
02:18:11 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
02:18:12 PM all 8.2 0.0 6.1 0.2 0.0 14.9 0.0 0.0 0.0 70.6
02:18:12 PM 7 3.1 0.0 5.9 0.0 0.0 62.2 0.0 0.0 0.0 28.8
Significado: Un core con %soft extremadamente alto sugiere que está ahogado en procesamiento de paquetes. Eso se correlaciona fuertemente con drops en softnet_stat.
Decisión: Redistribuye interrupciones, verifica el número de colas RSS, reduce el overhead por paquete (los offloads pueden ayudar) o escala el tráfico.
Tarea 10: Inspecciona drops y backlog en qdisc de salida
cr0x@server:~$ tc -s qdisc show dev eth0
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
Sent 8122331123 bytes 8112231 pkt (dropped 3312, overlimits 0 requeues 12)
backlog 0b 0p requeues 12
maxpacket 1514 drop_overlimit 3312 new_flow_count 4012 ecn_mark 0
Significado: Los drops aquí son drops en la cola de salida del host. Eso no es “la red”; es tu servidor decidiendo que no puede encolar más paquetes.
Decisión: Determina por qué el host está congestionado en egress: shaping/policing, límite de qdisc demasiado pequeño o la NIC no puede transmitir lo suficientemente rápido (o está bloqueada por flow control).
Tarea 11: Detecta desajuste de MTU y PMTUD blackholes
cr0x@server:~$ ping -M do -s 1472 -c 3 10.10.5.20
PING 10.10.5.20 (10.10.5.20) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
--- 10.10.5.20 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2025ms
Significado: La MTU de esta interfaz es 1500, y estás intentando enviar un paquete de 1500 bytes con DF activado. El error es local y esperado.
Decisión: Ahora haz la misma prueba con la carga útil máxima esperada para tu overlay o configuración jumbo. Si algún camino no puede pasarla y ICMP está filtrado, obtienes “pérdida solo para paquetes grandes”.
Tarea 12: Confirma offloads y entiende rarezas de capturas
cr0x@server:~$ ethtool -k eth0 | egrep -i 'gro|gso|tso|lro|rx-checksumming|tx-checksumming'
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
Significado: Con GRO/GSO/TSO activados, las capturas pueden mostrar “paquetes gigantes” o patrones extraños de segmentación. Eso no significa que los jumbo frames estén activados; significa que el kernel está optimizando.
Decisión: No desactives los offloads como primer recurso. Si debes probarlo, hazlo temporalmente y solo después de capturar contadores base. Desactivar offloads puede aumentar la CPU y crear pérdida.
Tarea 13: Captura en el lugar y momento adecuados (y mantenla pequeña)
cr0x@server:~$ sudo tcpdump -i eth0 -nn -s 96 -w /tmp/edge.pcap 'host 10.10.5.20 and (tcp or icmp)' -c 20000
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 96 bytes
20000 packets captured
20000 packets received by filter
0 packets dropped by kernel
Significado: “0 packets dropped by kernel” significa que tu proceso de captura pudo seguir el ritmo. Bien. Si tcpdump descarta paquetes, tu captura deja de ser confiable para análisis de microbursts.
Decisión: Si ves pérdida en la app pero tcpdump no muestra huecos en egress, probablemente tengas pérdidas remotas o problemas en la ruta de retorno. Captura también en el receptor.
Tarea 14: Usa ss para revisar presión en sockets (accept queue, rmem/wmem)
cr0x@server:~$ ss -s
Total: 1789 (kernel 0)
TCP: 912 (estab 501, closed 330, orphaned 0, timewait 309/0), ports 0
Transport Total IP IPv6
RAW 0 0 0
UDP 71 60 11
TCP 582 421 161
INET 653 481 172
FRAG 0 0 0
Significado: Esta vista es de sanity. Para diagnóstico más profundo, inspecciona listeners específicos y sus colas.
cr0x@server:~$ ss -lntp | head
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 512 4096 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1412,fd=8))
LISTEN 128 128 127.0.0.1:9100 0.0.0.0:* users:(("node_exporter",pid=1201,fd=3))
Significado: Recv-Q en un listener es el backlog de conexiones pendientes; si está consistentemente en o cerca de Send-Q (el backlog configurado), estás perdiendo SYNs o el accept está atascado.
Decisión: Si tu listener está saturado, la pérdida de paquetes puede ser un subproducto (reintentos/timeouts) en lugar de una pérdida de red verdadera. Arregla la tasa de accept de la aplicación, ajusta backlog o escala.
Tarea 15: Revisa saturación de conntrack (entornos con firewall/NAT stateful)
cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 252118
net.netfilter.nf_conntrack_max = 262144
Significado: Estás cerca del límite. Cuando conntrack está lleno, las conexiones nuevas pueden fallar de formas que parecen pérdida de paquetes (los SYNs desaparecen, los reintentos ocurren, los clientes hacen timeout).
Decisión: Si estás cerca del máximo durante incidentes, aumenta el límite (y la memoria), reduce el churn o deja de rastrear flujos que no necesitan tracking.
Tarea 16: Encuentra retransmisiones por conexión (deja de culpar a toda la red)
cr0x@server:~$ ss -ti dst 10.10.5.20 | head -n 30
ESTAB 0 0 10.10.4.55:48216 10.10.5.20:443
cubic wscale:7,7 rto:204 rtt:4.2/0.8 ato:40 mss:1460 pmtu:1500 rcvmss:1460 advmss:1460 cwnd:10 bytes_sent:88212 bytes_acked:88120 bytes_received:112233 segs_out:712 segs_in:690 data_segs_out:502 retrans:7/23 lost:0 sacked:8
Significado: Esta conexión está retransmitiendo. Ahora puedes preguntar “¿qué tiene de especial este flujo?” en lugar de discutir sobre todo el tejido.
Decisión: Compara flujos afectados vs no afectados: destino, DSCP, puerto, MTU, camino (ECMP) y si pasa por algún miembro de bond específico.
Broma #2: Desactivar todos los offloads para “hacerlo simple” es como quitar los asientos del coche para mejorar la aerodinámica. Técnicamente un cambio, emocionalmente satisfactorio, operativamente sospechoso.
Tres mini-historias del mundo corporativo
Mini-historia 1: El incidente causado por una suposición equivocada
Un equipo de plataforma heredó una flota de gateways Linux haciendo NAT para varios servicios internos. Una semana, los equipos empezaron a reportar “pérdida de paquetes aleatoria” que afectaba los flujos de inicio de sesión. Solo a veces. Principalmente en horas pico. El canal de incidentes se llenó de capturas de ping, como es tradición.
La suposición equivocada: “Si los pings muestran pérdida, debe ser la red.” El equipo escaló al grupo de red, que revisó errores en interfaces de switch y no encontró nada. Respondieron con el clásico: “Desde aquí se ve limpio.” La tensión aumentó. Alguien propuso un reinicio controlado de los gateways “para limpiar lo que sea”.
Un ingeniero más calmado revisó netstat -s y vio retransmisiones en aumento. Luego revisó contadores de conntrack y encontró la tabla cerca del límite. No siempre llena. Solo coqueteando con él. Bajo churn pico, las conexiones nuevas fallaban. Algunos clientes reintentaban con nuevos puertos de origen, añadiendo más churn. Un bucle de retroalimentación, pero solo en ciertos perfiles de carga.
El desenlace fue banal: el sistema había crecido y el dimensionamiento de conntrack no. Un plan de capacidad anterior asumió “conexiones pegadas”. No lo eran. Una actualización de un cliente móvil aumentó conexiones de corta duración. Nada “fallaba” en la red; el gateway estaba rechazando creación de estado y, en efecto, enrutando SYNs hacia un agujero negro.
La solución no fue heroica. Aumentaron conntrack max con margen de memoria, dejaron de rastrear tráfico que no necesitaba seguimiento y añadieron un dashboard que trazaba nf_conntrack_count vs nf_conntrack_max con alertas en > 80% sostenido.
Lección: la “pérdida de paquetes” intermitente puede ser un problema de agotamiento de estado. Si no revisas tablas del kernel compartidas pronto, perderás tiempo “depurando la red” mientras el servidor silenciosamente se niega a recordar nuevas conexiones.
Mini-historia 2: La optimización que salió mal
Un equipo ejecutaba un servicio sensible a latencia (no de alta frecuencia, pero con ingenieros discutiendo microsegundos como hobby). Querían reducir la carga de CPU en un nodo de ingestión ocupado. Alguien sugirió desactivar GRO/GSO/TSO para que el procesamiento de paquetes fuera “más predecible” y las capturas “más precisas”.
Hicieron el cambio en una ventana tranquila. El uso de CPU subió, pero aún dentro del presupuesto. Una semana después, el tráfico aumentó. De repente ese nodo empezó a mostrar timeouts intermitentes y retransmisiones. Los dashboards eran confusos: el throughput de red no cambió, pero la latencia en cola aumentó y los reintentos de cliente crecieron.
El modo de fallo fue clásico: al desactivar offloads aumentaron el coste por paquete en CPU. Bajo tasas de paquetes mayores, un único core manejando trabajo softirq se saturó. Los drops en /proc/net/softnet_stat subieron. Esos drops parecían “la red perdiendo paquetes”, pero era el host soltando carga porque no podía seguir el ritmo.
El equipo revirtió los cambios de offload y en su lugar resolvió el problema real: distribución de IRQ y dimensionado de colas RX, además de asegurar que RSS estaba configurado correctamente y mapeado a CPUs adecuadas. Las capturas siguieron siendo útiles capturando en los límites correctos y usando longitudes de snapshot apropiadas.
Lección: las “optimizaciones” de rendimiento que quitan funciones del kernel/NIC suelen trasladar el coste a la CPU y convertir throughput predecible en pérdida intermitente. Si cambias offloads, asume los efectos secundarios—especialmente en el siguiente salto de tráfico, no el de hoy.
Mini-historia 3: La práctica aburrida que salvó el día
Una compañía mediana tenía el hábito poco sexy pero muy útil: mantenían un runbook para triaje de incidentes de red que incluía “registra estos contadores antes y durante”. Listaba comandos exactos—ip -s link, ethtool -S, tc -s qdisc, softnet_stat y un filtro pequeño de tcpdump—y requería pegar las salidas en el ticket del incidente.
Un día, las solicitudes de clientes empezaron a hacer timeout, pero solo desde una AZ. Los ingenieros juraron que era un deploy porque el tiempo coincidía. El runbook les obligó a recoger contadores en un nodo afectado y en uno no afectado. La comparación fue decisiva: los nodos afectados mostraban un conteo creciente de errores RX “missed” en ethtool -S, mientras los no afectados no.
El equipo de red revisó estadísticas de puerto del switch para el rack afectado y encontró un patrón correspondiente de errores a nivel físico. No lo suficiente para hacer flap al enlace. Suficiente para arruinar tramas y provocar retransmisiones. La solución fue física: reemplazar ópticas y limpiar algunos patch panels. Se resolvió sin rollback y el postmortem tuvo una línea temporal clara basada en evidencia.
Lección: la recolección aburrida y consistente de contadores ahorra tiempo porque hace las comparaciones fáciles. El trabajo no es ser ingenioso; el trabajo es acertar rápidamente.
Errores comunes: síntoma → causa raíz → solución
1) “Ping muestra 5% de pérdida, los usuarios se quejan, así que la red está descartando paquetes”
Síntoma: pérdida en ping, pero las apps TCP están mayormente bien; RTT de ICMP irregular.
Causa raíz: ICMP está rate-limited o despriorizado en routers/firewalls; algunos dispositivos lo tratan como ruido.
Solución: valida con retransmisiones TCP (netstat -s, ss -ti) y métricas a nivel de aplicación; usa tcpdump dirigido para el protocolo real.
2) “No hay errores en la interfaz, así que no es físico”
Síntoma: retransmisiones suben; ip -s link parece limpio.
Causa raíz: problemas físicos pueden aparecer en contadores de switch, contadores FEC/PCS o estadísticas específicas del proveedor no visibles en contadores básicos.
Solución: usa ethtool -S y correlaciona con contadores del puerto del switch; busca flaps en logs.
3) “Aumentamos buffers, así que las pérdidas deberían desaparecer”
Síntoma: la pérdida disminuye, pero la latencia tail empeora; los usuarios siguen quejándose.
Causa raíz: bufferbloat: menos drops a costa de colas gigantes y alta latencia.
Solución: usa qdiscs sensatas (a menudo fq_codel), dimensiona bien los buffers y vigila p99 de latencia como métrica principal.
4) “Solo fallan las subidas grandes; las peticiones pequeñas van bien”
Síntoma: paquetes pequeños bien; transferencias grandes se estancan; retransmisiones suben.
Causa raíz: desajuste MTU/PMTUD blackhole, a menudo porque ICMP fragmentation-needed está bloqueado, especialmente con overlays.
Solución: valida path MTU con ping -M do; asegura MTU end-to-end correcta; permite ICMP necesarios; ajusta MTU del overlay.
5) “Los drops del NIC son cero, así que el host no puede estar descartando”
Síntoma: retransmisiones y timeouts; ethtool -S parece limpio.
Causa raíz: los drops ocurren en backlog del kernel (softnet_stat), qdisc (tc -s qdisc), netfilter o colas de socket.
Solución: revisa /proc/net/softnet_stat, estadísticas de tc y colas con ss; corrige distribución CPU/IRQ y límites de colas.
6) “Desactivamos offloads para depurar y ahora va peor”
Síntoma: aparecen drops nuevos bajo carga; sube la CPU; softirq alto.
Causa raíz: quitar offloads aumenta el coste por paquete en CPU y puede desencadenar drops en backlog.
Solución: revierte cambios de offload; depura usando capturas en límites; arregla escalado de interrupciones/colas en su lugar.
7) “Debe ser el firewall; añadimos reglas después”
Síntoma: fallos intermitentes de conexión bajo pico.
Causa raíz: saturación o churn en conntrack, además de reglas costosas que generan presión de CPU.
Solución: revisa uso de conntrack; reduce tráfico rastreado; ajusta timeouts; asegura que el procesamiento del firewall está dimensionado y observable.
8) “El bonding da redundancia, así que no puede causar pérdida”
Síntoma: pérdida intermitente solo para algunos flujos; un enlace miembro parece sospechoso.
Causa raíz: desequilibrio de miembros LACP, cable/óptica defectuosa en un miembro o hashing que fija ciertos flujos a un enlace degradado.
Solución: revisa estadísticas por miembro; drena/remueve temporalmente el miembro sospechoso; ajusta política de hashing donde proceda.
Listas de verificación / plan paso a paso
Checklist A: Durante el incidente (15–30 minutos)
- Define el síntoma en términos de protocolo. ¿Es pérdida ICMP, retransmisiones TCP, huecos UDP o timeouts de la aplicación?
- Fija el camino. Ejecuta
ip route getpara identificar interfaz de salida y siguiente salto. - Recoge contadores base ahora. Ejecuta:
ip -s link show dev <if>ethtool -S <if>tc -s qdisc show dev <if>awk ... /proc/net/softnet_statnetstat -soss -s
- Espera 60 segundos y recoge de nuevo. Los deltas importan más que los valores absolutos.
- Captura tráfico dirigido por una ventana corta. Snaplen pequeño, filtro estrecho, cuenta fija, guarda en disco.
- Correlaciona un síntoma con un contador. Si no puedes, aún no sabes dónde está la pérdida.
Checklist B: Si huele a presión CPU/softirq
- Revisa deltas en
/proc/net/softnet_statdurante el problema. - Revisa
mpstatpor%softalto en uno o pocos cores. - Revisa
/proc/interruptspor distribución sesgada de IRQs. - Revisa el número de colas RSS y si el driver expone múltiples colas.
- Sólo entonces considera tamaños de ring, offloads y tuning. Evita cambios aleatorios en sysctl.
Checklist C: Si huele a MTU / overlays
- Confirma MTU de interfaces:
ip link show. - Valida tamaños de payload con
ping -M doen ambos extremos. - Comprueba si ICMP está filtrado en tu entorno (a los equipos de seguridad les encanta hacer esto “por seguridad”).
- Confirma ajustes de MTU del overlay (VXLAN/Geneve) y asegura que el underlay los soporta.
- Ajusta MTU de forma consistente; no confíes en fragmentación en producción moderna a menos que te gusten las sorpresas.
Checklist D: Si huele a tablas de estado (conntrack) o políticas
- Revisa uso de conntrack vía sysctls y obsérvalo en picos.
- Inspecciona contadores del firewall (nftables/iptables) si están disponibles; los paquetes descartados con reglas coincidentes no son “misteriosos”.
- Reduce tráfico rastreado cuando sea seguro (ej., no todo el tráfico necesita estado).
- Dimensiona correctamente la tabla con margen de memoria y alertas.
Preguntas frecuentes
1) Si ping muestra pérdida pero TCP está bien, ¿es pérdida “real”?
Puede ser pérdida real de ICMP, que suele ser irrelevante para el rendimiento de la aplicación. Muchos dispositivos limitan ICMP. Valida con retransmisiones TCP y métricas de la app.
2) ¿Cuál es el archivo Linux más útil para “drops bajo carga”?
/proc/net/softnet_stat. Si la columna de drops sube durante el incidente, tienes drops en backlog del kernel. Eso suele apuntar a presión de CPU/interrupciones/tasa de paquetes.
3) ¿Por qué los promedios mienten tanto en pérdida intermitente?
Porque las pérdidas suelen ocurrir en microbursts. Una ráfaga de 200 ms puede desbordar una cola y causar pérdida visible, mientras tu promedio de 1 minuto parece normal.
4) ¿Debo desactivar GRO/TSO/GSO para que tcpdump sea “preciso”?
No como primer paso. Los offloads reducen la carga de CPU. Desactivarlos puede crear pérdida al saturar softirq. Si debes probarlo, hazlo temporalmente, captura antes/después y vigila drops en softnet y CPU.
5) ¿Cómo distingo si las pérdidas son en ingreso o en salida?
Ingreso: aumento de misses/no-buffer RX, drops en softnet o problemas en recepción de sockets. Salida: drops en tc -s qdisc, problemas de cola TX o shaping/policing. Capturas en ambos lados de un límite lo dejan claro.
6) ¿Por qué un desajuste de MTU parece “solo a veces”?
Porque no todos los paquetes son grandes. Las peticiones pequeñas funcionan; las respuestas grandes o uploads se estancan. Si PMTUD está roto (a menudo por ICMP filtrado), la conexión puede colgar y retransmitir hasta el timeout.
7) ¿Conntrack realmente puede parecer pérdida de paquetes?
Sí. Cuando conntrack está lleno o muy contendido, los flujos nuevos pueden fallar. Los clientes ven timeouts y reintentos, y es fácil etiquetarlo como “paquetes que desaparecen”.
8) ¿Qué pasa si tcpdump dice “packets dropped by kernel” durante la captura?
Tu captura no sigue el ritmo, lo cual es habitual en enlaces ocupados. Estrecha el filtro, reduce snaplen, captura menos paquetes o captura en un punto menos concurrido. No uses una captura con pérdidas para demostrar microbursts.
9) ¿Un ip -s link limpio significa que la NIC está bien?
No necesariamente. Muchos contadores importantes solo están en ethtool -S, y errores a nivel físico pueden ser más visibles en el lado del switch.
10) ¿Cómo evito culparse entre equipos sin fin?
Acordad límites y evidencia: “paquete visto aquí, no visto allí”, además de contadores que aumentan. Capturas en dos puntos vencen opiniones siempre.
Conclusión: siguientes pasos que funcionan
La pérdida de paquetes intermitente deja de ser mística cuando dejas de tratarla como una sensación y empiezas a tratarla como un desbordamiento de cola o una falla de camino condicional. La jugada ganadora es localizar el límite de caída usando deltas en contadores y capturas pequeñas y dirigidas.
Haz esto a continuación, en orden:
- En un host afectado, registra deltas de
netstat -s,ip -s link,ethtool -S,tc -s qdiscy/proc/net/softnet_staten una ventana de 1–5 minutos. - Si las pérdidas son locales, decide qué dominio las posee: ring del NIC, backlog softirq, qdisc, conntrack o presión de socket.
- Si las pérdidas no son locales, captura en ambos extremos (o en ambos lados de un límite) y fuerza que la conversación trate sobre evidencia.
- Escribe el runbook que desearías haber tenido hoy, mientras el dolor está fresco. Mantenlo corto. Requiere salidas en los tickets.
El mejor flujo de depuración es el que puedes ejecutar cuando estás cansado, bajo presión y con tres personas discutiendo en tu oído. Construye ese flujo, y la pérdida intermitente se convierte en un martes más.